From 42d6d593475112e479688e9cac60a4ba7264dce3 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 5 Jan 2024 10:58:56 +0100 Subject: [PATCH 01/55] Add staking proxy (In progress) --- .../NominationPoolsStakingNavigator.kt | 4 + .../parachain/ParachainStakingNavigator.kt | 4 + .../relaychain/RelayStakingNavigator.kt | 8 +- .../res/navigation/staking_main_graph.xml | 18 +- .../nova/common/view/TableCellView.kt | 4 +- .../nova/common/view/YourWalletsView.kt | 47 +++++ .../src/main/res/layout/view_your_wallets.xml | 38 ++++ common/src/main/res/values/attrs.xml | 1 + common/src/main/res/values/strings.xml | 8 + .../data/repository/ProxyRepository.kt | 2 + .../di/AccountFeatureApi.kt | 3 + .../domain/proxy/AddProxyInteractor.kt | 17 ++ .../bindings/calls/ExtrinsicBuilderExt.kt | 22 +++ .../data/repository/RealProxyRepository.kt | 20 ++- .../di/AccountFeatureModule.kt | 17 ++ .../domain/proxy/RealAddProxyInteractor.kt | 46 +++++ .../proxy/common/ProxyDepositCalculator.kt | 38 ++++ .../proxy/AddProxyValidationSystem.kt | 54 ++++++ .../send/TransferAssetValidationFailureUi.kt | 2 +- .../send/amount/SelectSendFragment.kt | 1 - .../main/res/layout/fragment_select_send.xml | 43 +---- .../fragment_revoke_delegation_confirm.xml | 2 +- .../di/StakingFeatureComponent.kt | 9 +- .../di/StakingFeatureDependencies.kt | 6 + .../di/StakingFeatureHolder.kt | 3 + .../di/StakingFeatureModule.kt | 2 +- .../SetControllerValidationsModule.kt | 8 +- .../controller/ControllerInteractor.kt | 2 +- .../proxy/SetStakingProxyInteractor.kt | 10 ++ .../validations/NotZeroBalanceValidation.kt | 4 +- .../ChangeStackingValidationSystem.kt | 2 +- .../controller/Declarations.kt | 2 +- .../SetControllerValidationFailure.kt | 2 +- .../SetControllerValidationPayload.kt | 2 +- .../validations/main/ValidationSystems.kt | 2 + .../current/CurrentValidatorsInteractor.kt | 4 +- .../presentation/NominationPoolsRouter.kt | 2 + .../presentation/ParachainStakingRouter.kt | 2 + .../presentation/StakingRouter.kt | 4 +- .../confirm/ConfirmSetControllerFragment.kt | 2 +- .../confirm/ConfirmSetControllerPayload.kt | 2 +- .../confirm/ConfirmSetControllerViewModel.kt | 10 +- .../di/ConfirmSetControllerComponent.kt | 6 +- .../confirm/di/ConfirmSetControllerModule.kt | 10 +- .../controller/set/SetControllerFragment.kt | 2 +- .../controller/set/SetControllerViewModel.kt | 10 +- .../set/ValidationFailureMessage.kt | 4 +- .../set/di/SetControllerComponent.kt | 4 +- .../controller/set/di/SetControllerModule.kt | 8 +- .../proxy/set/SetStakingProxyFragment.kt | 79 +++++++++ .../proxy/set/SetStakingProxyViewModel.kt | 163 ++++++++++++++++++ .../proxy/set/di/SetStakingProxyComponent.kt | 24 +++ .../proxy/set/di/SetStakingProxyModule.kt | 75 ++++++++ .../stakeActions/ManageStakeAction.kt | 18 ++ .../NominationPoolsStakeActionsComponent.kt | 20 ++- .../ParachainStakeActionsComponent.kt | 10 ++ .../RelaychainStakeActionsComponent.kt | 13 +- .../ChangeStakingValidationFailureUI.kt | 2 +- .../current/CurrentValidatorsViewModel.kt | 2 +- .../res/layout/fragment_set_staking_proxy.xml | 97 +++++++++++ .../assets/transfers/validations/Common.kt | 11 +- 61 files changed, 925 insertions(+), 112 deletions(-) create mode 100644 common/src/main/java/io/novafoundation/nova/common/view/YourWalletsView.kt create mode 100644 common/src/main/res/layout/view_your_wallets.xml create mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/proxy/AddProxyInteractor.kt create mode 100644 feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/network/blockchain/bindings/calls/ExtrinsicBuilderExt.kt create mode 100644 feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/RealAddProxyInteractor.kt create mode 100644 feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/common/ProxyDepositCalculator.kt create mode 100644 feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/validation/proxy/AddProxyValidationSystem.kt rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/{ => delegation}/controller/ControllerInteractor.kt (99%) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/SetStakingProxyInteractor.kt rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/{ => delegation}/controller/ChangeStackingValidationSystem.kt (98%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/{ => delegation}/controller/Declarations.kt (96%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/{ => delegation}/controller/SetControllerValidationFailure.kt (86%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/{ => delegation}/controller/SetControllerValidationPayload.kt (92%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/confirm/ConfirmSetControllerFragment.kt (98%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/confirm/ConfirmSetControllerPayload.kt (91%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/confirm/ConfirmSetControllerViewModel.kt (94%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/confirm/di/ConfirmSetControllerComponent.kt (81%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/confirm/di/ConfirmSetControllerModule.kt (91%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/set/SetControllerFragment.kt (99%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/set/SetControllerViewModel.kt (98%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/set/ValidationFailureMessage.kt (92%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/set/di/SetControllerComponent.kt (86%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/{ => delegation}/controller/set/di/SetControllerModule.kt (94%) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyFragment.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyComponent.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt create mode 100644 feature-staking-impl/src/main/res/layout/fragment_set_staking_proxy.xml diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/nominationPools/NominationPoolsStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/nominationPools/NominationPoolsStakingNavigator.kt index 43cd6f6fb3..bc2be82d0b 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/nominationPools/NominationPoolsStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/nominationPools/NominationPoolsStakingNavigator.kt @@ -38,4 +38,8 @@ class NominationPoolsStakingNavigator( override fun returnToMain() { commonNavigator.returnToMain() } + + override fun openSetStakingProxy() { + performNavigation(R.id.action_open_setStakingProxyFragment) + } } diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/parachain/ParachainStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/parachain/ParachainStakingNavigator.kt index cf99622a45..3f7b041d5c 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/parachain/ParachainStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/parachain/ParachainStakingNavigator.kt @@ -72,4 +72,8 @@ class ParachainStakingNavigator( actionId = R.id.action_setupYieldBoostFragment_to_yieldBoostConfirmFragment, args = YieldBoostConfirmFragment.getBundle(payload) ) + + override fun openSetStakingProxy() { + performNavigation(R.id.action_open_setStakingProxyFragment) + } } diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt index 2c797cef2e..6b341cf1fa 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt @@ -19,8 +19,8 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.con import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.confirm.ConfirmBondMorePayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.select.SelectBondMoreFragment import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.select.SelectBondMorePayload -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.ConfirmSetControllerFragment -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.ConfirmSetControllerPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.model.StakingStoryModel import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondFragment import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondPayload @@ -222,4 +222,8 @@ class RelayStakingNavigator( returnToStakingMain() } } + + override fun openSetStakingProxy() { + performNavigation(R.id.action_open_setStakingProxyFragment) + } } diff --git a/app/src/main/res/navigation/staking_main_graph.xml b/app/src/main/res/navigation/staking_main_graph.xml index e30a403d20..3fba927f41 100644 --- a/app/src/main/res/navigation/staking_main_graph.xml +++ b/app/src/main/res/navigation/staking_main_graph.xml @@ -29,6 +29,19 @@ app:popEnterAnim="@anim/fragment_close_enter" app:popExitAnim="@anim/fragment_close_exit" /> + + + + @@ -303,7 +316,7 @@ @@ -335,6 +348,7 @@ android:name="io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.confirm.ConfirmBondMoreFragment" android:label="ConfirmBondMoreFragment" tools:layout="@layout/fragment_confirm_bond_more" /> + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values/attrs.xml b/common/src/main/res/values/attrs.xml index 52f0ac9382..b1d8a0dc05 100644 --- a/common/src/main/res/values/attrs.xml +++ b/common/src/main/res/values/attrs.xml @@ -89,6 +89,7 @@ + diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 0d0d507f90..3935c3bef2 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,6 +1,14 @@ + Your delegations + Add delegated authority (Proxy) + + Give authority to + Proxy deposit + Add delegation for %s staking + + Enter address… Delegated account %s doesn’t have enough balance to pay the network fee of %s. Available balance to pay fee: %s Not enough tokens to pay the fee diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/ProxyRepository.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/ProxyRepository.kt index 75a614bb0a..dbdb00d692 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/ProxyRepository.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/ProxyRepository.kt @@ -11,4 +11,6 @@ interface ProxyRepository { suspend fun getAllProxiesForMetaAccounts(chainId: ChainId, metaAccountIds: List): List suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List + + suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int } diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt index 72ca04deb9..63b47f2f2c 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt @@ -18,6 +18,7 @@ import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase +import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor import io.novafoundation.nova.feature_account_api.domain.updaters.AccountUpdateScope import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase import io.novafoundation.nova.feature_account_api.presenatation.account.polkadotVault.config.PolkadotVaultVariantConfigProvider @@ -81,6 +82,8 @@ interface AccountFeatureApi { fun ledgerAddAccountRepository(): LedgerAddAccountRepository + fun addProxyInteractor(): AddProxyInteractor + val evmTransactionService: EvmTransactionService val identityMixinFactory: IdentityMixin.Factory diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/proxy/AddProxyInteractor.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/proxy/AddProxyInteractor.kt new file mode 100644 index 0000000000..493d4f5f0f --- /dev/null +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/proxy/AddProxyInteractor.kt @@ -0,0 +1,17 @@ +package io.novafoundation.nova.feature_account_api.domain.proxy + +import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission +import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import java.math.BigInteger +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +interface AddProxyInteractor { + + suspend fun estimateFee(chain: Chain, accountId: AccountId, proxyType: ProxyAccount.ProxyType): Fee + + suspend fun addProxy(chain: Chain, accountId: AccountId, proxyType: ProxyAccount.ProxyType): Result + + suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): BigInteger +} diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/network/blockchain/bindings/calls/ExtrinsicBuilderExt.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/network/blockchain/bindings/calls/ExtrinsicBuilderExt.kt new file mode 100644 index 0000000000..a12adc00b7 --- /dev/null +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/network/blockchain/bindings/calls/ExtrinsicBuilderExt.kt @@ -0,0 +1,22 @@ +package io.novafoundation.nova.feature_account_impl.data.network.blockchain.bindings.calls + +import io.novafoundation.nova.common.utils.Modules +import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount +import java.math.BigInteger +import jp.co.soramitsu.fearless_utils.runtime.AccountId +import jp.co.soramitsu.fearless_utils.runtime.definitions.types.composite.DictEnum +import jp.co.soramitsu.fearless_utils.runtime.definitions.types.instances.AddressInstanceConstructor +import jp.co.soramitsu.fearless_utils.runtime.extrinsic.ExtrinsicBuilder + + +fun ExtrinsicBuilder.addProxyCall(proxyAccountId: AccountId, proxyType: ProxyAccount.ProxyType): ExtrinsicBuilder { + return call( + Modules.PROXY, + "add_proxy", + mapOf( + "delegate" to AddressInstanceConstructor.constructInstance(runtime.typeRegistry, proxyAccountId), + "proxy_type" to DictEnum.Entry(proxyType.name, null), + "delay" to BigInteger.ZERO + ) + ) +} diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/RealProxyRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/RealProxyRepository.kt index e7d1886d74..4641aa9eb7 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/RealProxyRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/RealProxyRepository.kt @@ -50,19 +50,29 @@ class RealProxyRepository( } override suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List { - val proxies = remoteSource.query(chainId) { + val proxies = getAllProxiesFor(chainId, proxiedAccountId) + + return proxies.filter { it.accountId == proxyAccountId.intoKey() } + .map { mapProxyTypeToString(it.proxyType) } + } + + override suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int { + val proxies = getAllProxiesFor(chainId, proxiedAccountId) + + return proxies.size + } + + private suspend fun getAllProxiesFor(chainId: ChainId, accountId: AccountId): List { + return remoteSource.query(chainId) { runtime.metadata.module(Modules.PROXY) .storage("Proxies") .query( - keyArguments = arrayOf(proxiedAccountId), + keyArguments = arrayOf(accountId), binding = { result -> bindProxyAccounts(result) } ) } - - return proxies.filter { it.accountId == proxyAccountId.intoKey() } - .map { mapProxyTypeToString(it.proxyType) } } private suspend fun receiveAllProxies(chainId: ChainId): Map> { diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt index 4600ff7711..503f242aec 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt @@ -75,6 +75,7 @@ import io.novafoundation.nova.feature_account_impl.domain.account.advancedEncryp import io.novafoundation.nova.feature_account_api.domain.account.common.EncryptionDefaults import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.account.identity.OnChainIdentity +import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor import io.novafoundation.nova.feature_account_impl.data.proxy.RealMetaAccountsUpdatesRegistry import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.proxied.ProxiedAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.JsonAddAccountRepository @@ -82,6 +83,8 @@ import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.se import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.SeedAddAccountRepository import io.novafoundation.nova.feature_account_impl.di.modules.ProxySigningModule import io.novafoundation.nova.feature_account_impl.domain.account.details.WalletDetailsInteractor +import io.novafoundation.nova.feature_account_impl.domain.proxy.RealAddProxyInteractor +import io.novafoundation.nova.feature_account_impl.domain.proxy.common.ProxyDepositCalculator import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.DelegatedMetaAccountUpdatesListingMixinFactory import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountTypePresentationMapper @@ -506,4 +509,18 @@ class AccountFeatureModule { fun provideSigningNotSupportedPresentable( contextManager: ContextManager ): SigningNotSupportedPresentable = RealSigningNotSupportedPresentable(contextManager) + + @Provides + @FeatureScope + fun provideProxyDepositCalculator( + chainRegistry: ChainRegistry + ) = ProxyDepositCalculator(chainRegistry) + + @Provides + @FeatureScope + fun provideAddProxyInteractor( + extrinsicService: ExtrinsicService, + proxyRepository: ProxyRepository, + proxyDepositCalculator: ProxyDepositCalculator + ): AddProxyInteractor = RealAddProxyInteractor(extrinsicService, proxyDepositCalculator, proxyRepository) } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/RealAddProxyInteractor.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/RealAddProxyInteractor.kt new file mode 100644 index 0000000000..033c7f68fc --- /dev/null +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/RealAddProxyInteractor.kt @@ -0,0 +1,46 @@ +package io.novafoundation.nova.feature_account_impl.domain.proxy + +import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.intoOrigin +import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService +import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission +import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_account_api.data.repository.ProxyRepository +import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount +import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor +import io.novafoundation.nova.feature_account_impl.data.network.blockchain.bindings.calls.addProxyCall +import io.novafoundation.nova.feature_account_impl.domain.proxy.common.ProxyDepositCalculator +import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import jp.co.soramitsu.fearless_utils.runtime.AccountId +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class RealAddProxyInteractor( + private val extrinsicService: ExtrinsicService, + private val proxyDepositCalculator: ProxyDepositCalculator, + private val proxyRepository: ProxyRepository +) : AddProxyInteractor { + + override suspend fun estimateFee(chain: Chain, accountId: AccountId, proxyType: ProxyAccount.ProxyType): Fee { + return withContext(Dispatchers.IO) { + extrinsicService.estimateFee(chain, accountId.intoOrigin()) { + addProxyCall(accountId, proxyType) + } + } + } + + override suspend fun addProxy(chain: Chain, accountId: AccountId, proxyType: ProxyAccount.ProxyType): Result { + return withContext(Dispatchers.IO) { + + extrinsicService.submitExtrinsic(chain, accountId.intoOrigin()) { + addProxyCall(accountId, proxyType) + } + } + } + + override suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): Balance { + val depositConstants = proxyDepositCalculator.getDepositConstants(chain) + val currentProxiesCount = proxyRepository.getProxiesQuantity(chain.id, accountId) + return proxyDepositCalculator.calculateProxyDeposit(depositConstants, currentProxiesCount + 1) + } +} diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/common/ProxyDepositCalculator.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/common/ProxyDepositCalculator.kt new file mode 100644 index 0000000000..4c9bf72394 --- /dev/null +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/common/ProxyDepositCalculator.kt @@ -0,0 +1,38 @@ +package io.novafoundation.nova.feature_account_impl.domain.proxy.common + +import io.novafoundation.nova.common.utils.numberConstant +import io.novafoundation.nova.common.utils.proxy +import io.novafoundation.nova.feature_account_api.data.repository.ProxyRepository +import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance +import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import io.novafoundation.nova.runtime.multiNetwork.getRuntime +import java.math.BigInteger +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +class DepositBaseAndFactor( + val baseAmount: Balance, + val factorAmount: Balance +) + +class ProxyDepositCalculator( + private val chainRegestry: ChainRegistry +) { + + suspend fun getDepositConstants(chain: Chain): DepositBaseAndFactor { + val runtime = chainRegestry.getRuntime(chain.id) + val constantQuery = runtime.metadata.proxy() + return DepositBaseAndFactor( + baseAmount = constantQuery.numberConstant("ProxyDepositBase", runtime), + factorAmount = constantQuery.numberConstant("ProxyDepositFactor", runtime) + ) + } + + fun calculateProxyDeposit(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): Balance { + return if (proxiesCount == 0) { + Balance.ZERO + } else { + baseAndFactor.baseAmount + baseAndFactor.factorAmount * proxiesCount.toBigInteger() + } + } +} diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/validation/proxy/AddProxyValidationSystem.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/validation/proxy/AddProxyValidationSystem.kt new file mode 100644 index 0000000000..ce848bb24f --- /dev/null +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/validation/proxy/AddProxyValidationSystem.kt @@ -0,0 +1,54 @@ +package io.novafoundation.nova.feature_account_impl.domain.validation.proxy + +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.validation.NotEnoughToPayFeesError + +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy + +import io.novafoundation.nova.common.validation.ValidationSystem +import io.novafoundation.nova.common.validation.ValidationSystemBuilder +import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import java.math.BigDecimal + +class AddProxyValidationPayload( + val chain: Chain, + val asset: Asset, + val address: String, + val fee: Fee, + val deposit: Balance +) + +sealed class AddProxyValidationFailure { + + class NotEnoughToPayFee( + override val chainAsset: Chain.Asset, + override val maxUsable: BigDecimal, + override val fee: BigDecimal + ) : AddProxyValidationFailure(), NotEnoughToPayFeesError + + class NotEnoughBalanceToReserveDeposit( + val chainAsset: Chain.Asset, + val maxUsable: Balance, + val deposit: Balance + ) : AddProxyValidationFailure() + + class InvalidAddress(val chain: Chain) : AddProxyValidationFailure() + +} + +typealias AddProxyValidationSystem = ValidationSystem +typealias AddProxyValidationSystemBuilder = ValidationSystemBuilder + +fun AddProxyValidationSystemBuilder.controllerAccountAccess(accountRepository: AccountRepository, stakingSharedState: StakingSharedState) { + return validate( + ControllerRequiredValidation( + accountRepository = accountRepository, + accountAddressExtractor = { it.controllerAddress }, + sharedState = stakingSharedState, + errorProducer = { ChangeStackingValidationFailure.NO_ACCESS_TO_CONTROLLER_ACCOUNT } + ) + ) +} diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/TransferAssetValidationFailureUi.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/TransferAssetValidationFailureUi.kt index 24d4208e10..ce17b8fc56 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/TransferAssetValidationFailureUi.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/TransferAssetValidationFailureUi.kt @@ -6,7 +6,7 @@ import io.novafoundation.nova.common.validation.TransformedFailure.Default import io.novafoundation.nova.common.validation.ValidationFlowActions import io.novafoundation.nova.common.validation.ValidationStatus import io.novafoundation.nova.common.validation.asDefault -import io.novafoundation.nova.feature_account_api.domain.validation.handleSystemAccountValidationFailure +import io.novafoundation.nova.feature_account_api.domain.validation.proxy.handleSystemAccountValidationFailure import io.novafoundation.nova.feature_assets.R import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.AssetTransferPayload import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.AssetTransferValidationFailure diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendFragment.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendFragment.kt index 2411ad0874..6138ef9bb3 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendFragment.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendFragment.kt @@ -64,7 +64,6 @@ class SelectSendFragment : BaseFragment() { selectSendOriginChain.setOnClickListener { viewModel.originChainClicked() } selectSendDestinationChain.setOnClickListener { viewModel.destinationChainClicked() } - selectWallet.background = getRoundedCornerDrawable(cornerSizeDp = 8).withRippleMask(getRippleMask(cornerSizeDp = 8)) selectWallet.setOnClickListener { viewModel.selectRecipientWallet() } selectSendCrossChainFee.makeGone() // gone inititally diff --git a/feature-assets/src/main/res/layout/fragment_select_send.xml b/feature-assets/src/main/res/layout/fragment_select_send.xml index 9cad5f1582..b64d19866e 100644 --- a/feature-assets/src/main/res/layout/fragment_select_send.xml +++ b/feature-assets/src/main/res/layout/fragment_select_send.xml @@ -69,7 +69,7 @@ android:clipChildren="false" android:minHeight="24dp" android:paddingStart="16dp" - android:paddingEnd="12dp"> + android:paddingEnd="16dp"> - - - - - - - - - + android:layout_gravity="end|center_vertical"/> @@ -129,7 +94,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" - android:layout_marginTop="4dp" + android:layout_marginTop="8dp" android:layout_marginEnd="16dp" android:hint="@string/send_address_hint" app:hasExternalAccountIdentifiers="true" /> diff --git a/feature-governance-impl/src/main/res/layout/fragment_revoke_delegation_confirm.xml b/feature-governance-impl/src/main/res/layout/fragment_revoke_delegation_confirm.xml index 67471e3471..923396aaea 100644 --- a/feature-governance-impl/src/main/res/layout/fragment_revoke_delegation_confirm.xml +++ b/feature-governance-impl/src/main/res/layout/fragment_revoke_delegation_confirm.xml @@ -83,7 +83,7 @@ app:title="@string/delegation_undelegating_period" app:titleEllipsisable="true" app:titleIconStart="@drawable/ic_time_16" - app:titleIconTint="@color/icon_secondary" /> + app:titleIconStartTint="@color/icon_secondary" /> 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 13bae0259c..c1d6127984 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 @@ -6,6 +6,7 @@ import io.novafoundation.nova.common.di.CommonApi import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.core_db.di.DbApi import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator import io.novafoundation.nova.feature_dapp_api.di.DAppFeatureApi import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState @@ -56,8 +57,9 @@ import io.novafoundation.nova.feature_staking_impl.presentation.pools.searchPool import io.novafoundation.nova.feature_staking_impl.presentation.pools.selectPool.di.SelectPoolComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.confirm.di.ConfirmBondMoreComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.select.di.SelectBondMoreComponent -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.di.ConfirmSetControllerComponent -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.set.di.SetControllerComponent +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.di.ConfirmSetControllerComponent +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.di.SetControllerComponent +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.di.SetStakingProxyComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.di.StakingComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.di.ConfirmRebondComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.custom.di.CustomRebondComponent @@ -165,6 +167,8 @@ interface StakingFeatureComponent : StakingFeatureApi { fun setControllerFactory(): SetControllerComponent.Factory + fun setStakingProxyFactory(): SetStakingProxyComponent.Factory + fun confirmSetControllerFactory(): ConfirmSetControllerComponent.Factory fun rebondCustomFactory(): CustomRebondComponent.Factory @@ -226,6 +230,7 @@ interface StakingFeatureComponent : StakingFeatureApi { @BindsInstance parachainStaking: ParachainStakingRouter, @BindsInstance selectCollatorInterScreenCommunicator: SelectCollatorInterScreenCommunicator, @BindsInstance selectCollatorSettingsInterScreenCommunicator: SelectCollatorSettingsInterScreenCommunicator, + @BindsInstance selectAddressCommunicator: SelectAddressCommunicator, @BindsInstance nominationPoolsRouter: NominationPoolsRouter, diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt index 8703881f96..9d9249d9c9 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt @@ -26,10 +26,12 @@ import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicServic import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase +import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor import io.novafoundation.nova.feature_account_api.domain.updaters.AccountUpdateScope import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_account_api.presenatation.mixin.identity.IdentityMixin import io.novafoundation.nova.feature_dapp_api.data.repository.DAppMetadataRepository import io.novafoundation.nova.feature_wallet_api.data.cache.AssetCache @@ -123,6 +125,10 @@ interface StakingFeatureDependencies { fun enoughTotalToStayAboveEDValidationFactory(): EnoughTotalToStayAboveEDValidationFactory + fun addressInputMixinFactory(): AddressInputMixinFactory + + fun addProxyInteractor(): AddProxyInteractor + val amountChooserMixinFactory: AmountChooserMixin.Factory val actionAwaitableMixinFactory: ActionAwaitableMixin.Factory 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 ef40639987..8955fd4df6 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 @@ -5,6 +5,7 @@ import io.novafoundation.nova.common.di.FeatureContainer import io.novafoundation.nova.common.di.scope.ApplicationScope import io.novafoundation.nova.core_db.di.DbApi import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator import io.novafoundation.nova.feature_dapp_api.di.DAppFeatureApi import io.novafoundation.nova.feature_staking_impl.presentation.NominationPoolsRouter import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter @@ -25,6 +26,7 @@ class StakingFeatureHolder @Inject constructor( private val nominationPoolsRouter: NominationPoolsRouter, private val startMultiStakingRouter: StartMultiStakingRouter, private val stakingDashboardRouter: StakingDashboardRouter, + private val selectAddressCommunicator: SelectAddressCommunicator, private val selectCollatorInterScreenCommunicator: SelectCollatorInterScreenCommunicator, private val selectCollatorSettingsInterScreenCommunicator: SelectCollatorSettingsInterScreenCommunicator, ) : FeatureApiHolder(featureContainer) { @@ -45,6 +47,7 @@ class StakingFeatureHolder @Inject constructor( parachainStaking = parachainStakingRouter, selectCollatorInterScreenCommunicator = selectCollatorInterScreenCommunicator, selectCollatorSettingsInterScreenCommunicator = selectCollatorSettingsInterScreenCommunicator, + selectAddressCommunicator = selectAddressCommunicator, nominationPoolsRouter = nominationPoolsRouter, startMultiStakingRouter = startMultiStakingRouter, stakingDashboardRouter = stakingDashboardRouter, diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt index d768208a63..fc1bddb0b8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt @@ -74,7 +74,7 @@ import io.novafoundation.nova.feature_staking_impl.domain.recommendations.settin import io.novafoundation.nova.feature_staking_impl.domain.rewards.RewardCalculatorFactory import io.novafoundation.nova.feature_staking_impl.domain.setup.ChangeValidatorsInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.bond.BondMoreInteractor -import io.novafoundation.nova.feature_staking_impl.domain.staking.controller.ControllerInteractor +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.rebond.RebondInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.redeem.RedeemInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.rewardDestination.ChangeRewardDestinationInteractor diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/SetControllerValidationsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/SetControllerValidationsModule.kt index cab15bab83..6ebd5a50fb 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/SetControllerValidationsModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/SetControllerValidationsModule.kt @@ -7,10 +7,10 @@ import io.novafoundation.nova.common.validation.CompositeValidation import io.novafoundation.nova.feature_staking_api.domain.api.StakingRepository import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState import io.novafoundation.nova.feature_staking_impl.domain.validations.NotZeroBalanceValidation -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.IsNotControllerAccountValidation -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerFeeValidation -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationFailure -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.IsNotControllerAccountValidation +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerFeeValidation +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationFailure +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationSystem import io.novafoundation.nova.feature_wallet_api.domain.interfaces.WalletRepository import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughAmountToTransferValidation diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/controller/ControllerInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/controller/ControllerInteractor.kt similarity index 99% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/controller/ControllerInteractor.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/controller/ControllerInteractor.kt index 690a2e0e0c..85d5f3b5fb 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/controller/ControllerInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/controller/ControllerInteractor.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.domain.staking.controller +package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.intoOrigin import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/SetStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/SetStakingProxyInteractor.kt new file mode 100644 index 0000000000..cf2faa64af --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/SetStakingProxyInteractor.kt @@ -0,0 +1,10 @@ +package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy + +import io.novafoundation.nova.common.validation.ValidationSystem + +class SetStakingProxyInteractor { + + fun validationSystem(): ValidationSystem<> { + + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/NotZeroBalanceValidation.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/NotZeroBalanceValidation.kt index d0825b2dfe..ef2695d923 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/NotZeroBalanceValidation.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/NotZeroBalanceValidation.kt @@ -4,8 +4,8 @@ import io.novafoundation.nova.common.validation.DefaultFailureLevel import io.novafoundation.nova.common.validation.Validation import io.novafoundation.nova.common.validation.ValidationStatus import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationFailure -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationPayload +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationFailure +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationPayload import io.novafoundation.nova.feature_wallet_api.domain.interfaces.WalletRepository import io.novafoundation.nova.runtime.ext.accountIdOf import io.novafoundation.nova.runtime.state.chain diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/ChangeStackingValidationSystem.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/ChangeStackingValidationSystem.kt similarity index 98% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/ChangeStackingValidationSystem.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/ChangeStackingValidationSystem.kt index 2407497729..1aa56e3387 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/ChangeStackingValidationSystem.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/ChangeStackingValidationSystem.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.domain.validations.controller +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller import io.novafoundation.nova.common.validation.ValidationSystem import io.novafoundation.nova.common.validation.ValidationSystemBuilder diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/Declarations.kt similarity index 96% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/Declarations.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/Declarations.kt index 0227cae53d..d633bc5434 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/Declarations.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.domain.validations.controller +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller import io.novafoundation.nova.common.validation.ValidationSystem import io.novafoundation.nova.feature_staking_impl.domain.validations.AccountIsNotControllerValidation diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/SetControllerValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/SetControllerValidationFailure.kt similarity index 86% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/SetControllerValidationFailure.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/SetControllerValidationFailure.kt index d3d51dd29e..98e784933e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/SetControllerValidationFailure.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/SetControllerValidationFailure.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.domain.validations.controller +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller enum class SetControllerValidationFailure { NOT_ENOUGH_TO_PAY_FEES, ALREADY_CONTROLLER, ZERO_CONTROLLER_BALANCE diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/SetControllerValidationPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/SetControllerValidationPayload.kt similarity index 92% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/SetControllerValidationPayload.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/SetControllerValidationPayload.kt index 4d35cf660c..c0b3046448 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/controller/SetControllerValidationPayload.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/controller/SetControllerValidationPayload.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.domain.validations.controller +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller import io.novafoundation.nova.feature_wallet_api.presentation.model.DecimalFee import java.math.BigDecimal diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/ValidationSystems.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/ValidationSystems.kt index a5ce0048e5..077adc17c2 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/ValidationSystems.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/ValidationSystems.kt @@ -11,5 +11,7 @@ const val SYSTEM_MANAGE_PAYOUTS = "ManageStakingPayouts" const val SYSTEM_MANAGE_VALIDATORS = "ManageStakingValidators" const val SYSTEM_MANAGE_CONTROLLER = "ManageStakingController" const val SYSTEM_MANAGE_STAKING_REBAG = "ManageStakingRebag" +const val SYSTEM_ADD_PROXY = "AddStakingProxy" +const val SYSTEM_MANAGE_PROXIES = "ManageStakingProxies" typealias StakeActionsValidationSystem = ValidationSystem diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validators/current/CurrentValidatorsInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validators/current/CurrentValidatorsInteractor.kt index 558a328eac..cb6d0f08e1 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validators/current/CurrentValidatorsInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validators/current/CurrentValidatorsInteractor.kt @@ -14,8 +14,8 @@ import io.novafoundation.nova.feature_staking_impl.data.repository.StakingConsta import io.novafoundation.nova.feature_staking_impl.domain.common.StakingSharedComputation import io.novafoundation.nova.feature_staking_impl.domain.common.electedExposuresInActiveEra import io.novafoundation.nova.feature_staking_impl.domain.common.isWaiting -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.ChangeStackingValidationSystem -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.controllerAccountAccess +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.ChangeStackingValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.controllerAccountAccess import io.novafoundation.nova.feature_staking_impl.domain.validators.ValidatorProvider import io.novafoundation.nova.feature_staking_impl.domain.validators.ValidatorSource import io.novafoundation.nova.feature_staking_impl.domain.validators.getValidators diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/NominationPoolsRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/NominationPoolsRouter.kt index c506a97243..5651dd40b4 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/NominationPoolsRouter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/NominationPoolsRouter.kt @@ -21,4 +21,6 @@ interface NominationPoolsRouter : ReturnableRouter { fun returnToStakingMain() fun returnToMain() + + fun openSetStakingProxy() } 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 2971f2d1e4..83920d4d32 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 @@ -37,6 +37,8 @@ interface ParachainStakingRouter { fun openSetupYieldBoost() fun openConfirmYieldBoost(payload: YieldBoostConfirmPayload) + + fun openSetStakingProxy() } fun ParachainStakingRouter.openStartStaking(flowMode: StartParachainStakingMode) = openStartStaking(StartParachainStakingPayload(flowMode)) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt index 7682f0bc93..26cd327050 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt @@ -5,7 +5,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.payouts.confirm. import io.novafoundation.nova.feature_staking_impl.presentation.payouts.model.PendingPayoutParcelable import io.novafoundation.nova.feature_staking_impl.presentation.pools.common.SelectingPoolPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.confirm.ConfirmBondMorePayload -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.ConfirmSetControllerPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.model.StakingStoryModel import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.rewardDestination.confirm.parcel.ConfirmRewardDestinationPayload @@ -93,4 +93,6 @@ interface StakingRouter { fun finishSetupPoolFlow() fun finishRedeemFlow(redeemConsequences: RedeemConsequences) + + fun openSetStakingProxy() } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/ConfirmSetControllerFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/ConfirmSetControllerFragment.kt similarity index 98% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/ConfirmSetControllerFragment.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/ConfirmSetControllerFragment.kt index 349c468ae8..cbccf7d087 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/ConfirmSetControllerFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/ConfirmSetControllerFragment.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm import android.os.Bundle import android.view.LayoutInflater diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/ConfirmSetControllerPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/ConfirmSetControllerPayload.kt similarity index 91% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/ConfirmSetControllerPayload.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/ConfirmSetControllerPayload.kt index 385b742f66..12a49b89eb 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/ConfirmSetControllerPayload.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/ConfirmSetControllerPayload.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm import android.os.Parcelable import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeParcelModel diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/ConfirmSetControllerViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/ConfirmSetControllerViewModel.kt similarity index 94% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/ConfirmSetControllerViewModel.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/ConfirmSetControllerViewModel.kt index 655ac315ba..c88f923a09 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/ConfirmSetControllerViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/ConfirmSetControllerViewModel.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm import io.novafoundation.nova.common.address.AddressIconGenerator import io.novafoundation.nova.common.base.BaseViewModel @@ -13,11 +13,11 @@ import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.W import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor -import io.novafoundation.nova.feature_staking_impl.domain.staking.controller.ControllerInteractor -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationPayload -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationPayload +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.set.bondSetControllerValidationFailure +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.bondSetControllerValidationFailure import io.novafoundation.nova.feature_wallet_api.data.mappers.mapFeeToFeeModel import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeStatus import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.mapFeeFromParcel diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/di/ConfirmSetControllerComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/di/ConfirmSetControllerComponent.kt similarity index 81% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/di/ConfirmSetControllerComponent.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/di/ConfirmSetControllerComponent.kt index 9696d4817c..2ab54de1fd 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/di/ConfirmSetControllerComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/di/ConfirmSetControllerComponent.kt @@ -1,11 +1,11 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.di +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.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.staking.controller.confirm.ConfirmSetControllerFragment -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.ConfirmSetControllerPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload @Subcomponent( modules = [ diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/di/ConfirmSetControllerModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/di/ConfirmSetControllerModule.kt similarity index 91% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/di/ConfirmSetControllerModule.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/di/ConfirmSetControllerModule.kt index 95ea9195c1..71fac83dfa 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/confirm/di/ConfirmSetControllerModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/confirm/di/ConfirmSetControllerModule.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.di +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.di import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModel @@ -15,11 +15,11 @@ import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.W import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor -import io.novafoundation.nova.feature_staking_impl.domain.staking.controller.ControllerInteractor -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.ConfirmSetControllerPayload -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.ConfirmSetControllerViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerViewModel @Module(includes = [ViewModelModule::class]) class ConfirmSetControllerModule { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/SetControllerFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt similarity index 99% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/SetControllerFragment.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt index b5d90ab20b..e41e7dfd03 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/SetControllerFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.set +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set import android.os.Bundle import android.view.LayoutInflater diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/SetControllerViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerViewModel.kt similarity index 98% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/SetControllerViewModel.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerViewModel.kt index 2e3d7bc762..ca5746e1a9 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/SetControllerViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerViewModel.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.set +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set import androidx.lifecycle.viewModelScope import io.novafoundation.nova.common.address.AddressIconGenerator @@ -29,11 +29,11 @@ import io.novafoundation.nova.feature_staking_impl.data.repository.ControllersDe import io.novafoundation.nova.feature_staking_impl.data.repository.ControllersDeprecationStage.DEPRECATED import io.novafoundation.nova.feature_staking_impl.data.repository.ControllersDeprecationStage.NORMAL import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor -import io.novafoundation.nova.feature_staking_impl.domain.staking.controller.ControllerInteractor -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationPayload -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationPayload +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.confirm.ConfirmSetControllerPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.awaitDecimalFee import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.mapFeeToParcel diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/ValidationFailureMessage.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/ValidationFailureMessage.kt similarity index 92% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/ValidationFailureMessage.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/ValidationFailureMessage.kt index 5fd0185a8d..3b0c385597 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/ValidationFailureMessage.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/ValidationFailureMessage.kt @@ -1,9 +1,9 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.set +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set import io.novafoundation.nova.common.base.TitleAndMessage import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.feature_staking_impl.R -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationFailure +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationFailure fun bondSetControllerValidationFailure( reason: SetControllerValidationFailure, diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/di/SetControllerComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/di/SetControllerComponent.kt similarity index 86% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/di/SetControllerComponent.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/di/SetControllerComponent.kt index 8dc2a42980..39989026db 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/di/SetControllerComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/di/SetControllerComponent.kt @@ -1,10 +1,10 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.set.di +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.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.staking.controller.set.SetControllerFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.SetControllerFragment @Subcomponent( modules = [ diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/di/SetControllerModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/di/SetControllerModule.kt similarity index 94% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/di/SetControllerModule.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/di/SetControllerModule.kt index c2ad946915..f8e93966d3 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/controller/set/di/SetControllerModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/di/SetControllerModule.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.set.di +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.di import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModel @@ -17,10 +17,10 @@ import io.novafoundation.nova.feature_account_api.presenatation.account.AddressD import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor -import io.novafoundation.nova.feature_staking_impl.domain.staking.controller.ControllerInteractor -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.SetControllerValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.staking.controller.set.SetControllerViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.SetControllerViewModel import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin @Module(includes = [ViewModelModule::class]) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyFragment.kt new file mode 100644 index 0000000000..9df75ffa96 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyFragment.kt @@ -0,0 +1,79 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isInvisible +import io.novafoundation.nova.common.base.BaseFragment +import io.novafoundation.nova.common.di.FeatureUtils +import io.novafoundation.nova.common.mixin.impl.observeValidations +import io.novafoundation.nova.common.utils.applyStatusBarInsets +import io.novafoundation.nova.common.view.setState +import io.novafoundation.nova.feature_account_api.presenatation.actions.setupExternalActions +import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.setupAddressInput +import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.setupExternalAccounts +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_wallet_api.presentation.mixin.fee.setupFeeLoading +import io.novafoundation.nova.feature_wallet_api.presentation.view.showAmount +import kotlinx.android.synthetic.main.fragment_set_controller_account.confirmSetControllerContainer +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyAddress +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyButton +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyContainer +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyDeposit +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyFee +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyTitle +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.stakingProxySelectWallet + +class SetStakingProxyFragment : BaseFragment() { + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View? { + return inflater.inflate(R.layout.fragment_set_staking_proxy, container, false) + } + + override fun initViews() { + setStakingProxyContainer.applyStatusBarInsets() + + stakingProxySelectWallet.setOnClickListener { viewModel.selectRecipientWallet() } + } + + override fun inject() { + FeatureUtils.getFeature( + requireContext(), + StakingFeatureApi::class.java + ) + .setStakingProxyFactory() + .create(this) + .inject(this) + } + + override fun subscribe(viewModel: SetStakingProxyViewModel) { + setupExternalActions(viewModel) + observeValidations(viewModel) + + setupAddressInput(viewModel.addressInputMixin, setStakingProxyAddress) + setupExternalAccounts(viewModel.addressInputMixin, setStakingProxyAddress) + + viewModel.titleFlow.observe { + setStakingProxyTitle.text = it + } + + viewModel.isSelectAddressAvailable.observe { + stakingProxySelectWallet.isInvisible = !it + } + + viewModel.proxyDeposit.observe { + setStakingProxyDeposit.showAmount(it) + } + + setupFeeLoading(viewModel.feeMixin, setStakingProxyFee) + + viewModel.continueButtonState.observe(setStakingProxyButton::setState) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt new file mode 100644 index 0000000000..70883442fc --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt @@ -0,0 +1,163 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set + +import io.novafoundation.nova.common.base.BaseViewModel +import io.novafoundation.nova.common.mixin.api.Validatable +import io.novafoundation.nova.common.presentation.DescriptiveButtonState +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.utils.flowOf +import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInteractor +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount +import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory +import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor +import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase +import io.novafoundation.nova.feature_wallet_api.domain.model.withAmount +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.create +import io.novafoundation.nova.feature_wallet_api.presentation.model.AmountModel +import io.novafoundation.nova.feature_wallet_api.presentation.model.mapAmountToAmountModel +import io.novafoundation.nova.feature_wallet_api.presentation.model.transferableAmountModel +import io.novafoundation.nova.runtime.ext.accountIdOrNull +import io.novafoundation.nova.runtime.ext.commissionAsset +import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState +import io.novafoundation.nova.runtime.state.assetWithChain +import io.novafoundation.nova.runtime.state.chain +import io.novafoundation.nova.runtime.state.selectedAssetFlow +import io.novafoundation.nova.runtime.state.selectedChainFlow +import io.novafoundation.nova.runtime.state.selectedOption +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch + +class SetStakingProxyViewModel( + addressInputMixinFactory: AddressInputMixinFactory, + feeLoaderMixinFactory: FeeLoaderMixin.Factory, + private val selectedAssetState: AnySelectedAssetOptionSharedState, + private val externalActions: ExternalActions.Presentation, + private val interactor: StakingInteractor, + private val accountRepository: AccountRepository, + private val assetUseCase: ArbitraryAssetUseCase, + private val resourceManager: ResourceManager, + private val selectAddressRequester: SelectAddressForTransactionRequester, + private val addProxyInteractor: AddProxyInteractor, + private val validationExecutor: ValidationExecutor, +) : BaseViewModel(), + ExternalActions by externalActions, + Validatable by validationExecutor { + + @OptIn(ExperimentalCoroutinesApi::class) + private val commissionAssetFlow = selectedAssetState.selectedChainFlow() + .flatMapLatest { assetUseCase.assetFlow(it.id, it.commissionAsset.id) } + .shareInBackground() + + @OptIn(ExperimentalCoroutinesApi::class) + private val selectedAssetFlow = selectedAssetState.selectedAssetFlow() + .flatMapLatest { assetUseCase.assetFlow(it) } + .shareInBackground() + + val titleFlow = selectedAssetFlow.map { + resourceManager.getString(R.string.fragment_set_staking_proxy_title, it.token.configuration.symbol) + } + .shareInBackground() + + val addressInputMixin = with(addressInputMixinFactory) { + val inputSpec = singleChainInputSpec(selectedAssetState.selectedChainFlow()) + + create( + inputSpecProvider = inputSpec, + myselfBehaviorProvider = noMyself(), + accountIdentifierProvider = web3nIdentifiers( + destinationChainFlow = selectedAssetState.assetWithChain, + inputSpecProvider = inputSpec, + coroutineScope = this@SetStakingProxyViewModel, + ), + errorDisplayer = this@SetStakingProxyViewModel::showError, + showAccountEvent = this@SetStakingProxyViewModel::showAccountDetails, + coroutineScope = this@SetStakingProxyViewModel, + ) + } + + val isSelectAddressAvailable = flowOf { true } + .shareInBackground() + + val proxyDeposit: Flow = selectedAssetFlow + .map { asset -> + val metaAccount = accountRepository.getSelectedMetaAccount() + val chain = selectedAssetState.chain() + val accountId = metaAccount.requireAccountIdIn(chain) + val deposit = addProxyInteractor.calculateDepositForAddProxy(chain, accountId) + mapAmountToAmountModel(deposit, asset) + } + .shareInBackground() + + val feeMixin: FeeLoaderMixin.Presentation = feeLoaderMixinFactory.create(commissionAssetFlow) + + private val validationProgressFlow = MutableStateFlow(false) + + val continueButtonState = combine( + addressInputMixin.inputFlow, + validationProgressFlow + ) { addressInput, validationInProgress -> + when { + validationInProgress -> DescriptiveButtonState.Loading + + addressInput.isEmpty() -> DescriptiveButtonState.Disabled(resourceManager.getString(R.string.common_enter_address)) + + else -> DescriptiveButtonState.Enabled(resourceManager.getString(R.string.common_continue)) + } + } + + init { + runFeeUpdate() + } + + fun selectRecipientWallet() { + launch { + val selectedAddress = addressInputMixin.inputFlow.value + val chain = selectedAssetState.chain() + val request = SelectAddressForTransactionRequester.Request(chain.id, chain.id, selectedAddress) + selectAddressRequester.openRequest(request) + } + } + + fun onConfirmClick() { + + } + + private fun runFeeUpdate() { + addressInputMixin.inputFlow.onEach { + val chain = selectedAssetState.chain() + val accountId = chain.accountIdOrNull(it) + + if (accountId == null) { + feeMixin.setFee(null) + } else { + feeMixin.loadFee( + coroutineScope = this, + feeConstructor = { addProxyInteractor.estimateFee(chain, accountId, ProxyAccount.ProxyType.Staking) }, + onRetryCancelled = {} + ) + } + }.launchIn(this) + } + + private fun showAccountDetails(address: String) { + launch { + val chain = selectedAssetState.chain() + externalActions.showExternalActions(ExternalActions.Type.Address(address), chain) + } + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyComponent.kt new file mode 100644 index 0000000000..f86f1d86ea --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyComponent.kt @@ -0,0 +1,24 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.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.staking.delegation.controller.set.SetControllerFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.SetStakingProxyFragment + +@Subcomponent( + modules = [ + SetStakingProxyModule::class + ] +) +@ScreenScope +interface SetStakingProxyComponent { + + @Subcomponent.Factory + interface Factory { + fun create(@BindsInstance fragment: Fragment): SetStakingProxyComponent + } + + fun inject(fragment: SetStakingProxyFragment) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt new file mode 100644 index 0000000000..5333529f2d --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt @@ -0,0 +1,75 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.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.data.network.AppLinksProvider +import io.novafoundation.nova.common.di.viewmodel.ViewModelKey +import io.novafoundation.nova.common.di.viewmodel.ViewModelModule +import io.novafoundation.nova.common.mixin.actionAwaitable.ActionAwaitableMixin +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor +import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory +import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState +import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.SetControllerViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.SetStakingProxyViewModel +import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin +import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState + +@Module(includes = [ViewModelModule::class]) +class SetStakingProxyModule { + + @Provides + @IntoMap + @ViewModelKey(SetStakingProxyViewModel::class) + fun provideViewModel( + addressInputMixinFactory: AddressInputMixinFactory, + feeLoaderMixinFactory: FeeLoaderMixin.Factory, + selectedAssetState: AnySelectedAssetOptionSharedState, + externalActions: ExternalActions.Presentation, + interactor: StakingInteractor, + accountRepository: AccountRepository, + assetUseCase: ArbitraryAssetUseCase, + resourceManager: ResourceManager, + selectAddressCommunicator: SelectAddressCommunicator, + addProxyInteractor: AddProxyInteractor, + validationExecutor: ValidationExecutor + ): ViewModel { + return SetStakingProxyViewModel( + addressInputMixinFactory = addressInputMixinFactory, + feeLoaderMixinFactory = feeLoaderMixinFactory, + selectedAssetState = selectedAssetState, + externalActions = externalActions, + interactor = interactor, + accountRepository = accountRepository, + assetUseCase = assetUseCase, + resourceManager = resourceManager, + selectAddressRequester = selectAddressCommunicator, + addProxyInteractor = addProxyInteractor, + validationExecutor = validationExecutor + ) + } + + @Provides + fun provideViewModelCreator( + fragment: Fragment, + viewModelFactory: ViewModelProvider.Factory + ): SetStakingProxyViewModel { + return ViewModelProvider(fragment, viewModelFactory).get(SetStakingProxyViewModel::class.java) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt index 8219ed8037..6e834ebe9f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt @@ -3,8 +3,10 @@ package io.novafoundation.nova.feature_staking_impl.presentation.staking.main.co import androidx.annotation.DrawableRes import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_ADD_PROXY import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_CONTROLLER import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_PAYOUTS +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_PROXIES import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_REWARD_DESTINATION import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_BOND_MORE import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_UNBOND @@ -66,3 +68,19 @@ fun ManageStakeAction.Companion.controller(resourceManager: ResourceManager): Ma iconRes = R.drawable.ic_people_outline ) } + +fun ManageStakeAction.Companion.addStakingProxy(resourceManager: ResourceManager): ManageStakeAction { + return ManageStakeAction( + id = SYSTEM_ADD_PROXY, + label = resourceManager.getString(R.string.staking_action_add_proxy), + iconRes = R.drawable.ic_delegate_outline + ) +} + +fun ManageStakeAction.Companion.stakingProxies(resourceManager: ResourceManager): ManageStakeAction { + return ManageStakeAction( + id = SYSTEM_MANAGE_PROXIES, + label = resourceManager.getString(R.string.staking_action_your_proxies), + iconRes = R.drawable.ic_people_outline + ) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt index 81e14b8e61..0568981638 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt @@ -7,8 +7,11 @@ import io.novafoundation.nova.common.utils.Event import io.novafoundation.nova.common.utils.WithCoroutineScopeExtensions import io.novafoundation.nova.common.utils.flowOf import io.novafoundation.nova.feature_staking_impl.data.StakingOption +import io.novafoundation.nova.feature_staking_impl.data.chain import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network.blockhain.models.PoolMember import io.novafoundation.nova.feature_staking_impl.domain.nominationPools.common.NominationPoolSharedComputation +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_ADD_PROXY +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_PROXIES import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_BOND_MORE import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_UNBOND import io.novafoundation.nova.feature_staking_impl.presentation.NominationPoolsRouter @@ -19,6 +22,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.com import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsEvent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsState +import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.addStakingProxy import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.bondMore import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.unbond import kotlinx.coroutines.CoroutineScope @@ -45,7 +49,7 @@ class NominationPoolsStakeActionsComponentFactory( private open class NominationPoolsStakeActionsComponent( nominationPoolSharedComputation: NominationPoolSharedComputation, - stakingOption: StakingOption, + private val stakingOption: StakingOption, private val router: NominationPoolsRouter, private val hostContext: ComponentHostContext, private val resourceManager: ResourceManager, @@ -75,6 +79,8 @@ private open class NominationPoolsStakeActionsComponent( when (action.id) { SYSTEM_MANAGE_STAKING_BOND_MORE -> router.openSetupBondMore() SYSTEM_MANAGE_STAKING_UNBOND -> router.openSetupUnbond() + SYSTEM_ADD_PROXY -> router.openSetStakingProxy() + SYSTEM_MANAGE_PROXIES -> TODO() } } @@ -86,8 +92,12 @@ private open class NominationPoolsStakeActionsComponent( } } - private fun availablePoolMemberActions(): List = listOf( - ManageStakeAction.bondMore(resourceManager), - ManageStakeAction.unbond(resourceManager) - ) + private fun availablePoolMemberActions(): List = buildList { + add(ManageStakeAction.bondMore(resourceManager)) + add(ManageStakeAction.unbond(resourceManager)) + + if (stakingOption.chain.supportProxy) { + add(ManageStakeAction.addStakingProxy(resourceManager)) + } + } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt index 50659af6ac..769c3836ac 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt @@ -11,9 +11,12 @@ import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.feature_staking_api.domain.model.parachain.DelegatorState import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.data.StakingOption +import io.novafoundation.nova.feature_staking_impl.data.chain import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.DelegatorStateUseCase import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.unbond.validations.preliminary.ParachainStakingUnbondPreliminaryValidationPayload import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.unbond.validations.preliminary.ParachainStakingUnbondPreliminaryValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_ADD_PROXY +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_PROXIES import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_BOND_MORE import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_UNBOND import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_VALIDATORS @@ -28,6 +31,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.com import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsEvent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsState +import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.addStakingProxy import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.bondMore import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.unbond import kotlinx.coroutines.CoroutineScope @@ -94,6 +98,8 @@ internal open class ParachainStakeActionsComponent( SYSTEM_MANAGE_VALIDATORS -> router.openCurrentCollators() SYSTEM_MANAGE_STAKING_BOND_MORE -> router.openStartStaking(StartParachainStakingMode.BOND_MORE) SYSTEM_MANAGE_STAKING_UNBOND -> openUnbondIfValid() + SYSTEM_ADD_PROXY -> router.openSetStakingProxy() + SYSTEM_MANAGE_PROXIES -> TODO() } } @@ -111,6 +117,10 @@ internal open class ParachainStakeActionsComponent( val collatorsCount = delegatorState.delegations.size.format() add(ManageStakeAction.collators(resourceManager, collatorsCount)) + + if (stakingOption.chain.supportProxy) { + add(ManageStakeAction.addStakingProxy(resourceManager)) //TODO: handle case when proxy is already set + } } private fun openUnbondIfValid() = launch { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt index 145d5a7e59..c1145e7360 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt @@ -6,9 +6,12 @@ import io.novafoundation.nova.common.utils.Event import io.novafoundation.nova.common.utils.WithCoroutineScopeExtensions import io.novafoundation.nova.feature_staking_api.domain.model.relaychain.StakingState import io.novafoundation.nova.feature_staking_impl.data.StakingOption +import io.novafoundation.nova.feature_staking_impl.data.chain import io.novafoundation.nova.feature_staking_impl.domain.common.StakingSharedComputation +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_ADD_PROXY import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_CONTROLLER import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_PAYOUTS +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_PROXIES import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_REWARD_DESTINATION import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_BOND_MORE import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_UNBOND @@ -22,6 +25,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.com import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsEvent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsState +import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.addStakingProxy import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.bondMore import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.controller import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.payouts @@ -120,6 +124,8 @@ private class RelaychainStakeActionsComponent( SYSTEM_MANAGE_CONTROLLER -> router.openControllerAccount() SYSTEM_MANAGE_VALIDATORS -> router.openCurrentValidators() SYSTEM_MANAGE_REWARD_DESTINATION -> router.openChangeRewardDestination() + SYSTEM_ADD_PROXY -> router.openSetStakingProxy() + SYSTEM_MANAGE_PROXIES -> TODO() } } @@ -127,7 +133,6 @@ private class RelaychainStakeActionsComponent( add(ManageStakeAction.Companion::bondMore) add(ManageStakeAction.Companion::unbond) add(ManageStakeAction.Companion::rewardDestination) - add(ManageStakeAction.Companion::controller) if (stakingState !is StakingState.Stash.None) { add(ManageStakeAction.Companion::payouts) @@ -136,5 +141,11 @@ private class RelaychainStakeActionsComponent( if (stakingState !is StakingState.Stash.Validator) { add(ManageStakeAction.Companion::validators) } + + add(ManageStakeAction.Companion::controller) + + if (stakingOption.chain.supportProxy) { + add(ManageStakeAction.Companion::addStakingProxy) //TODO: handle case when proxy is already set + } }.map { it.invoke(resourceManager) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/change/ChangeStakingValidationFailureUI.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/change/ChangeStakingValidationFailureUI.kt index d7bca03440..b572726f85 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/change/ChangeStakingValidationFailureUI.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/change/ChangeStakingValidationFailureUI.kt @@ -3,7 +3,7 @@ package io.novafoundation.nova.feature_staking_impl.presentation.validators.chan import io.novafoundation.nova.common.base.TitleAndMessage import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.feature_staking_impl.R -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.ChangeStackingValidationFailure +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.ChangeStackingValidationFailure fun mapAddEvmTokensValidationFailureToUI( resourceManager: ResourceManager, diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/current/CurrentValidatorsViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/current/CurrentValidatorsViewModel.kt index 8ec5486d08..fdb3e2b9b4 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/current/CurrentValidatorsViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/current/CurrentValidatorsViewModel.kt @@ -16,7 +16,7 @@ import io.novafoundation.nova.feature_staking_api.domain.model.NominatedValidato import io.novafoundation.nova.feature_staking_api.domain.model.relaychain.StakingState import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor -import io.novafoundation.nova.feature_staking_impl.domain.validations.controller.ChangeStackingValidationPayload +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.ChangeStackingValidationPayload import io.novafoundation.nova.feature_staking_impl.domain.validators.current.CurrentValidatorsInteractor import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.common.SetupStakingProcess diff --git a/feature-staking-impl/src/main/res/layout/fragment_set_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_set_staking_proxy.xml new file mode 100644 index 0000000000..af2666e8a1 --- /dev/null +++ b/feature-staking-impl/src/main/res/layout/fragment_set_staking_proxy.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt b/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt index 674c352673..e1b2e3c129 100644 --- a/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt +++ b/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt @@ -1,6 +1,6 @@ package io.novafoundation.nova.feature_wallet_impl.data.network.blockchain.assets.transfers.validations -import io.novafoundation.nova.feature_account_api.domain.validation.notSystemAccount +import io.novafoundation.nova.feature_account_api.domain.validation.proxy.notSystemAccount import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.AssetSourceRegistry import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.existentialDeposit import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.AssetTransfer @@ -103,10 +103,11 @@ fun AssetTransfersValidationSystemBuilder.sufficientBalanceInUsedAsset() = suffi error = { AssetTransferValidationFailure.NotEnoughFunds.InUsedAsset } ) -fun AssetTransfersValidationSystemBuilder.recipientIsNotSystemAccount() = notSystemAccount( - accountId = { it.transfer.recipientOrNull() }, - error = { AssetTransferValidationFailure.RecipientIsSystemAccount } -) +fun AssetTransfersValidationSystemBuilder.recipientIsNotSystemAccount() = + io.novafoundation.nova.feature_account_api.domain.validation.proxy.notSystemAccount( + accountId = { it.transfer.recipientOrNull() }, + error = { AssetTransferValidationFailure.RecipientIsSystemAccount } + ) private suspend fun AssetSourceRegistry.existentialDepositForUsedAsset(transfer: AssetTransfer): BigDecimal { return existentialDeposit(transfer.originChain, transfer.originChainAsset) From 4d5deffc560be69c0a2d3596516ce01c36ca8b4d Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 8 Jan 2024 11:17:46 +0100 Subject: [PATCH 02/55] Refactorung proxy module --- app/build.gradle | 3 + .../nova/app/di/deps/ComponentHolderModule.kt | 8 ++ .../nova/app/root/di/RootDependencies.kt | 2 +- .../nova/app/root/di/RootFeatureModule.kt | 2 +- .../nova/app/root/domain/RootInteractor.kt | 2 +- feature-account-api/build.gradle | 1 + .../data/proxy/ProxySyncService.kt | 6 -- .../data/proxy/sync/ProxySyncService.kt | 6 ++ .../data/repository/ProxyRepository.kt | 16 ---- .../ledger/LedgerAddAccountRepository.kt | 7 +- .../proxied/ProxiedAddAccountRepository.kt | 14 ++++ .../di/AccountFeatureApi.kt | 4 +- .../domain/model/MetaAccountId.kt | 5 -- .../domain/model/ProxyAccount.kt | 25 +------ .../account/proxy/ProxySigningPresenter.kt | 4 +- feature-account-impl/build.gradle | 1 + .../data/mappers/Mappers.kt | 36 +++------ .../proxy/{ => sync}/RealProxySyncService.kt | 75 +++++++++++++------ .../addAccount/BaseAddAccountRepository.kt | 5 +- .../ledger/RealLedgerAddAccountRepository.kt | 6 +- .../ParitySignerAddAccountRepository.kt | 4 +- ....kt => RealProxiedAddAccountRepository.kt} | 19 ++--- .../secrets/JsonAddAccountRepository.kt | 2 +- .../secrets/MnemonicAddAccountRepository.kt | 2 +- .../secrets/SecretsAddAccountRepository.kt | 4 +- .../secrets/SeedAddAccountRepository.kt | 2 +- .../WatchOnlyAddAccountRepository.kt | 4 +- .../signer/proxy/ModuleToProxyTypeMatcher.kt | 26 +++---- .../data/signer/proxy/ProxiedFeeSigner.kt | 4 +- .../data/signer/proxy/ProxiedSigner.kt | 12 +-- .../signer/proxy/SignerPayloadModifierExt.kt | 4 +- .../di/AccountFeatureComponent.kt | 2 + .../di/AccountFeatureDependencies.kt | 3 + .../di/AccountFeatureHolder.kt | 2 + .../di/AccountFeatureModule.kt | 71 ++++++------------ .../di/AddAccountsModule.kt | 7 +- .../di/modules/signers/ProxiedSignerModule.kt | 4 +- .../proxy/AddProxyValidationSystem.kt | 54 ------------- .../account/common/listing/ProxyFormatter.kt | 21 +++--- .../proxy/sign/RealProxySigningPresenter.kt | 6 +- .../send/TransferAssetValidationFailureUi.kt | 2 +- feature-proxy-api/.gitignore | 1 + feature-proxy-api/build.gradle | 31 ++++++++ feature-proxy-api/consumer-rules.pro | 0 feature-proxy-api/proguard-rules.pro | 21 ++++++ .../src/main/AndroidManifest.xml | 3 + .../data}/calls/ExtrinsicBuilderExt.kt | 6 +- .../data/common/ProxyDepositCalculator.kt | 20 +++++ .../data/model/ProxiedWithProxy.kt | 3 +- .../data/repository/GetProxyRepository.kt | 16 ++++ .../feature_proxy_api/di/ProxyFeatureApi.kt | 11 +++ .../domain/model/ProxyType.kt | 38 ++++++++++ feature-proxy-impl/.gitignore | 1 + feature-proxy-impl/build.gradle | 66 ++++++++++++++++ feature-proxy-impl/consumer-rules.pro | 0 feature-proxy-impl/proguard-rules.pro | 21 ++++++ .../src/main/AndroidManifest.xml | 2 + .../data/common/RealProxyDepositCalculator.kt | 22 ++---- .../data/repository/RealGetProxyRepository.kt | 44 +++++------ .../di/ProxyFeatureComponent.kt | 35 +++++++++ .../di/ProxyFeatureDependencies.kt | 18 +++++ .../di/ProxyFeatureHolder.kt | 24 ++++++ .../di/ProxyFeatureModule.kt | 33 ++++++++ feature-staking-api/build.gradle | 1 + .../data/proxy/AddStakingProxyRepository.kt | 10 +-- feature-staking-impl/build.gradle | 1 + .../proxy/RealAddStakingProxyRepository.kt | 28 +++---- .../di/StakingFeatureComponent.kt | 2 + .../di/StakingFeatureDependencies.kt | 9 ++- .../di/StakingFeatureHolder.kt | 2 + .../di/StakingFeatureModule.kt | 18 +++++ .../proxy/SetStakingProxyInteractor.kt | 10 --- .../proxy/AddProxyValidationSystem.kt | 41 ++++++++++ .../proxy/set/SetStakingProxyViewModel.kt | 14 +--- .../proxy/set/di/SetStakingProxyModule.kt | 16 +--- .../assets/transfers/validations/Common.kt | 4 +- settings.gradle | 2 + 77 files changed, 678 insertions(+), 379 deletions(-) delete mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/ProxySyncService.kt create mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/sync/ProxySyncService.kt delete mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/ProxyRepository.kt create mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt delete mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/model/MetaAccountId.kt rename feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/{ => sync}/RealProxySyncService.kt (67%) rename {feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api => feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl}/data/repository/addAccount/BaseAddAccountRepository.kt (59%) rename feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/{ProxiedAddAccountRepository.kt => RealProxiedAddAccountRepository.kt} (83%) delete mode 100644 feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/validation/proxy/AddProxyValidationSystem.kt create mode 100644 feature-proxy-api/.gitignore create mode 100644 feature-proxy-api/build.gradle create mode 100644 feature-proxy-api/consumer-rules.pro create mode 100644 feature-proxy-api/proguard-rules.pro create mode 100644 feature-proxy-api/src/main/AndroidManifest.xml rename {feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/network/blockchain/bindings => feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data}/calls/ExtrinsicBuilderExt.kt (77%) create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt rename {feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api => feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api}/data/model/ProxiedWithProxy.kt (81%) create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/di/ProxyFeatureApi.kt create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyType.kt create mode 100644 feature-proxy-impl/.gitignore create mode 100644 feature-proxy-impl/build.gradle create mode 100644 feature-proxy-impl/consumer-rules.pro create mode 100644 feature-proxy-impl/proguard-rules.pro create mode 100644 feature-proxy-impl/src/main/AndroidManifest.xml rename feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/common/ProxyDepositCalculator.kt => feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt (58%) rename feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/RealProxyRepository.kt => feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt (76%) create mode 100644 feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureComponent.kt create mode 100644 feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureDependencies.kt create mode 100644 feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureHolder.kt create mode 100644 feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt rename feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/proxy/AddProxyInteractor.kt => feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt (50%) rename feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/RealAddProxyInteractor.kt => feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt (61%) delete mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/SetStakingProxyInteractor.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddProxyValidationSystem.kt diff --git a/app/build.gradle b/app/build.gradle index 6ca8ca4f40..cef749f83b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -210,6 +210,9 @@ dependencies { implementation project(':feature-wallet-connect-api') implementation project(':feature-wallet-connect-impl') + implementation project(':feature-proxy-api') + implementation project(':feature-proxy-impl') + implementation project(':feature-settings-api') implementation project(':feature-settings-impl') diff --git a/app/src/main/java/io/novafoundation/nova/app/di/deps/ComponentHolderModule.kt b/app/src/main/java/io/novafoundation/nova/app/di/deps/ComponentHolderModule.kt index 5d43bffc76..d491dac546 100644 --- a/app/src/main/java/io/novafoundation/nova/app/di/deps/ComponentHolderModule.kt +++ b/app/src/main/java/io/novafoundation/nova/app/di/deps/ComponentHolderModule.kt @@ -36,6 +36,8 @@ import io.novafoundation.nova.feature_nft_api.NftFeatureApi import io.novafoundation.nova.feature_nft_impl.di.NftFeatureHolder import io.novafoundation.nova.feature_onboarding_api.di.OnboardingFeatureApi import io.novafoundation.nova.feature_onboarding_impl.di.OnboardingFeatureHolder +import io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi +import io.novafoundation.nova.feature_proxy_impl.di.ProxyFeatureHolder import io.novafoundation.nova.feature_settings_api.SettingsFeatureApi import io.novafoundation.nova.feature_settings_impl.di.SettingsFeatureHolder import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi @@ -207,4 +209,10 @@ interface ComponentHolderModule { @ClassKey(BuyFeatureApi::class) @IntoMap fun provideBuyFeature(holder: BuyFeatureHolder): FeatureApiHolder + + @ApplicationScope + @Binds + @ClassKey(io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi::class) + @IntoMap + fun provideProxyFeature(holder: ProxyFeatureHolder): FeatureApiHolder } diff --git a/app/src/main/java/io/novafoundation/nova/app/root/di/RootDependencies.kt b/app/src/main/java/io/novafoundation/nova/app/root/di/RootDependencies.kt index 5eea5fa6ed..2a35d2b664 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/di/RootDependencies.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/di/RootDependencies.kt @@ -10,7 +10,7 @@ import io.novafoundation.nova.common.utils.coroutines.RootScope import io.novafoundation.nova.common.utils.sequrity.AutomaticInteractionGate import io.novafoundation.nova.common.utils.sequrity.BackgroundAccessObserver import io.novafoundation.nova.common.utils.systemCall.SystemCallExecutor -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxyExtrinsicValidationRequestBus import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.account.common.EncryptionDefaults diff --git a/app/src/main/java/io/novafoundation/nova/app/root/di/RootFeatureModule.kt b/app/src/main/java/io/novafoundation/nova/app/root/di/RootFeatureModule.kt index acdb0015f2..d7d8e8040f 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/di/RootFeatureModule.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/di/RootFeatureModule.kt @@ -5,7 +5,7 @@ import dagger.Provides import io.novafoundation.nova.app.root.di.busHandler.RequestBusHandlerModule import io.novafoundation.nova.app.root.domain.RootInteractor import io.novafoundation.nova.common.di.scope.FeatureScope -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_assets.data.network.BalancesUpdateSystem import io.novafoundation.nova.feature_wallet_api.domain.interfaces.WalletRepository diff --git a/app/src/main/java/io/novafoundation/nova/app/root/domain/RootInteractor.kt b/app/src/main/java/io/novafoundation/nova/app/root/domain/RootInteractor.kt index d5a3fa40a8..48b5609a6e 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/domain/RootInteractor.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/domain/RootInteractor.kt @@ -1,7 +1,7 @@ package io.novafoundation.nova.app.root.domain import io.novafoundation.nova.core.updater.Updater -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_assets.data.network.BalancesUpdateSystem import io.novafoundation.nova.feature_buy_impl.domain.providers.ExternalProvider diff --git a/feature-account-api/build.gradle b/feature-account-api/build.gradle index cd5b1d6235..9a6c4f6b2b 100644 --- a/feature-account-api/build.gradle +++ b/feature-account-api/build.gradle @@ -30,6 +30,7 @@ dependencies { implementation project(':runtime') implementation project(":common") implementation project(":feature-currency-api") + implementation project(":feature-proxy-api") implementation project(':web3names') implementation project(":feature-ledger-api") diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/ProxySyncService.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/ProxySyncService.kt deleted file mode 100644 index b54663ec26..0000000000 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/ProxySyncService.kt +++ /dev/null @@ -1,6 +0,0 @@ -package io.novafoundation.nova.feature_account_api.data.proxy - -interface ProxySyncService { - - fun startSyncing() -} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/sync/ProxySyncService.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/sync/ProxySyncService.kt new file mode 100644 index 0000000000..7f412880a2 --- /dev/null +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/sync/ProxySyncService.kt @@ -0,0 +1,6 @@ +package io.novafoundation.nova.feature_account_api.data.proxy.sync + +interface ProxySyncService { + + fun startSyncing() +} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/ProxyRepository.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/ProxyRepository.kt deleted file mode 100644 index dbdb00d692..0000000000 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/ProxyRepository.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.novafoundation.nova.feature_account_api.data.repository - -import io.novafoundation.nova.feature_account_api.data.model.ProxiedWithProxy -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountId -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount -import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId -import jp.co.soramitsu.fearless_utils.runtime.AccountId - -interface ProxyRepository { - - suspend fun getAllProxiesForMetaAccounts(chainId: ChainId, metaAccountIds: List): List - - suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List - - suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int -} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/ledger/LedgerAddAccountRepository.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/ledger/LedgerAddAccountRepository.kt index db227fa813..b51bd013f2 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/ledger/LedgerAddAccountRepository.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/ledger/LedgerAddAccountRepository.kt @@ -1,13 +1,10 @@ package io.novafoundation.nova.feature_account_api.data.repository.addAccount.ledger -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService -import io.novafoundation.nova.feature_account_api.data.repository.addAccount.BaseAddAccountRepository +import io.novafoundation.nova.feature_account_api.data.repository.addAccount.AddAccountRepository import io.novafoundation.nova.feature_ledger_api.sdk.application.substrate.LedgerSubstrateAccount import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId -abstract class LedgerAddAccountRepository( - private val proxySyncService: ProxySyncService, -) : BaseAddAccountRepository(proxySyncService) { +interface LedgerAddAccountRepository : AddAccountRepository { sealed interface Payload { class MetaAccount( diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt new file mode 100644 index 0000000000..6a99f79294 --- /dev/null +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt @@ -0,0 +1,14 @@ +package io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied + +import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy +import io.novafoundation.nova.feature_account_api.data.repository.addAccount.AddAccountRepository +import io.novafoundation.nova.feature_account_api.domain.account.identity.Identity + +interface ProxiedAddAccountRepository : AddAccountRepository { + + class Payload( + val proxiedWithProxy: ProxiedWithProxy, + val proxyMetaId: Long, + val identity: Identity? + ) +} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt index 63b47f2f2c..b40ceb466b 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt @@ -5,7 +5,7 @@ import io.novafoundation.nova.common.sequrity.TwoFactorVerificationExecutor import io.novafoundation.nova.common.utils.MutableSharedState import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.EvmTransactionService import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxyExtrinsicValidationRequestBus import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository import io.novafoundation.nova.feature_account_api.data.repository.addAccount.ledger.LedgerAddAccountRepository @@ -18,7 +18,6 @@ import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase -import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor import io.novafoundation.nova.feature_account_api.domain.updaters.AccountUpdateScope import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase import io.novafoundation.nova.feature_account_api.presenatation.account.polkadotVault.config.PolkadotVaultVariantConfigProvider @@ -82,7 +81,6 @@ interface AccountFeatureApi { fun ledgerAddAccountRepository(): LedgerAddAccountRepository - fun addProxyInteractor(): AddProxyInteractor val evmTransactionService: EvmTransactionService diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/model/MetaAccountId.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/model/MetaAccountId.kt deleted file mode 100644 index 24fbb19f44..0000000000 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/model/MetaAccountId.kt +++ /dev/null @@ -1,5 +0,0 @@ -package io.novafoundation.nova.feature_account_api.domain.model - -import jp.co.soramitsu.fearless_utils.runtime.AccountId - -class MetaAccountId(val accountId: AccountId, val metaId: Long) diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/model/ProxyAccount.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/model/ProxyAccount.kt index 4eb5e0c4a6..306eb1c4bf 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/model/ProxyAccount.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/model/ProxyAccount.kt @@ -1,5 +1,6 @@ package io.novafoundation.nova.feature_account_api.domain.model +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId class ProxyAccount( @@ -7,26 +8,4 @@ class ProxyAccount( val chainId: ChainId, val proxiedAccountId: ByteArray, val proxyType: ProxyType, -) { - - sealed class ProxyType(val name: String) { - - object Any : ProxyType("Any") - - object NonTransfer : ProxyType("NonTransfer") - - object Governance : ProxyType("Governance") - - object Staking : ProxyType("Staking") - - object IdentityJudgement : ProxyType("IdentityJudgement") - - object CancelProxy : ProxyType("CancelProxy") - - object Auction : ProxyType("Auction") - - object NominationPools : ProxyType("NominationPools") - - class Other(name: String) : ProxyType(name) - } -} +) diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/proxy/ProxySigningPresenter.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/proxy/ProxySigningPresenter.kt index 98f8682d84..041f4d2fad 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/proxy/ProxySigningPresenter.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/proxy/ProxySigningPresenter.kt @@ -2,7 +2,7 @@ package io.novafoundation.nova.feature_account_api.presenatation.account.proxy import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import java.math.BigInteger @@ -10,7 +10,7 @@ interface ProxySigningPresenter { suspend fun acknowledgeProxyOperation(proxiedMetaAccount: MetaAccount, proxyMetaAccount: MetaAccount): Boolean - suspend fun notEnoughPermission(proxiedMetaAccount: MetaAccount, proxyMetaAccount: MetaAccount, proxyTypes: List) + suspend fun notEnoughPermission(proxiedMetaAccount: MetaAccount, proxyMetaAccount: MetaAccount, proxyTypes: List) suspend fun signingIsNotSupported() diff --git a/feature-account-impl/build.gradle b/feature-account-impl/build.gradle index 5909d7a896..8d1f54825b 100644 --- a/feature-account-impl/build.gradle +++ b/feature-account-impl/build.gradle @@ -43,6 +43,7 @@ dependencies { implementation project(':feature-currency-api') implementation project(':feature-ledger-api') implementation project(':feature-versions-api') + implementation project(':feature-proxy-api') implementation project(':web3names') implementation kotlinDep diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/mappers/Mappers.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/mappers/Mappers.kt index 60c027fea0..035e50c674 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/mappers/Mappers.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/mappers/Mappers.kt @@ -22,6 +22,8 @@ import io.novafoundation.nova.feature_account_impl.presentation.common.mixin.api import io.novafoundation.nova.feature_account_impl.presentation.node.model.NodeModel import io.novafoundation.nova.feature_account_impl.presentation.view.advanced.encryption.model.CryptoTypeModel import io.novafoundation.nova.feature_account_impl.presentation.view.advanced.network.model.NetworkModel +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.feature_proxy_api.domain.model.fromString fun mapNetworkTypeToNetworkModel(networkType: NetworkType): NetworkModel { val type = when (networkType) { @@ -40,21 +42,21 @@ fun mapCryptoTypeToCryptoTypeModel( ): CryptoTypeModel { val name = when (encryptionType) { CryptoType.SR25519 -> "${resourceManager.getString(R.string.sr25519_selection_title)} ${ - resourceManager.getString( - R.string.sr25519_selection_subtitle - ) + resourceManager.getString( + R.string.sr25519_selection_subtitle + ) }" CryptoType.ED25519 -> "${resourceManager.getString(R.string.ed25519_selection_title)} ${ - resourceManager.getString( - R.string.ed25519_selection_subtitle - ) + resourceManager.getString( + R.string.ed25519_selection_subtitle + ) }" CryptoType.ECDSA -> "${resourceManager.getString(R.string.ecdsa_selection_title)} ${ - resourceManager.getString( - R.string.ecdsa_selection_subtitle - ) + resourceManager.getString( + R.string.ecdsa_selection_subtitle + ) }" } @@ -182,7 +184,7 @@ fun mapProxyAccountFromLocal(proxyAccountLocal: ProxyAccountLocal): ProxyAccount metaId = proxyMetaId, chainId = chainId, proxiedAccountId = proxiedAccountId, - proxyType = mapProxyTypeToString(proxyType) + proxyType = ProxyType.fromString(proxyType) ) } } @@ -207,20 +209,6 @@ fun mapOptionalNameToNameChooserState(name: String?) = when (name) { else -> AccountNameChooserMixin.State.Input(name) } -fun mapProxyTypeToString(proxyType: String): ProxyAccount.ProxyType { - return when (proxyType) { - "Any" -> ProxyAccount.ProxyType.Any - "NonTransfer" -> ProxyAccount.ProxyType.NonTransfer - "Governance" -> ProxyAccount.ProxyType.Governance - "Staking" -> ProxyAccount.ProxyType.Staking - "IdentityJudgement" -> ProxyAccount.ProxyType.IdentityJudgement - "CancelProxy" -> ProxyAccount.ProxyType.CancelProxy - "Auction" -> ProxyAccount.ProxyType.Auction - "NominationPools" -> ProxyAccount.ProxyType.NominationPools - else -> ProxyAccount.ProxyType.Other(proxyType) - } -} - private fun mapMetaAccountStateFromLocal(local: MetaAccountLocal.Status): LightMetaAccount.Status { return when (local) { MetaAccountLocal.Status.ACTIVE -> LightMetaAccount.Status.ACTIVE diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/sync/RealProxySyncService.kt similarity index 67% rename from feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt rename to feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/sync/RealProxySyncService.kt index 17f5853a56..abd424c775 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/sync/RealProxySyncService.kt @@ -1,36 +1,42 @@ -package io.novafoundation.nova.feature_account_impl.data.proxy +package io.novafoundation.nova.feature_account_impl.data.proxy.sync import android.util.Log import io.novafoundation.nova.common.address.AccountIdKey import io.novafoundation.nova.common.address.intoKey +import io.novafoundation.nova.common.list.GroupedList import io.novafoundation.nova.common.utils.LOG_TAG import io.novafoundation.nova.common.utils.coroutines.RootScope import io.novafoundation.nova.common.utils.mapToSet import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.model.chain.account.MetaAccountLocal import io.novafoundation.nova.core_db.model.chain.account.ProxyAccountLocal -import io.novafoundation.nova.feature_account_api.data.model.ProxiedWithProxy +import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy import io.novafoundation.nova.feature_account_api.data.proxy.MetaAccountsUpdatesRegistry -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService -import io.novafoundation.nova.feature_account_api.data.repository.ProxyRepository +import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.identity.Identity import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountId import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn -import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.proxied.ProxiedAddAccountRepository +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import io.novafoundation.nova.runtime.multiNetwork.findChains +import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +class ProxiedWithProxyMetaAccount( + val proxiedWithProxy: ProxiedWithProxy, + val proxyMetaAccount: MetaAccount, +) + class RealProxySyncService( private val chainRegistry: ChainRegistry, - private val proxyRepository: ProxyRepository, + private val getProxyRepository: GetProxyRepository, private val accountRepository: AccountRepository, private val accountDao: MetaAccountDao, private val identityProvider: IdentityProvider, @@ -61,9 +67,11 @@ class RealProxySyncService( private suspend fun syncChainProxies(chain: Chain, metaAccounts: List) = runCatching { Log.d(LOG_TAG, "Started syncing proxies for ${chain.name}") - val availableAccountIds = chain.getAvailableAccountIds(metaAccounts) + val availableAccountIdsToMetaAccounts = chain.getAvailableAccountIds(metaAccounts) + val availableAccountIds = availableAccountIdsToMetaAccounts.keys - val proxiedsWithProxies = proxyRepository.getAllProxiesForMetaAccounts(chain.id, availableAccountIds) + val proxiedsWithProxies = getProxyRepository.getAllProxiesForAccounts(chain.id, availableAccountIds) + .withProxyMetaAccount(availableAccountIdsToMetaAccounts) val oldProxies = accountDao.getProxyAccounts(chain.id) @@ -71,9 +79,15 @@ class RealProxySyncService( val identitiesByChain = notAddedProxies.loadProxiedIdentities(chain.id) val addedProxiedsMetaIds = notAddedProxies.map { - val identity = identitiesByChain[it.proxied.accountId.intoKey()] - - proxiedAddAccountRepository.addAccount(ProxiedAddAccountRepository.Payload(it, identity)) + val identity = identitiesByChain[it.proxiedWithProxy.proxied.accountId.intoKey()] + + proxiedAddAccountRepository.addAccount( + ProxiedAddAccountRepository.Payload( + it.proxiedWithProxy, + it.proxyMetaAccount.id, + identity + ) + ) } val deactivatedMetaAccountIds = getDeactivatedMetaIds(proxiedsWithProxies, oldProxies) @@ -88,15 +102,15 @@ class RealProxySyncService( } private fun filterNotAddedProxieds( - proxiedsWithProxies: List, + proxiedsWithProxies: List, oldProxies: List - ): List { + ): List { val oldIdentifiers = oldProxies.mapToSet { it.identifier } return proxiedsWithProxies.filter { it.toLocalIdentifier() !in oldIdentifiers } } private suspend fun getDeactivatedMetaIds( - onChainProxies: List, + onChainProxies: List, oldProxies: List ): List { val newIdentifiers = onChainProxies.mapToSet { it.toLocalIdentifier() } @@ -127,17 +141,34 @@ class RealProxySyncService( return chainRegistry.findChains { it.supportProxy } } - private fun Chain.getAvailableAccountIds(metaAccounts: List): List { + private fun Chain.getAvailableAccountIds2(metaAccounts: List): List { + return metaAccounts.mapNotNull { metaAccount -> + metaAccount.accountIdIn(chain = this) + } + } + + private fun Chain.getAvailableAccountIds(metaAccounts: List): GroupedList { return metaAccounts.mapNotNull { metaAccount -> val accountId = metaAccount.accountIdIn(chain = this) accountId?.let { - MetaAccountId(accountId, metaAccount.id) + accountId to metaAccount } + }.groupBy( + keySelector = { it.first.intoKey() }, + valueTransform = { it.second } + ) + } + + private fun List.withProxyMetaAccount(metaAccounts: GroupedList): List { + return flatMap { proxied -> + val proxyAccountId = proxied.proxy.accountId.intoKey() + metaAccounts.getValue(proxyAccountId) + .map { metaAccount -> ProxiedWithProxyMetaAccount(proxied, metaAccount) } } } - private suspend fun List.loadProxiedIdentities(chainId: ChainId): Map { - val proxiedAccountIds = map { it.proxied.accountId } + private suspend fun List.loadProxiedIdentities(chainId: ChainId): Map { + val proxiedAccountIds = map { it.proxiedWithProxy.proxied.accountId } return identityProvider.identitiesFor(proxiedAccountIds, chainId) } @@ -148,9 +179,11 @@ class RealProxySyncService( return this - alreadyDeactivatedMetaAccountIds.toSet() } - private fun ProxiedWithProxy.toLocalIdentifier(): String { + private fun ProxiedWithProxyMetaAccount.toLocalIdentifier(): String { + val proxy = proxiedWithProxy.proxy + val proxied = proxiedWithProxy.proxied return ProxyAccountLocal.makeIdentifier( - proxyMetaId = proxy.metaId, + proxyMetaId = proxyMetaAccount.id, chainId = proxied.chainId, proxiedAccountId = proxied.accountId, proxyType = proxy.proxyType diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/BaseAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/BaseAddAccountRepository.kt similarity index 59% rename from feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/BaseAddAccountRepository.kt rename to feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/BaseAddAccountRepository.kt index 0c3b6a7a6a..bf17941a76 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/BaseAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/BaseAddAccountRepository.kt @@ -1,6 +1,7 @@ -package io.novafoundation.nova.feature_account_api.data.repository.addAccount +package io.novafoundation.nova.feature_account_impl.data.repository.addAccount -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.repository.addAccount.AddAccountRepository +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService abstract class BaseAddAccountRepository( private val proxySyncService: ProxySyncService diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/ledger/RealLedgerAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/ledger/RealLedgerAddAccountRepository.kt index 949ea9a4d7..f4f6c93abd 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/ledger/RealLedgerAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/ledger/RealLedgerAddAccountRepository.kt @@ -5,8 +5,10 @@ import io.novafoundation.nova.common.data.secrets.v2.SecretStoreV2 import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.model.chain.account.ChainAccountLocal import io.novafoundation.nova.core_db.model.chain.account.MetaAccountLocal -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.BaseAddAccountRepository +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.addAccount.ledger.LedgerAddAccountRepository +import io.novafoundation.nova.feature_account_api.data.repository.addAccount.ledger.LedgerAddAccountRepository.Payload import io.novafoundation.nova.feature_ledger_api.data.repository.LedgerDerivationPath import io.novafoundation.nova.runtime.ext.accountIdOf import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry @@ -16,7 +18,7 @@ class RealLedgerAddAccountRepository( private val chainRegistry: ChainRegistry, private val secretStoreV2: SecretStoreV2, private val proxySyncService: ProxySyncService, -) : LedgerAddAccountRepository(proxySyncService) { +) : BaseAddAccountRepository(proxySyncService), LedgerAddAccountRepository { override suspend fun addAccountInternal(payload: Payload): Long { return when (payload) { diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/paritySigner/ParitySignerAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/paritySigner/ParitySignerAddAccountRepository.kt index 77f6a49249..d58b26a925 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/paritySigner/ParitySignerAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/paritySigner/ParitySignerAddAccountRepository.kt @@ -3,9 +3,9 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.p import io.novafoundation.nova.core.model.CryptoType import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.model.chain.account.MetaAccountLocal -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.model.PolkadotVaultVariant -import io.novafoundation.nova.feature_account_api.data.repository.addAccount.BaseAddAccountRepository +import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.BaseAddAccountRepository import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import jp.co.soramitsu.fearless_utils.runtime.AccountId diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/RealProxiedAddAccountRepository.kt similarity index 83% rename from feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt rename to feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/RealProxiedAddAccountRepository.kt index 29365870bf..4287e3c0cb 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/RealProxiedAddAccountRepository.kt @@ -4,9 +4,8 @@ import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.model.chain.account.ChainAccountLocal import io.novafoundation.nova.core_db.model.chain.account.MetaAccountLocal import io.novafoundation.nova.core_db.model.chain.account.ProxyAccountLocal -import io.novafoundation.nova.feature_account_api.data.model.ProxiedWithProxy -import io.novafoundation.nova.feature_account_api.domain.account.identity.Identity -import io.novafoundation.nova.feature_account_api.data.repository.addAccount.AddAccountRepository +import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository +import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository.Payload import io.novafoundation.nova.runtime.ext.addressOf import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry @@ -14,15 +13,10 @@ import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry * It's important to extends ProxiedAddAccountRepository from AddAccountRepository instead of BaseAddAccountRepository * since we don't need to sync proxy accounts for this case */ -class ProxiedAddAccountRepository( +class RealProxiedAddAccountRepository( private val accountDao: MetaAccountDao, private val chainRegistry: ChainRegistry -) : AddAccountRepository { - - class Payload( - val proxiedWithProxy: ProxiedWithProxy, - val identity: Identity? - ) +) : ProxiedAddAccountRepository { override suspend fun addAccount(payload: Payload): Long { val position = accountDao.nextAccountPosition() @@ -39,7 +33,6 @@ class ProxiedAddAccountRepository( position: Int ): MetaAccountLocal { val proxied = payload.proxiedWithProxy.proxied - val proxy = payload.proxiedWithProxy.proxy val chain = chainRegistry.getChain(proxied.chainId) return MetaAccountLocal( @@ -49,7 +42,7 @@ class ProxiedAddAccountRepository( ethereumPublicKey = null, ethereumAddress = null, name = payload.identity?.name ?: chain.addressOf(proxied.accountId), - parentMetaId = proxy.metaId, + parentMetaId = payload.proxyMetaId, isSelected = false, position = position, type = MetaAccountLocal.Type.PROXIED, @@ -78,7 +71,7 @@ class ProxiedAddAccountRepository( return ProxyAccountLocal( proxiedMetaId = proxiedMetaId, - proxyMetaId = proxy.metaId, + proxyMetaId = payload.proxyMetaId, chainId = proxied.chainId, proxiedAccountId = proxied.accountId, proxyType = proxy.proxyType diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/JsonAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/JsonAddAccountRepository.kt index 1513108ce3..18a32a3d61 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/JsonAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/JsonAddAccountRepository.kt @@ -2,7 +2,7 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.s import io.novafoundation.nova.common.data.mappers.mapEncryptionToCryptoType import io.novafoundation.nova.common.utils.removeHexPrefix -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.advancedEncryption.AdvancedEncryption import io.novafoundation.nova.feature_account_api.domain.model.AddAccountType import io.novafoundation.nova.feature_account_api.domain.model.ImportJsonMetaData diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/MnemonicAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/MnemonicAddAccountRepository.kt index 56738c682c..686264ed7a 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/MnemonicAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/MnemonicAddAccountRepository.kt @@ -1,6 +1,6 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.advancedEncryption.AdvancedEncryption import io.novafoundation.nova.feature_account_api.domain.model.AddAccountType import io.novafoundation.nova.feature_account_impl.data.repository.datasource.AccountDataSource diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SecretsAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SecretsAddAccountRepository.kt index b7ff9af903..ef4e3224a4 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SecretsAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SecretsAddAccountRepository.kt @@ -2,8 +2,8 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.s import android.database.sqlite.SQLiteConstraintException import io.novafoundation.nova.core.model.CryptoType -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService -import io.novafoundation.nova.feature_account_api.data.repository.addAccount.BaseAddAccountRepository +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.BaseAddAccountRepository import io.novafoundation.nova.feature_account_api.domain.account.advancedEncryption.AdvancedEncryption import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountAlreadyExistsException import io.novafoundation.nova.feature_account_api.domain.model.AddAccountType diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SeedAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SeedAddAccountRepository.kt index fdafbcdc67..85c97a5e84 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SeedAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SeedAddAccountRepository.kt @@ -1,6 +1,6 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.advancedEncryption.AdvancedEncryption import io.novafoundation.nova.feature_account_api.domain.model.AddAccountType import io.novafoundation.nova.feature_account_impl.data.repository.datasource.AccountDataSource diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/watchOnly/WatchOnlyAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/watchOnly/WatchOnlyAddAccountRepository.kt index ac772a3dbb..0c73e58178 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/watchOnly/WatchOnlyAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/watchOnly/WatchOnlyAddAccountRepository.kt @@ -3,8 +3,8 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.w import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.model.chain.account.ChainAccountLocal import io.novafoundation.nova.core_db.model.chain.account.MetaAccountLocal -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService -import io.novafoundation.nova.feature_account_api.data.repository.addAccount.BaseAddAccountRepository +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.BaseAddAccountRepository import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import jp.co.soramitsu.fearless_utils.runtime.AccountId diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ModuleToProxyTypeMatcher.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ModuleToProxyTypeMatcher.kt index e551728e7b..cfc66a2a69 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ModuleToProxyTypeMatcher.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ModuleToProxyTypeMatcher.kt @@ -1,29 +1,29 @@ package io.novafoundation.nova.feature_account_impl.data.signer.proxy import io.novafoundation.nova.common.utils.Modules -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import jp.co.soramitsu.fearless_utils.runtime.metadata.module.Module class ModuleToProxyTypeMatcher(private val module: String) { - fun matchToProxyTypes(proxyTypes: List): ProxyAccount.ProxyType? { + fun matchToProxyTypes(proxyTypes: List): ProxyType? { if (proxyTypes.isEmpty()) return null return proxyTypes.firstOrNull { getModulesSupportedByProxyType(it).isSupporting(module) } } - private fun getModulesSupportedByProxyType(proxyType: ProxyAccount.ProxyType): SupportedModules { + private fun getModulesSupportedByProxyType(proxyType: ProxyType): SupportedModules { return when (proxyType) { - ProxyAccount.ProxyType.Any, - is ProxyAccount.ProxyType.Other -> SupportedModules.AnyModule - - ProxyAccount.ProxyType.NonTransfer -> SupportedModules.SpeificModules(Modules.STAKING, Modules.REFERENDA, Modules.NOMINATION_POOLS) - ProxyAccount.ProxyType.Governance -> SupportedModules.SpeificModules(Modules.REFERENDA) - ProxyAccount.ProxyType.Staking -> SupportedModules.SpeificModules(Modules.STAKING) - ProxyAccount.ProxyType.IdentityJudgement -> SupportedModules.SpeificModules(Modules.IDENTITY) - ProxyAccount.ProxyType.CancelProxy -> SupportedModules.SpeificModules(Modules.PROXY) - ProxyAccount.ProxyType.Auction -> SupportedModules.SpeificModules(Modules.AUCTIONS) - ProxyAccount.ProxyType.NominationPools -> SupportedModules.SpeificModules(Modules.NOMINATION_POOLS) + ProxyType.Any, + is ProxyType.Other -> SupportedModules.AnyModule + + ProxyType.NonTransfer -> SupportedModules.SpeificModules(Modules.STAKING, Modules.REFERENDA, Modules.NOMINATION_POOLS) + ProxyType.Governance -> SupportedModules.SpeificModules(Modules.REFERENDA) + ProxyType.Staking -> SupportedModules.SpeificModules(Modules.STAKING) + ProxyType.IdentityJudgement -> SupportedModules.SpeificModules(Modules.IDENTITY) + ProxyType.CancelProxy -> SupportedModules.SpeificModules(Modules.PROXY) + ProxyType.Auction -> SupportedModules.SpeificModules(Modules.AUCTIONS) + ProxyType.NominationPools -> SupportedModules.SpeificModules(Modules.NOMINATION_POOLS) } } } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedFeeSigner.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedFeeSigner.kt index 80b247b602..6713f92d23 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedFeeSigner.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedFeeSigner.kt @@ -4,8 +4,8 @@ import io.novafoundation.nova.common.utils.toCallInstance import io.novafoundation.nova.feature_account_api.data.signer.SignerProvider import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.extrinsic.signer.FeeSigner import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId @@ -49,7 +49,7 @@ class ProxiedFeeSigner( val modifiedPayloadExtrinsic = payloadExtrinsic.wrapIntoProxyPayload( proxyAccountId = getProxyAccountId(), currentProxyNonce = BigInteger.ZERO, - proxyType = ProxyAccount.ProxyType.Any, + proxyType = ProxyType.Any, callInstance = callInstance ) diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt index 79404825c6..2a2bf428e2 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt @@ -5,16 +5,16 @@ import io.novafoundation.nova.common.utils.chainId import io.novafoundation.nova.common.utils.toCallInstance import io.novafoundation.nova.common.validation.ValidationStatus import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxyExtrinsicValidationRequestBus -import io.novafoundation.nova.feature_account_api.data.repository.ProxyRepository import io.novafoundation.nova.feature_account_api.data.signer.SignerProvider import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount.ProxyType import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_account_api.domain.model.requireAddressIn import io.novafoundation.nova.feature_account_api.presenatation.account.proxy.ProxySigningPresenter import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxiedExtrinsicValidationFailure.ProxyNotEnoughFee import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxiedExtrinsicValidationPayload +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.ext.commissionAsset import io.novafoundation.nova.runtime.extrinsic.signer.NovaSigner import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry @@ -31,7 +31,7 @@ class ProxiedSignerFactory( private val chainRegistry: ChainRegistry, private val accountRepository: AccountRepository, private val proxySigningPresenter: ProxySigningPresenter, - private val proxyRepository: ProxyRepository, + private val getProxyRepository: GetProxyRepository, private val rpcCalls: RpcCalls, private val proxyExtrinsicValidationEventBus: ProxyExtrinsicValidationRequestBus ) { @@ -43,7 +43,7 @@ class ProxiedSignerFactory( accountRepository = accountRepository, signerProvider = signerProvider, proxySigningPresenter = proxySigningPresenter, - proxyRepository = proxyRepository, + getProxyRepository = getProxyRepository, rpcCalls = rpcCalls, proxyExtrinsicValidationEventBus = proxyExtrinsicValidationEventBus, isRootProxied = isRoot @@ -57,7 +57,7 @@ class ProxiedSigner( private val accountRepository: AccountRepository, private val signerProvider: SignerProvider, private val proxySigningPresenter: ProxySigningPresenter, - private val proxyRepository: ProxyRepository, + private val getProxyRepository: GetProxyRepository, private val rpcCalls: RpcCalls, private val proxyExtrinsicValidationEventBus: ProxyExtrinsicValidationRequestBus, private val isRootProxied: Boolean @@ -124,7 +124,7 @@ class ProxiedSigner( val proxyAccountId = proxyMetaAccount.requireAccountIdIn(chain) val proxiedAccountId = proxiedMetaAccount.requireAccountIdIn(chain) - val availableProxyTypes = proxyRepository.getDelegatedProxyTypes( + val availableProxyTypes = getProxyRepository.getDelegatedProxyTypes( chainId = payload.chainId, proxiedAccountId = proxiedAccountId, proxyAccountId = proxyAccountId diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/SignerPayloadModifierExt.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/SignerPayloadModifierExt.kt index 12ede274f2..8aa9eda85d 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/SignerPayloadModifierExt.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/SignerPayloadModifierExt.kt @@ -1,7 +1,7 @@ package io.novafoundation.nova.feature_account_impl.data.signer.proxy import io.novafoundation.nova.common.utils.Modules -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.extrinsic.multi.SimpleCallBuilder import jp.co.soramitsu.fearless_utils.runtime.AccountId import jp.co.soramitsu.fearless_utils.runtime.RuntimeSnapshot @@ -17,7 +17,7 @@ import java.math.BigInteger fun SignerPayloadExtrinsic.wrapIntoProxyPayload( proxyAccountId: AccountId, currentProxyNonce: BigInteger, - proxyType: ProxyAccount.ProxyType, + proxyType: ProxyType, callInstance: CallRepresentation.Instance ): SignerPayloadExtrinsic { val proxiedAccountId = accountId diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureComponent.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureComponent.kt index 624415e608..fb2a99047c 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureComponent.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureComponent.kt @@ -42,6 +42,7 @@ import io.novafoundation.nova.feature_account_impl.presentation.pincode.di.PinCo import io.novafoundation.nova.feature_account_impl.presentation.watchOnly.change.di.ChangeWatchAccountComponent import io.novafoundation.nova.feature_account_impl.presentation.watchOnly.create.di.CreateWatchWalletComponent import io.novafoundation.nova.feature_currency_api.di.CurrencyFeatureApi +import io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi import io.novafoundation.nova.feature_versions_api.di.VersionsFeatureApi import io.novafoundation.nova.runtime.di.RuntimeApi import io.novafoundation.nova.web3names.di.Web3NamesApi @@ -128,6 +129,7 @@ interface AccountFeatureComponent : AccountFeatureApi { CommonApi::class, RuntimeApi::class, CurrencyFeatureApi::class, + ProxyFeatureApi::class, DbApi::class, VersionsFeatureApi::class, Web3NamesApi::class diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureDependencies.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureDependencies.kt index 8848ee5d22..d9d1ae5c7c 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureDependencies.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureDependencies.kt @@ -33,6 +33,7 @@ import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.dao.NodeDao import io.novafoundation.nova.feature_currency_api.domain.CurrencyInteractor import io.novafoundation.nova.feature_currency_api.domain.interfaces.CurrencyRepository +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_versions_api.domain.UpdateNotificationsInteractor import io.novafoundation.nova.runtime.di.REMOTE_STORAGE_SOURCE import io.novafoundation.nova.runtime.ethereum.gas.GasPriceProviderFactory @@ -118,6 +119,8 @@ interface AccountFeatureDependencies { fun computationalCache(): ComputationalCache + fun getProxyRepository(): GetProxyRepository + val systemCallExecutor: SystemCallExecutor val multiChainQrSharingFactory: MultiChainQrSharingFactory diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureHolder.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureHolder.kt index 7037bd70ad..1ad2bf2063 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureHolder.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureHolder.kt @@ -11,6 +11,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.sign.LedgerSignC import io.novafoundation.nova.feature_account_impl.data.signer.paritySigner.PolkadotVaultVariantSignCommunicator import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter import io.novafoundation.nova.feature_currency_api.di.CurrencyFeatureApi +import io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi import io.novafoundation.nova.feature_versions_api.di.VersionsFeatureApi import io.novafoundation.nova.runtime.di.RuntimeApi import io.novafoundation.nova.web3names.di.Web3NamesApi @@ -33,6 +34,7 @@ class AccountFeatureHolder @Inject constructor( .dbApi(getFeature(DbApi::class.java)) .runtimeApi(getFeature(RuntimeApi::class.java)) .currencyFeatureApi(getFeature(CurrencyFeatureApi::class.java)) + .proxyFeatureApi(getFeature(ProxyFeatureApi::class.java)) .versionsFeatureApi(getFeature(VersionsFeatureApi::class.java)) .web3NamesApi(getFeature(Web3NamesApi::class.java)) .build() diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt index 503f242aec..374a0328da 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt @@ -28,10 +28,10 @@ import io.novafoundation.nova.runtime.ethereum.gas.GasPriceProviderFactory import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.EvmTransactionService import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService import io.novafoundation.nova.feature_account_api.data.proxy.MetaAccountsUpdatesRegistry -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository -import io.novafoundation.nova.feature_account_api.data.repository.ProxyRepository +import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository import io.novafoundation.nova.feature_account_api.data.signer.SignerProvider +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor @@ -54,10 +54,8 @@ import io.novafoundation.nova.feature_account_impl.data.ethereum.transaction.Rea import io.novafoundation.nova.feature_account_impl.data.extrinsic.RealExtrinsicService import io.novafoundation.nova.feature_account_impl.data.network.blockchain.AccountSubstrateSource import io.novafoundation.nova.feature_account_impl.data.network.blockchain.AccountSubstrateSourceImpl -import io.novafoundation.nova.feature_account_impl.data.proxy.RealProxySyncService import io.novafoundation.nova.feature_account_impl.data.repository.AccountRepositoryImpl import io.novafoundation.nova.feature_account_impl.data.repository.RealOnChainIdentityRepository -import io.novafoundation.nova.feature_account_impl.data.repository.RealProxyRepository import io.novafoundation.nova.feature_account_impl.data.repository.datasource.AccountDataSource import io.novafoundation.nova.feature_account_impl.data.repository.datasource.AccountDataSourceImpl import io.novafoundation.nova.feature_account_impl.data.repository.datasource.migration.AccountDataMigration @@ -75,16 +73,13 @@ import io.novafoundation.nova.feature_account_impl.domain.account.advancedEncryp import io.novafoundation.nova.feature_account_api.domain.account.common.EncryptionDefaults import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.account.identity.OnChainIdentity -import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor import io.novafoundation.nova.feature_account_impl.data.proxy.RealMetaAccountsUpdatesRegistry -import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.proxied.ProxiedAddAccountRepository +import io.novafoundation.nova.feature_account_impl.data.proxy.sync.RealProxySyncService import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.JsonAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.MnemonicAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.SeedAddAccountRepository import io.novafoundation.nova.feature_account_impl.di.modules.ProxySigningModule import io.novafoundation.nova.feature_account_impl.domain.account.details.WalletDetailsInteractor -import io.novafoundation.nova.feature_account_impl.domain.proxy.RealAddProxyInteractor -import io.novafoundation.nova.feature_account_impl.domain.proxy.common.ProxyDepositCalculator import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.DelegatedMetaAccountUpdatesListingMixinFactory import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountTypePresentationMapper @@ -100,6 +95,7 @@ import io.novafoundation.nova.feature_account_impl.presentation.mixin.identity.R import io.novafoundation.nova.feature_account_impl.presentation.mixin.selectWallet.RealRealSelectWalletMixinFactory import io.novafoundation.nova.feature_account_impl.presentation.paritySigner.config.RealPolkadotVaultVariantConfigProvider import io.novafoundation.nova.feature_currency_api.domain.interfaces.CurrencyRepository +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.runtime.di.REMOTE_STORAGE_SOURCE import io.novafoundation.nova.runtime.extrinsic.ExtrinsicBuilderFactory import io.novafoundation.nova.runtime.extrinsic.multi.ExtrinsicSplitter @@ -133,35 +129,6 @@ class AccountFeatureModule { preferences: Preferences ): MetaAccountsUpdatesRegistry = RealMetaAccountsUpdatesRegistry(preferences) - @Provides - @FeatureScope - fun provideProxyRepository( - @Named(REMOTE_STORAGE_SOURCE) storageDataSource: StorageDataSource, - chainRegistry: ChainRegistry - ): ProxyRepository = RealProxyRepository(storageDataSource, chainRegistry) - - @Provides - @FeatureScope - fun provideProxySyncService( - chainRegistry: ChainRegistry, - proxyRepository: ProxyRepository, - accounRepository: AccountRepository, - metaAccountDao: MetaAccountDao, - @OnChainIdentity identityProvider: IdentityProvider, - metaAccountsUpdatesRegistry: MetaAccountsUpdatesRegistry, - proxiedAddAccountRepository: ProxiedAddAccountRepository, - rootScope: RootScope - ): ProxySyncService = RealProxySyncService( - chainRegistry, - proxyRepository, - accounRepository, - metaAccountDao, - identityProvider, - metaAccountsUpdatesRegistry, - proxiedAddAccountRepository, - rootScope - ) - @Provides @FeatureScope fun provideEncryptionDefaults(): EncryptionDefaults = EncryptionDefaults( @@ -512,15 +479,23 @@ class AccountFeatureModule { @Provides @FeatureScope - fun provideProxyDepositCalculator( - chainRegistry: ChainRegistry - ) = ProxyDepositCalculator(chainRegistry) - - @Provides - @FeatureScope - fun provideAddProxyInteractor( - extrinsicService: ExtrinsicService, - proxyRepository: ProxyRepository, - proxyDepositCalculator: ProxyDepositCalculator - ): AddProxyInteractor = RealAddProxyInteractor(extrinsicService, proxyDepositCalculator, proxyRepository) + fun provideProxySyncService( + chainRegistry: ChainRegistry, + getProxyRepository: GetProxyRepository, + accounRepository: AccountRepository, + metaAccountDao: MetaAccountDao, + @OnChainIdentity identityProvider: IdentityProvider, + metaAccountsUpdatesRegistry: MetaAccountsUpdatesRegistry, + proxiedAddAccountRepository: ProxiedAddAccountRepository, + rootScope: RootScope + ): ProxySyncService = RealProxySyncService( + chainRegistry, + getProxyRepository, + accounRepository, + metaAccountDao, + identityProvider, + metaAccountsUpdatesRegistry, + proxiedAddAccountRepository, + rootScope + ) } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AddAccountsModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AddAccountsModule.kt index ac8cc8c5f8..d4e9636229 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AddAccountsModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AddAccountsModule.kt @@ -5,13 +5,14 @@ import dagger.Provides import io.novafoundation.nova.common.data.secrets.v2.SecretStoreV2 import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.core_db.dao.MetaAccountDao -import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.addAccount.ledger.LedgerAddAccountRepository +import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.datasource.AccountDataSource import io.novafoundation.nova.feature_account_impl.data.secrets.AccountSecretsFactory import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.ledger.RealLedgerAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.paritySigner.ParitySignerAddAccountRepository -import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.proxied.ProxiedAddAccountRepository +import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.proxied.RealProxiedAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.JsonAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.MnemonicAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.SeedAddAccountRepository @@ -93,7 +94,7 @@ class AddAccountsModule { fun provideProxiedAddAccountRepository( accountDao: MetaAccountDao, chainRegistry: ChainRegistry - ) = ProxiedAddAccountRepository( + ): ProxiedAddAccountRepository = RealProxiedAddAccountRepository( accountDao, chainRegistry ) diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/modules/signers/ProxiedSignerModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/modules/signers/ProxiedSignerModule.kt index 33e103dbf8..68c30b014b 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/modules/signers/ProxiedSignerModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/modules/signers/ProxiedSignerModule.kt @@ -3,11 +3,11 @@ package io.novafoundation.nova.feature_account_impl.di.modules.signers import dagger.Module import dagger.Provides import io.novafoundation.nova.common.di.scope.FeatureScope -import io.novafoundation.nova.feature_account_api.data.repository.ProxyRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.presenatation.account.proxy.ProxySigningPresenter import io.novafoundation.nova.feature_account_impl.data.signer.proxy.ProxiedSignerFactory import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxyExtrinsicValidationRequestBus +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.network.rpc.RpcCalls @@ -24,7 +24,7 @@ class ProxiedSignerModule { chainRegistry: ChainRegistry, accountRepository: AccountRepository, proxySigningPresenter: ProxySigningPresenter, - proxyRepository: ProxyRepository, + proxyRepository: GetProxyRepository, rpcCalls: RpcCalls, proxyExtrinsicValidationRequestBus: ProxyExtrinsicValidationRequestBus, ) = ProxiedSignerFactory( diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/validation/proxy/AddProxyValidationSystem.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/validation/proxy/AddProxyValidationSystem.kt deleted file mode 100644 index ce848bb24f..0000000000 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/validation/proxy/AddProxyValidationSystem.kt +++ /dev/null @@ -1,54 +0,0 @@ -package io.novafoundation.nova.feature_account_impl.domain.validation.proxy - -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.validation.NotEnoughToPayFeesError - -package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy - -import io.novafoundation.nova.common.validation.ValidationSystem -import io.novafoundation.nova.common.validation.ValidationSystemBuilder -import io.novafoundation.nova.feature_account_api.data.model.Fee -import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository -import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain -import java.math.BigDecimal - -class AddProxyValidationPayload( - val chain: Chain, - val asset: Asset, - val address: String, - val fee: Fee, - val deposit: Balance -) - -sealed class AddProxyValidationFailure { - - class NotEnoughToPayFee( - override val chainAsset: Chain.Asset, - override val maxUsable: BigDecimal, - override val fee: BigDecimal - ) : AddProxyValidationFailure(), NotEnoughToPayFeesError - - class NotEnoughBalanceToReserveDeposit( - val chainAsset: Chain.Asset, - val maxUsable: Balance, - val deposit: Balance - ) : AddProxyValidationFailure() - - class InvalidAddress(val chain: Chain) : AddProxyValidationFailure() - -} - -typealias AddProxyValidationSystem = ValidationSystem -typealias AddProxyValidationSystemBuilder = ValidationSystemBuilder - -fun AddProxyValidationSystemBuilder.controllerAccountAccess(accountRepository: AccountRepository, stakingSharedState: StakingSharedState) { - return validate( - ControllerRequiredValidation( - accountRepository = accountRepository, - accountAddressExtractor = { it.controllerAddress }, - sharedState = stakingSharedState, - errorProducer = { ChangeStackingValidationFailure.NO_ACCESS_TO_CONTROLLER_ACCOUNT } - ) - ) -} diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/common/listing/ProxyFormatter.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/common/listing/ProxyFormatter.kt index e5aed65682..06bb0eaec6 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/common/listing/ProxyFormatter.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/common/listing/ProxyFormatter.kt @@ -14,6 +14,7 @@ import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase import io.novafoundation.nova.feature_account_impl.R +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType class ProxyFormatter( private val walletUiUseCase: WalletUiUseCase, @@ -41,17 +42,17 @@ class ProxyFormatter( .append(proxyAccountName, colorSpan(resourceManager.getColor(R.color.text_primary))) } - fun mapProxyTypeToString(type: ProxyAccount.ProxyType): String { + fun mapProxyTypeToString(type: ProxyType): String { val proxyType = when (type) { - ProxyAccount.ProxyType.Any -> resourceManager.getString(R.string.account_proxy_type_any) - ProxyAccount.ProxyType.NonTransfer -> resourceManager.getString(R.string.account_proxy_type_non_transfer) - ProxyAccount.ProxyType.Governance -> resourceManager.getString(R.string.account_proxy_type_governance) - ProxyAccount.ProxyType.Staking -> resourceManager.getString(R.string.account_proxy_type_staking) - ProxyAccount.ProxyType.IdentityJudgement -> resourceManager.getString(R.string.account_proxy_type_identity_judgement) - ProxyAccount.ProxyType.CancelProxy -> resourceManager.getString(R.string.account_proxy_type_cancel_proxy) - ProxyAccount.ProxyType.Auction -> resourceManager.getString(R.string.account_proxy_type_auction) - ProxyAccount.ProxyType.NominationPools -> resourceManager.getString(R.string.account_proxy_type_nomination_pools) - is ProxyAccount.ProxyType.Other -> type.name.splitCamelCase().joinToString { it.capitalize() } + ProxyType.Any -> resourceManager.getString(R.string.account_proxy_type_any) + ProxyType.NonTransfer -> resourceManager.getString(R.string.account_proxy_type_non_transfer) + ProxyType.Governance -> resourceManager.getString(R.string.account_proxy_type_governance) + ProxyType.Staking -> resourceManager.getString(R.string.account_proxy_type_staking) + ProxyType.IdentityJudgement -> resourceManager.getString(R.string.account_proxy_type_identity_judgement) + ProxyType.CancelProxy -> resourceManager.getString(R.string.account_proxy_type_cancel_proxy) + ProxyType.Auction -> resourceManager.getString(R.string.account_proxy_type_auction) + ProxyType.NominationPools -> resourceManager.getString(R.string.account_proxy_type_nomination_pools) + is ProxyType.Other -> type.name.splitCamelCase().joinToString { it.capitalize() } } return resourceManager.getString(R.string.proxy_wallet_type, proxyType) diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/proxy/sign/RealProxySigningPresenter.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/proxy/sign/RealProxySigningPresenter.kt index ccd55fdb37..5c023e6f23 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/proxy/sign/RealProxySigningPresenter.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/proxy/sign/RealProxySigningPresenter.kt @@ -10,10 +10,10 @@ import io.novafoundation.nova.common.utils.toSpannable import io.novafoundation.nova.common.view.dialog.dialog import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount import io.novafoundation.nova.feature_account_api.presenatation.account.proxy.ProxySigningPresenter import io.novafoundation.nova.feature_account_impl.R import io.novafoundation.nova.feature_account_impl.presentation.common.sign.notSupported.SigningNotSupportedPresentable +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_wallet_api.domain.model.amountFromPlanks import io.novafoundation.nova.feature_wallet_api.presentation.formatters.formatTokenAmount import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain @@ -54,7 +54,7 @@ class RealProxySigningPresenter( override suspend fun notEnoughPermission( proxiedMetaAccount: MetaAccount, proxyMetaAccount: MetaAccount, - proxyTypes: List + proxyTypes: List ) = withContext(Dispatchers.Main) { suspendCoroutine { continuation -> ProxySignNotEnoughPermissionBottomSheet( @@ -121,7 +121,7 @@ class RealProxySigningPresenter( private fun formatNotEnoughPermissionWarning( proxiedMetaAccount: MetaAccount, proxyMetaAccount: MetaAccount, - proxyTypes: List + proxyTypes: List ): CharSequence { val subtitle = resourceManager.getString(R.string.proxy_signing_not_enough_permission_message) val primaryColor = resourceManager.getColor(R.color.text_primary) diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/TransferAssetValidationFailureUi.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/TransferAssetValidationFailureUi.kt index ce17b8fc56..24d4208e10 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/TransferAssetValidationFailureUi.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/TransferAssetValidationFailureUi.kt @@ -6,7 +6,7 @@ import io.novafoundation.nova.common.validation.TransformedFailure.Default import io.novafoundation.nova.common.validation.ValidationFlowActions import io.novafoundation.nova.common.validation.ValidationStatus import io.novafoundation.nova.common.validation.asDefault -import io.novafoundation.nova.feature_account_api.domain.validation.proxy.handleSystemAccountValidationFailure +import io.novafoundation.nova.feature_account_api.domain.validation.handleSystemAccountValidationFailure import io.novafoundation.nova.feature_assets.R import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.AssetTransferPayload import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.AssetTransferValidationFailure diff --git a/feature-proxy-api/.gitignore b/feature-proxy-api/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/feature-proxy-api/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature-proxy-api/build.gradle b/feature-proxy-api/build.gradle new file mode 100644 index 0000000000..8844dda1bf --- /dev/null +++ b/feature-proxy-api/build.gradle @@ -0,0 +1,31 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion rootProject.compileSdkVersion + + defaultConfig { + minSdkVersion rootProject.minSdkVersion + targetSdkVersion rootProject.targetSdkVersion + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + + kotlinOptions { + jvmTarget = '1.8' + freeCompilerArgs = ["-Xcontext-receivers"] + } +} + +dependencies { + implementation project(":common") + implementation project(':runtime') + + implementation fearlessLibDep +} \ No newline at end of file diff --git a/feature-proxy-api/consumer-rules.pro b/feature-proxy-api/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/feature-proxy-api/proguard-rules.pro b/feature-proxy-api/proguard-rules.pro new file mode 100644 index 0000000000..481bb43481 --- /dev/null +++ b/feature-proxy-api/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature-proxy-api/src/main/AndroidManifest.xml b/feature-proxy-api/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..10c74f4bde --- /dev/null +++ b/feature-proxy-api/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + \ No newline at end of file diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/network/blockchain/bindings/calls/ExtrinsicBuilderExt.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt similarity index 77% rename from feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/network/blockchain/bindings/calls/ExtrinsicBuilderExt.kt rename to feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt index a12adc00b7..f948b3d2ac 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/network/blockchain/bindings/calls/ExtrinsicBuilderExt.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt @@ -1,7 +1,7 @@ -package io.novafoundation.nova.feature_account_impl.data.network.blockchain.bindings.calls +package io.novafoundation.nova.feature_proxy_api.data.calls import io.novafoundation.nova.common.utils.Modules -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import java.math.BigInteger import jp.co.soramitsu.fearless_utils.runtime.AccountId import jp.co.soramitsu.fearless_utils.runtime.definitions.types.composite.DictEnum @@ -9,7 +9,7 @@ import jp.co.soramitsu.fearless_utils.runtime.definitions.types.instances.Addres import jp.co.soramitsu.fearless_utils.runtime.extrinsic.ExtrinsicBuilder -fun ExtrinsicBuilder.addProxyCall(proxyAccountId: AccountId, proxyType: ProxyAccount.ProxyType): ExtrinsicBuilder { +fun ExtrinsicBuilder.addProxyCall(proxyAccountId: AccountId, proxyType: ProxyType): ExtrinsicBuilder { return call( Modules.PROXY, "add_proxy", diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt new file mode 100644 index 0000000000..de018dc158 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt @@ -0,0 +1,20 @@ +package io.novafoundation.nova.feature_proxy_api.data.common + +import io.novafoundation.nova.common.utils.numberConstant +import io.novafoundation.nova.common.utils.proxy +import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import io.novafoundation.nova.runtime.multiNetwork.getRuntime +import java.math.BigInteger + +class DepositBaseAndFactor( + val baseAmount: BigInteger, + val factorAmount: BigInteger +) + +interface ProxyDepositCalculator { + + suspend fun getDepositConstants(chain: Chain): DepositBaseAndFactor + + fun calculateProxyDeposit(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger +} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/model/ProxiedWithProxy.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxiedWithProxy.kt similarity index 81% rename from feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/model/ProxiedWithProxy.kt rename to feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxiedWithProxy.kt index 887e97763c..c6e43fb500 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/model/ProxiedWithProxy.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxiedWithProxy.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_account_api.data.model +package io.novafoundation.nova.feature_proxy_api.data.model import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import jp.co.soramitsu.fearless_utils.runtime.AccountId @@ -14,7 +14,6 @@ class ProxiedWithProxy( class Proxy( val accountId: AccountId, - val metaId: Long, val proxyType: String ) } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt new file mode 100644 index 0000000000..560c67ad80 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt @@ -0,0 +1,16 @@ +package io.novafoundation.nova.feature_proxy_api.data.repository + +import io.novafoundation.nova.common.address.AccountIdKey +import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +interface GetProxyRepository { + + suspend fun getAllProxiesForAccounts(chainId: ChainId, accountIds: Set): List + + suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List + + suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int +} diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/di/ProxyFeatureApi.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/di/ProxyFeatureApi.kt new file mode 100644 index 0000000000..12ed8cdf61 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/di/ProxyFeatureApi.kt @@ -0,0 +1,11 @@ +package io.novafoundation.nova.feature_proxy_api.di + +import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository + +interface ProxyFeatureApi { + + val proxyRepository: GetProxyRepository + + val proxyDepositCalculator: ProxyDepositCalculator +} diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyType.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyType.kt new file mode 100644 index 0000000000..cf6d12b013 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyType.kt @@ -0,0 +1,38 @@ +package io.novafoundation.nova.feature_proxy_api.domain.model + +sealed class ProxyType(val name: String) { + + object Any : ProxyType("Any") + + object NonTransfer : ProxyType("NonTransfer") + + object Governance : ProxyType("Governance") + + object Staking : ProxyType("Staking") + + object IdentityJudgement : ProxyType("IdentityJudgement") + + object CancelProxy : ProxyType("CancelProxy") + + object Auction : ProxyType("Auction") + + object NominationPools : ProxyType("NominationPools") + + class Other(name: String) : ProxyType(name) + + companion object +} + +fun ProxyType.Companion.fromString(name: String): ProxyType { + return when (name) { + "Any" -> ProxyType.Any + "NonTransfer" -> ProxyType.NonTransfer + "Governance" -> ProxyType.Governance + "Staking" -> ProxyType.Staking + "IdentityJudgement" -> ProxyType.IdentityJudgement + "CancelProxy" -> ProxyType.CancelProxy + "Auction" -> ProxyType.Auction + "NominationPools" -> ProxyType.NominationPools + else -> ProxyType.Other(name) + } +} diff --git a/feature-proxy-impl/.gitignore b/feature-proxy-impl/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/feature-proxy-impl/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature-proxy-impl/build.gradle b/feature-proxy-impl/build.gradle new file mode 100644 index 0000000000..c2024b6284 --- /dev/null +++ b/feature-proxy-impl/build.gradle @@ -0,0 +1,66 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' +apply plugin: 'kotlin-android-extensions' +apply from: '../tests.gradle' +apply from: '../scripts/secrets.gradle' + +android { + compileSdkVersion rootProject.compileSdkVersion + namespace 'io.novafoundation.nova.feature_proxy' + + defaultConfig { + minSdkVersion rootProject.minSdkVersion + targetSdkVersion rootProject.targetSdkVersion + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + + kotlinOptions { + jvmTarget = '1.8' + freeCompilerArgs = ["-Xcontext-receivers"] + } +} + +dependencies { + implementation project(':common') + implementation project(':runtime') + implementation project(':feature-proxy-api') + + implementation kotlinDep + + implementation androidDep + implementation materialDep + implementation constraintDep + + implementation coroutinesDep + implementation coroutinesAndroidDep + implementation viewModelKtxDep + implementation lifeCycleKtxDep + + implementation daggerDep + kapt daggerKapt + + testImplementation jUnitDep + testImplementation mockitoDep + + implementation insetterDep + + implementation shimmerDep + + androidTestImplementation androidTestRunnerDep + androidTestImplementation androidTestRulesDep + androidTestImplementation androidJunitDep +} \ No newline at end of file diff --git a/feature-proxy-impl/consumer-rules.pro b/feature-proxy-impl/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/feature-proxy-impl/proguard-rules.pro b/feature-proxy-impl/proguard-rules.pro new file mode 100644 index 0000000000..481bb43481 --- /dev/null +++ b/feature-proxy-impl/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature-proxy-impl/src/main/AndroidManifest.xml b/feature-proxy-impl/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..10728cc703 --- /dev/null +++ b/feature-proxy-impl/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/common/ProxyDepositCalculator.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt similarity index 58% rename from feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/common/ProxyDepositCalculator.kt rename to feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt index 4c9bf72394..275d33e15b 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/common/ProxyDepositCalculator.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt @@ -1,25 +1,19 @@ -package io.novafoundation.nova.feature_account_impl.domain.proxy.common +package io.novafoundation.nova.feature_proxy_impl.data.common import io.novafoundation.nova.common.utils.numberConstant import io.novafoundation.nova.common.utils.proxy -import io.novafoundation.nova.feature_account_api.data.repository.ProxyRepository -import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance +import io.novafoundation.nova.feature_proxy_api.data.common.DepositBaseAndFactor +import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.multiNetwork.getRuntime import java.math.BigInteger -import jp.co.soramitsu.fearless_utils.runtime.AccountId -class DepositBaseAndFactor( - val baseAmount: Balance, - val factorAmount: Balance -) - -class ProxyDepositCalculator( +class RealProxyDepositCalculator( private val chainRegestry: ChainRegistry -) { +) : ProxyDepositCalculator { - suspend fun getDepositConstants(chain: Chain): DepositBaseAndFactor { + override suspend fun getDepositConstants(chain: Chain): DepositBaseAndFactor { val runtime = chainRegestry.getRuntime(chain.id) val constantQuery = runtime.metadata.proxy() return DepositBaseAndFactor( @@ -28,9 +22,9 @@ class ProxyDepositCalculator( ) } - fun calculateProxyDeposit(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): Balance { + override fun calculateProxyDeposit(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger { return if (proxiesCount == 0) { - Balance.ZERO + BigInteger.ZERO } else { baseAndFactor.baseAmount + baseAndFactor.factorAmount * proxiesCount.toBigInteger() } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/RealProxyRepository.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt similarity index 76% rename from feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/RealProxyRepository.kt rename to feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt index 4641aa9eb7..6f7b0c9e6d 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/RealProxyRepository.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_account_impl.data.repository +package io.novafoundation.nova.feature_proxy_impl.data.repository import io.novafoundation.nova.common.address.AccountIdKey import io.novafoundation.nova.common.address.intoKey @@ -7,11 +7,10 @@ import io.novafoundation.nova.common.data.network.runtime.binding.castToList import io.novafoundation.nova.common.data.network.runtime.binding.castToStruct import io.novafoundation.nova.common.data.network.runtime.binding.getTyped import io.novafoundation.nova.common.utils.Modules -import io.novafoundation.nova.feature_account_api.data.model.ProxiedWithProxy -import io.novafoundation.nova.feature_account_api.data.repository.ProxyRepository -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountId -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount -import io.novafoundation.nova.feature_account_impl.data.mappers.mapProxyTypeToString +import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.feature_proxy_api.domain.model.fromString import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import io.novafoundation.nova.runtime.storage.source.StorageDataSource @@ -26,20 +25,18 @@ private class OnChainProxyModel( val delay: BigInteger ) -class RealProxyRepository( +class RealGetProxyRepository( private val remoteSource: StorageDataSource, private val chainRegistry: ChainRegistry -) : ProxyRepository { +) : GetProxyRepository { - override suspend fun getAllProxiesForMetaAccounts(chainId: ChainId, metaAccountIds: List): List { + override suspend fun getAllProxiesForAccounts(chainId: ChainId, accountIds: Set): List { val delegatorToProxies = receiveAllProxies(chainId) - val accountIdToMetaAccounts = metaAccountIds.groupBy { it.accountId.intoKey() } - return delegatorToProxies .mapNotNull { (delegator, proxies) -> val notDelayedProxies = proxies.filter { it.delay == BigInteger.ZERO } - val matchedProxies = matchProxiesToAccountsAndMap(notDelayedProxies, accountIdToMetaAccounts) + val matchedProxies = matchProxiesToAccountsAndMap(notDelayedProxies, accountIds) if (matchedProxies.isEmpty()) return@mapNotNull null @@ -49,11 +46,11 @@ class RealProxyRepository( } } - override suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List { + override suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List { val proxies = getAllProxiesFor(chainId, proxiedAccountId) return proxies.filter { it.accountId == proxyAccountId.intoKey() } - .map { mapProxyTypeToString(it.proxyType) } + .map { ProxyType.fromString(it.proxyType) } } override suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int { @@ -124,18 +121,15 @@ class RealProxyRepository( private fun matchProxiesToAccountsAndMap( proxies: List, - accountIdToMetaAccounts: Map> + accountIdToMetaAccounts: Set ): List { - return proxies.flatMap { onChainProxy -> - val matchedAccounts = accountIdToMetaAccounts[onChainProxy.accountId] ?: return@flatMap emptyList() - - matchedAccounts.map { - ProxiedWithProxy.Proxy( - accountId = onChainProxy.accountId.value, - metaId = it.metaId, - proxyType = onChainProxy.proxyType - ) - } + return proxies.filter { + accountIdToMetaAccounts.contains(it.accountId) + }.map { onChainProxy -> + ProxiedWithProxy.Proxy( + accountId = onChainProxy.accountId.value, + proxyType = onChainProxy.proxyType + ) } } } diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureComponent.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureComponent.kt new file mode 100644 index 0000000000..51109907b3 --- /dev/null +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureComponent.kt @@ -0,0 +1,35 @@ +package io.novafoundation.nova.feature_proxy_impl.di + +import dagger.Component +import io.novafoundation.nova.common.di.CommonApi +import io.novafoundation.nova.common.di.scope.FeatureScope +import io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi +import io.novafoundation.nova.runtime.di.RuntimeApi + +@Component( + dependencies = [ + ProxyFeatureDependencies::class + ], + modules = [ + ProxyFeatureModule::class, + ] +) +@FeatureScope +interface ProxyFeatureComponent : ProxyFeatureApi { + + @Component.Factory + interface Factory { + + fun create( + deps: ProxyFeatureDependencies + ): ProxyFeatureComponent + } + + @Component( + dependencies = [ + CommonApi::class, + RuntimeApi::class + ] + ) + interface VoteFeatureDependenciesComponent : ProxyFeatureDependencies +} diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureDependencies.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureDependencies.kt new file mode 100644 index 0000000000..15efb8b851 --- /dev/null +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureDependencies.kt @@ -0,0 +1,18 @@ +package io.novafoundation.nova.feature_proxy_impl.di + +import io.novafoundation.nova.runtime.di.LOCAL_STORAGE_SOURCE +import io.novafoundation.nova.runtime.di.REMOTE_STORAGE_SOURCE +import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry +import io.novafoundation.nova.runtime.storage.source.StorageDataSource +import javax.inject.Named + +interface ProxyFeatureDependencies { + + @Named(REMOTE_STORAGE_SOURCE) + fun remoteStorageSource(): StorageDataSource + + @Named(LOCAL_STORAGE_SOURCE) + fun localStorageSource(): StorageDataSource + + fun chainRegistry(): ChainRegistry +} diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureHolder.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureHolder.kt new file mode 100644 index 0000000000..055221d857 --- /dev/null +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureHolder.kt @@ -0,0 +1,24 @@ +package io.novafoundation.nova.feature_proxy_impl.di + +import io.novafoundation.nova.common.di.FeatureApiHolder +import io.novafoundation.nova.common.di.FeatureContainer +import io.novafoundation.nova.common.di.scope.ApplicationScope +import io.novafoundation.nova.feature_proxy_impl.di.DaggerProxyFeatureComponent +import io.novafoundation.nova.feature_proxy_impl.di.DaggerProxyFeatureComponent_VoteFeatureDependenciesComponent +import io.novafoundation.nova.runtime.di.RuntimeApi +import javax.inject.Inject + +@ApplicationScope +class ProxyFeatureHolder @Inject constructor( + featureContainer: FeatureContainer +) : FeatureApiHolder(featureContainer) { + + override fun initializeDependencies(): Any { + val dependencies = DaggerProxyFeatureComponent_VoteFeatureDependenciesComponent.builder() + .commonApi(commonApi()) + .runtimeApi(getFeature(RuntimeApi::class.java)) + .build() + return DaggerProxyFeatureComponent.factory() + .create(dependencies) + } +} diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt new file mode 100644 index 0000000000..b60a4b649a --- /dev/null +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt @@ -0,0 +1,33 @@ +package io.novafoundation.nova.feature_proxy_impl.di + +import dagger.Module +import dagger.Provides +import io.novafoundation.nova.common.di.scope.FeatureScope +import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_impl.data.common.RealProxyDepositCalculator +import io.novafoundation.nova.feature_proxy_impl.data.repository.RealGetProxyRepository +import io.novafoundation.nova.runtime.di.REMOTE_STORAGE_SOURCE +import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry +import io.novafoundation.nova.runtime.storage.source.StorageDataSource +import javax.inject.Named + +@Module +class ProxyFeatureModule { + + @Provides + @FeatureScope + fun provideProxyRepository( + @Named(REMOTE_STORAGE_SOURCE) storageDataSource: StorageDataSource, + chainRegistry: ChainRegistry + ): GetProxyRepository = RealGetProxyRepository( + storageDataSource, + chainRegistry + ) + + @Provides + @FeatureScope + fun provideProxyDepositCalculator(chainRegistry: ChainRegistry): ProxyDepositCalculator { + return RealProxyDepositCalculator(chainRegistry) + } +} diff --git a/feature-staking-api/build.gradle b/feature-staking-api/build.gradle index edfa58ff43..92bf8e2f78 100644 --- a/feature-staking-api/build.gradle +++ b/feature-staking-api/build.gradle @@ -31,6 +31,7 @@ dependencies { implementation project(':runtime') implementation project(':common') + implementation project(':feature-proxy-api') api project(":feature-wallet-api") api project(":feature-account-api") diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/proxy/AddProxyInteractor.kt b/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt similarity index 50% rename from feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/proxy/AddProxyInteractor.kt rename to feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt index 493d4f5f0f..e1fc6f2f22 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/proxy/AddProxyInteractor.kt +++ b/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt @@ -1,17 +1,17 @@ -package io.novafoundation.nova.feature_account_api.domain.proxy +package io.novafoundation.nova.feature_staking_api.data.proxy import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.model.Fee -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import java.math.BigInteger import jp.co.soramitsu.fearless_utils.runtime.AccountId -interface AddProxyInteractor { +interface AddStakingProxyRepository { - suspend fun estimateFee(chain: Chain, accountId: AccountId, proxyType: ProxyAccount.ProxyType): Fee + suspend fun estimateFee(chain: Chain, accountId: AccountId): Fee - suspend fun addProxy(chain: Chain, accountId: AccountId, proxyType: ProxyAccount.ProxyType): Result + suspend fun addProxy(chain: Chain, accountId: AccountId): Result suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): BigInteger } diff --git a/feature-staking-impl/build.gradle b/feature-staking-impl/build.gradle index d816e347f3..ede505cf2f 100644 --- a/feature-staking-impl/build.gradle +++ b/feature-staking-impl/build.gradle @@ -46,6 +46,7 @@ dependencies { implementation project(':feature-currency-api') implementation project(':feature-ledger-api') implementation project(':feature-dapp-api') + implementation project(':feature-proxy-api') implementation project(':runtime') implementation kotlinDep diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/RealAddProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt similarity index 61% rename from feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/RealAddProxyInteractor.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt index 033c7f68fc..df9d13d7a4 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/proxy/RealAddProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt @@ -1,46 +1,46 @@ -package io.novafoundation.nova.feature_account_impl.domain.proxy +package io.novafoundation.nova.feature_staking_impl.data.proxy import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.intoOrigin import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.model.Fee -import io.novafoundation.nova.feature_account_api.data.repository.ProxyRepository -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount -import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor -import io.novafoundation.nova.feature_account_impl.data.network.blockchain.bindings.calls.addProxyCall -import io.novafoundation.nova.feature_account_impl.domain.proxy.common.ProxyDepositCalculator +import io.novafoundation.nova.feature_proxy_api.data.calls.addProxyCall +import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator +import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -class RealAddProxyInteractor( +class RealAddStakingProxyRepository( private val extrinsicService: ExtrinsicService, private val proxyDepositCalculator: ProxyDepositCalculator, - private val proxyRepository: ProxyRepository -) : AddProxyInteractor { + private val getProxyRepository: GetProxyRepository +) : io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository { - override suspend fun estimateFee(chain: Chain, accountId: AccountId, proxyType: ProxyAccount.ProxyType): Fee { + override suspend fun estimateFee(chain: Chain, accountId: AccountId): Fee { return withContext(Dispatchers.IO) { extrinsicService.estimateFee(chain, accountId.intoOrigin()) { - addProxyCall(accountId, proxyType) + addProxyCall(accountId, ProxyType.Staking) } } } - override suspend fun addProxy(chain: Chain, accountId: AccountId, proxyType: ProxyAccount.ProxyType): Result { + override suspend fun addProxy(chain: Chain, accountId: AccountId): Result { return withContext(Dispatchers.IO) { extrinsicService.submitExtrinsic(chain, accountId.intoOrigin()) { - addProxyCall(accountId, proxyType) + addProxyCall(accountId, ProxyType.Staking) } } } override suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): Balance { val depositConstants = proxyDepositCalculator.getDepositConstants(chain) - val currentProxiesCount = proxyRepository.getProxiesQuantity(chain.id, accountId) + val currentProxiesCount = getProxyRepository.getProxiesQuantity(chain.id, accountId) return proxyDepositCalculator.calculateProxyDeposit(depositConstants, currentProxiesCount + 1) } } 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 c1d6127984..f3d7addb24 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 @@ -8,6 +8,7 @@ import io.novafoundation.nova.core_db.di.DbApi import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator import io.novafoundation.nova.feature_dapp_api.di.DAppFeatureApi +import io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.StakingUpdateSystem @@ -247,6 +248,7 @@ interface StakingFeatureComponent : StakingFeatureApi { DbApi::class, RuntimeApi::class, AccountFeatureApi::class, + ProxyFeatureApi::class, WalletFeatureApi::class, DAppFeatureApi::class ] diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt index 9d9249d9c9..fedead1805 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt @@ -26,7 +26,6 @@ import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicServic import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase -import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor import io.novafoundation.nova.feature_account_api.domain.updaters.AccountUpdateScope import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase @@ -34,6 +33,8 @@ import io.novafoundation.nova.feature_account_api.presenatation.actions.External import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_account_api.presenatation.mixin.identity.IdentityMixin import io.novafoundation.nova.feature_dapp_api.data.repository.DAppMetadataRepository +import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_wallet_api.data.cache.AssetCache import io.novafoundation.nova.feature_wallet_api.data.repository.BalanceLocksRepository import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase @@ -127,8 +128,6 @@ interface StakingFeatureDependencies { fun addressInputMixinFactory(): AddressInputMixinFactory - fun addProxyInteractor(): AddProxyInteractor - val amountChooserMixinFactory: AmountChooserMixin.Factory val actionAwaitableMixinFactory: ActionAwaitableMixin.Factory @@ -169,4 +168,8 @@ interface StakingFeatureDependencies { val externalBalanceDao: ExternalBalanceDao val partialRetriableMixinFactory: PartialRetriableMixin.Factory + + val proxyDepositCalculator: ProxyDepositCalculator + + val getProxyRepository: GetProxyRepository } 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 8955fd4df6..048ed2f867 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 @@ -7,6 +7,7 @@ import io.novafoundation.nova.core_db.di.DbApi import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator import io.novafoundation.nova.feature_dapp_api.di.DAppFeatureApi +import io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi import io.novafoundation.nova.feature_staking_impl.presentation.NominationPoolsRouter import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.StakingDashboardRouter @@ -38,6 +39,7 @@ class StakingFeatureHolder @Inject constructor( .dbApi(getFeature(DbApi::class.java)) .walletFeatureApi(getFeature(WalletFeatureApi::class.java)) .accountFeatureApi(getFeature(AccountFeatureApi::class.java)) + .proxyFeatureApi(getFeature(ProxyFeatureApi::class.java)) .dAppFeatureApi(getFeature(DAppFeatureApi::class.java)) .build() diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt index fc1bddb0b8..1d9b199487 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt @@ -19,8 +19,11 @@ import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentit import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.updaters.AccountUpdateScope import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase +import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_staking_api.data.network.blockhain.updaters.PooledBalanceUpdaterFactory import io.novafoundation.nova.feature_staking_api.data.nominationPools.pool.PoolAccountDerivation +import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository import io.novafoundation.nova.feature_staking_api.domain.api.StakingRepository import io.novafoundation.nova.feature_staking_api.presentation.nominationPools.display.PoolDisplayUseCase import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState @@ -30,6 +33,7 @@ import io.novafoundation.nova.feature_staking_impl.data.network.subquery.SubQuer import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network.blockhain.updater.RealPooledBalanceUpdaterFactory import io.novafoundation.nova.feature_staking_impl.data.nominationPools.repository.NominationPoolStateRepository import io.novafoundation.nova.feature_staking_impl.data.parachainStaking.RoundDurationEstimator +import io.novafoundation.nova.feature_staking_impl.data.proxy.RealAddStakingProxyRepository import io.novafoundation.nova.feature_staking_impl.data.repository.BagListRepository import io.novafoundation.nova.feature_staking_impl.data.repository.LocalBagListRepository import io.novafoundation.nova.feature_staking_impl.data.repository.ParasRepository @@ -602,4 +606,18 @@ class StakingFeatureModule { accountRepository = accountRepository, chainRegistry = chainRegistry ) + + @Provides + @FeatureScope + fun provideAddProxyRepository( + extrinsicService: ExtrinsicService, + proxyDepositCalculator: ProxyDepositCalculator, + getProxyRepository: GetProxyRepository + ): AddStakingProxyRepository { + return RealAddStakingProxyRepository( + extrinsicService, + proxyDepositCalculator, + getProxyRepository + ) + } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/SetStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/SetStakingProxyInteractor.kt deleted file mode 100644 index cf2faa64af..0000000000 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/SetStakingProxyInteractor.kt +++ /dev/null @@ -1,10 +0,0 @@ -package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy - -import io.novafoundation.nova.common.validation.ValidationSystem - -class SetStakingProxyInteractor { - - fun validationSystem(): ValidationSystem<> { - - } -} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddProxyValidationSystem.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddProxyValidationSystem.kt new file mode 100644 index 0000000000..e59d32c405 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddProxyValidationSystem.kt @@ -0,0 +1,41 @@ +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy + +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.validation.NotEnoughToPayFeesError +import io.novafoundation.nova.common.validation.ValidationSystem +import io.novafoundation.nova.common.validation.ValidationSystemBuilder +import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import java.math.BigDecimal + +class AddStakingProxyValidationPayload( + val chain: Chain, + val asset: Asset, + val address: String, + val fee: Fee, + val deposit: Balance, + val newProxyQuantity: Int, +) + +sealed interface AddStakingProxyValidationFailure { + + class NotEnoughToPayFee( + override val chainAsset: Chain.Asset, + override val maxUsable: BigDecimal, + override val fee: BigDecimal + ) : AddStakingProxyValidationFailure, NotEnoughToPayFeesError + + class NotEnoughBalanceToReserveDeposit( + val chainAsset: Chain.Asset, + val maxUsable: Balance, + val deposit: Balance + ) : AddStakingProxyValidationFailure + + class InvalidAddress(val chain: Chain) : AddStakingProxyValidationFailure + + class MaximumProxiesReached(val chain: Chain, val max: Int) : AddStakingProxyValidationFailure +} + +typealias AddStakingProxyValidationSystem = ValidationSystem +typealias AddStakingProxyValidationSystemBuilder = ValidationSystemBuilder diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt index 70883442fc..fddfbb01c7 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt @@ -6,24 +6,19 @@ import io.novafoundation.nova.common.presentation.DescriptiveButtonState import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.flowOf import io.novafoundation.nova.common.validation.ValidationExecutor -import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount -import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn -import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory +import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase -import io.novafoundation.nova.feature_wallet_api.domain.model.withAmount import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.create import io.novafoundation.nova.feature_wallet_api.presentation.model.AmountModel import io.novafoundation.nova.feature_wallet_api.presentation.model.mapAmountToAmountModel -import io.novafoundation.nova.feature_wallet_api.presentation.model.transferableAmountModel import io.novafoundation.nova.runtime.ext.accountIdOrNull import io.novafoundation.nova.runtime.ext.commissionAsset import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState @@ -31,7 +26,6 @@ import io.novafoundation.nova.runtime.state.assetWithChain import io.novafoundation.nova.runtime.state.chain import io.novafoundation.nova.runtime.state.selectedAssetFlow import io.novafoundation.nova.runtime.state.selectedChainFlow -import io.novafoundation.nova.runtime.state.selectedOption import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -52,7 +46,7 @@ class SetStakingProxyViewModel( private val assetUseCase: ArbitraryAssetUseCase, private val resourceManager: ResourceManager, private val selectAddressRequester: SelectAddressForTransactionRequester, - private val addProxyInteractor: AddProxyInteractor, + private val addStakingProxyRepository: AddStakingProxyRepository, private val validationExecutor: ValidationExecutor, ) : BaseViewModel(), ExternalActions by externalActions, @@ -98,7 +92,7 @@ class SetStakingProxyViewModel( val metaAccount = accountRepository.getSelectedMetaAccount() val chain = selectedAssetState.chain() val accountId = metaAccount.requireAccountIdIn(chain) - val deposit = addProxyInteractor.calculateDepositForAddProxy(chain, accountId) + val deposit = addStakingProxyRepository.calculateDepositForAddProxy(chain, accountId) mapAmountToAmountModel(deposit, asset) } .shareInBackground() @@ -147,7 +141,7 @@ class SetStakingProxyViewModel( } else { feeMixin.loadFee( coroutineScope = this, - feeConstructor = { addProxyInteractor.estimateFee(chain, accountId, ProxyAccount.ProxyType.Staking) }, + feeConstructor = { addStakingProxyRepository.estimateFee(chain, accountId) }, onRetryCancelled = {} ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt index 5333529f2d..881d43985b 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt @@ -6,26 +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.data.network.AppLinksProvider import io.novafoundation.nova.common.di.viewmodel.ViewModelKey import io.novafoundation.nova.common.di.viewmodel.ViewModelModule -import io.novafoundation.nova.common.mixin.actionAwaitable.ActionAwaitableMixin import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository -import io.novafoundation.nova.feature_account_api.domain.proxy.AddProxyInteractor -import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory -import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState +import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor -import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.controller.SetControllerValidationSystem -import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.SetControllerViewModel import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.SetStakingProxyViewModel import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin @@ -47,7 +37,7 @@ class SetStakingProxyModule { assetUseCase: ArbitraryAssetUseCase, resourceManager: ResourceManager, selectAddressCommunicator: SelectAddressCommunicator, - addProxyInteractor: AddProxyInteractor, + addStakingProxyRepository: AddStakingProxyRepository, validationExecutor: ValidationExecutor ): ViewModel { return SetStakingProxyViewModel( @@ -60,7 +50,7 @@ class SetStakingProxyModule { assetUseCase = assetUseCase, resourceManager = resourceManager, selectAddressRequester = selectAddressCommunicator, - addProxyInteractor = addProxyInteractor, + addStakingProxyRepository = addStakingProxyRepository, validationExecutor = validationExecutor ) } diff --git a/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt b/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt index e1b2e3c129..30cf65c1d9 100644 --- a/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt +++ b/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt @@ -1,6 +1,6 @@ package io.novafoundation.nova.feature_wallet_impl.data.network.blockchain.assets.transfers.validations -import io.novafoundation.nova.feature_account_api.domain.validation.proxy.notSystemAccount +import io.novafoundation.nova.feature_account_api.domain.validation.notSystemAccount import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.AssetSourceRegistry import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.existentialDeposit import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.AssetTransfer @@ -104,7 +104,7 @@ fun AssetTransfersValidationSystemBuilder.sufficientBalanceInUsedAsset() = suffi ) fun AssetTransfersValidationSystemBuilder.recipientIsNotSystemAccount() = - io.novafoundation.nova.feature_account_api.domain.validation.proxy.notSystemAccount( + notSystemAccount( accountId = { it.transfer.recipientOrNull() }, error = { AssetTransferValidationFailure.RecipientIsSystemAccount } ) diff --git a/settings.gradle b/settings.gradle index 60b8b164f3..dbe2e34e9b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,3 +36,5 @@ include ':feature-swap-api' include ':feature-swap-impl' include ':feature-buy-api' include ':feature-buy-impl' +include ':feature-proxy-impl' +include ':feature-proxy-api' From 271a665fa1305338b1e51aba768ee4c0dcf2a1c2 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 9 Jan 2024 03:44:45 +0100 Subject: [PATCH 03/55] Add validation for add staking proxy screen --- .../res/navigation/staking_main_graph.xml | 2 +- common/src/main/res/values/strings.xml | 9 ++ .../data/repository/GetProxyRepository.kt | 3 + .../domain/model/ProxyDepositWithQuantity.kt | 8 ++ ...EnoughAmountToPayProxyDepositValidation.kt | 53 ++++++++++++ .../MaximumProxiesNotReachedValidator.kt | 45 ++++++++++ .../data/repository/RealGetProxyRepository.kt | 56 ++++++++----- .../data/proxy/AddStakingProxyRepository.kt | 7 +- .../proxy/RealAddStakingProxyRepository.kt | 22 +++-- .../di/StakingFeatureComponent.kt | 8 +- .../AddStakingProxyValidationsModule.kt | 35 ++++++++ ...kt => AddStakingProxyValidationFailure.kt} | 19 +---- .../proxy/AddStakingProxyValidationPayload.kt | 16 ++++ .../delegation/proxy/Declarations.kt | 82 ++++++++++++++++++ .../controller/set/SetControllerFragment.kt | 4 +- .../AddProxyValidationFailureHandling.kt | 35 ++++++++ ...Fragment.kt => AddStakingProxyFragment.kt} | 31 +++---- ...ewModel.kt => AddStakingProxyViewModel.kt} | 83 +++++++++++++------ ...mponent.kt => AddStakingProxyComponent.kt} | 11 ++- ...roxyModule.kt => AddStakingProxyModule.kt} | 19 +++-- .../fragment_set_controller_account.xml | 2 +- .../res/layout/fragment_set_staking_proxy.xml | 16 ++-- 22 files changed, 447 insertions(+), 119 deletions(-) create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyDepositWithQuantity.kt create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidator.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/{AddProxyValidationSystem.kt => AddStakingProxyValidationFailure.kt} (57%) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/{SetStakingProxyFragment.kt => AddStakingProxyFragment.kt} (77%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/{SetStakingProxyViewModel.kt => AddStakingProxyViewModel.kt} (66%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/{SetStakingProxyComponent.kt => AddStakingProxyComponent.kt} (55%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/{SetStakingProxyModule.kt => AddStakingProxyModule.kt} (81%) diff --git a/app/src/main/res/navigation/staking_main_graph.xml b/app/src/main/res/navigation/staking_main_graph.xml index 3fba927f41..553e964e56 100644 --- a/app/src/main/res/navigation/staking_main_graph.xml +++ b/app/src/main/res/navigation/staking_main_graph.xml @@ -39,7 +39,7 @@ + Maximum number of proxies has been reached + You have reached the limit of %s added proxies in %s. Remove proxies to add new ones. + + Invalid address + An address must be a valid for %s + + Not enough tokens + You don’t have enough balance for proxy deposit of %s. Available balance: %s + Your delegations Add delegated authority (Proxy) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt index 560c67ad80..f4df269efd 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt @@ -4,6 +4,7 @@ import io.novafoundation.nova.common.address.AccountIdKey import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId +import java.math.BigInteger import jp.co.soramitsu.fearless_utils.runtime.AccountId interface GetProxyRepository { @@ -13,4 +14,6 @@ interface GetProxyRepository { suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int + + suspend fun getProxDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyDepositWithQuantity.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyDepositWithQuantity.kt new file mode 100644 index 0000000000..c4d26b6f2d --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyDepositWithQuantity.kt @@ -0,0 +1,8 @@ +package io.novafoundation.nova.feature_proxy_api.domain.model + +import java.math.BigInteger + +class ProxyDepositWithQuantity( + val deposit: BigInteger, + val quantity: Int +) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt new file mode 100644 index 0000000000..3555ea71b4 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt @@ -0,0 +1,53 @@ +package io.novafoundation.nova.feature_proxy_api.domain.validators + +import io.novafoundation.nova.common.utils.atLeastZero +import io.novafoundation.nova.common.validation.Validation +import io.novafoundation.nova.common.validation.ValidationStatus +import io.novafoundation.nova.common.validation.ValidationSystemBuilder +import io.novafoundation.nova.common.validation.validOrError +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import java.math.BigInteger +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +class EnoughAmountToPayProxyDepositValidation( + private val chain: (P) -> Chain, + private val accountId: (P) -> AccountId, + private val newDeposit: (P) -> BigInteger, + private val availableBalance: (P) -> BigInteger, + private val error: (P, BigInteger) -> E, + private val proxyRepository: GetProxyRepository +) : Validation { + + override suspend fun validate(value: P): ValidationStatus { + val availableBalance = availableBalance(value) + val currentDeposit = proxyRepository.getProxDeposit(chain(value).id, accountId(value)) + + val deltaDeposit = (newDeposit(value) - currentDeposit).atLeastZero() + + return validOrError(deltaDeposit <= availableBalance) { + val maxUsable = availableBalance - deltaDeposit + error(value, maxUsable) + } + } +} + +fun ValidationSystemBuilder.enoughBalanceToPayProxyDeposit( + chain: (P) -> Chain, + accountId: (P) -> AccountId, + newDeposit: (P) -> BigInteger, + availableBalance: (P) -> BigInteger, + error: (P, BigInteger) -> E, + proxyRepository: GetProxyRepository +) { + validate( + EnoughAmountToPayProxyDepositValidation( + chain = chain, + accountId = accountId, + newDeposit = newDeposit, + availableBalance = availableBalance, + error = error, + proxyRepository = proxyRepository + ) + ) +} diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidator.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidator.kt new file mode 100644 index 0000000000..c19fa5cb79 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidator.kt @@ -0,0 +1,45 @@ +package io.novafoundation.nova.feature_proxy_api.domain.validators + +import io.novafoundation.nova.common.validation.Validation +import io.novafoundation.nova.common.validation.ValidationStatus +import io.novafoundation.nova.common.validation.ValidationSystemBuilder +import io.novafoundation.nova.common.validation.validOrError +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +class MaximumProxiesNotReachedValidator( + private val chain: (P) -> Chain, + private val accountId: (P) -> AccountId, + private val newProxiedQuantity: (P) -> Int, + private val error: (P, Int) -> E, + private val proxyRepository: GetProxyRepository +) : Validation { + + override suspend fun validate(value: P): ValidationStatus { + val newProxiesQuantity = newProxiedQuantity(value) + val maximumProxiesQuantiy = proxyRepository.getProxiesQuantity(chain(value).id, accountId(value)) + + return validOrError(newProxiesQuantity <= newProxiesQuantity) { + error(value, maximumProxiesQuantiy) + } + } +} + +fun ValidationSystemBuilder.maximumProxiesNotReached( + chain: (P) -> Chain, + accountId: (P) -> AccountId, + newProxiedQuantity: (P) -> Int, + error: (P, Int) -> E, + proxyRepository: GetProxyRepository +) { + validate( + MaximumProxiesNotReachedValidator( + chain = chain, + accountId = accountId, + newProxiedQuantity = newProxiedQuantity, + error = error, + proxyRepository = proxyRepository + ) + ) +} diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt index 6f7b0c9e6d..9aa71e7a38 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt @@ -2,6 +2,7 @@ package io.novafoundation.nova.feature_proxy_impl.data.repository import io.novafoundation.nova.common.address.AccountIdKey import io.novafoundation.nova.common.address.intoKey +import io.novafoundation.nova.common.data.network.runtime.binding.cast import io.novafoundation.nova.common.data.network.runtime.binding.castToDictEnum import io.novafoundation.nova.common.data.network.runtime.binding.castToList import io.novafoundation.nova.common.data.network.runtime.binding.castToStruct @@ -19,6 +20,12 @@ import jp.co.soramitsu.fearless_utils.runtime.AccountId import jp.co.soramitsu.fearless_utils.runtime.metadata.module import jp.co.soramitsu.fearless_utils.runtime.metadata.storage + +private class OnChainProxiedModel( + val proxies: List, + val deposit: BigInteger +) + private class OnChainProxyModel( val accountId: AccountIdKey, val proxyType: String, @@ -34,8 +41,8 @@ class RealGetProxyRepository( val delegatorToProxies = receiveAllProxies(chainId) return delegatorToProxies - .mapNotNull { (delegator, proxies) -> - val notDelayedProxies = proxies.filter { it.delay == BigInteger.ZERO } + .mapNotNull { (delegator, proxied) -> + val notDelayedProxies = proxied.proxies.filter { it.delay == BigInteger.ZERO } val matchedProxies = matchProxiesToAccountsAndMap(notDelayedProxies, accountIds) if (matchedProxies.isEmpty()) return@mapNotNull null @@ -47,19 +54,25 @@ class RealGetProxyRepository( } override suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List { - val proxies = getAllProxiesFor(chainId, proxiedAccountId) + val proxied = getAllProxiesFor(chainId, proxiedAccountId) - return proxies.filter { it.accountId == proxyAccountId.intoKey() } + return proxied.proxies.filter { it.accountId == proxyAccountId.intoKey() } .map { ProxyType.fromString(it.proxyType) } } override suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int { - val proxies = getAllProxiesFor(chainId, proxiedAccountId) + val proxied = getAllProxiesFor(chainId, proxiedAccountId) + + return proxied.proxies.size + } - return proxies.size + override suspend fun getProxDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger { + val proxied = getAllProxiesFor(chainId, proxiedAccountId) + + return proxied.deposit } - private suspend fun getAllProxiesFor(chainId: ChainId, accountId: AccountId): List { + private suspend fun getAllProxiesFor(chainId: ChainId, accountId: AccountId): OnChainProxiedModel { return remoteSource.query(chainId) { runtime.metadata.module(Modules.PROXY) .storage("Proxies") @@ -72,7 +85,7 @@ class RealGetProxyRepository( } } - private suspend fun receiveAllProxies(chainId: ChainId): Map> { + private suspend fun receiveAllProxies(chainId: ChainId): Map { return remoteSource.query(chainId) { runtime.metadata.module(Modules.PROXY) .storage("Proxies") @@ -88,21 +101,24 @@ class RealGetProxyRepository( } } - private fun bindProxyAccounts(dynamicInstance: Any?): List { + private fun bindProxyAccounts(dynamicInstance: Any?): OnChainProxiedModel { val root = dynamicInstance.castToList() val proxies = root[0].castToList() - return proxies.map { - val proxy = it.castToStruct() - val proxyAccountId: ByteArray = proxy.getTyped("delegate") - val proxyType = proxy.get("proxyType").castToDictEnum() - val delay = proxy.getTyped("delay") - OnChainProxyModel( - proxyAccountId.intoKey(), - proxyType.name, - delay - ) - } + return OnChainProxiedModel( + proxies = proxies.map { + val proxy = it.castToStruct() + val proxyAccountId: ByteArray = proxy.getTyped("delegate") + val proxyType = proxy.get("proxyType").castToDictEnum() + val delay = proxy.getTyped("delay") + OnChainProxyModel( + proxyAccountId.intoKey(), + proxyType.name, + delay + ) + }, + deposit = root[1].cast() + ) } private fun mapToProxiedWithProxies( diff --git a/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt b/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt index e1fc6f2f22..b3eeb0df18 100644 --- a/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt +++ b/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt @@ -2,6 +2,7 @@ package io.novafoundation.nova.feature_staking_api.data.proxy import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import java.math.BigInteger @@ -9,9 +10,9 @@ import jp.co.soramitsu.fearless_utils.runtime.AccountId interface AddStakingProxyRepository { - suspend fun estimateFee(chain: Chain, accountId: AccountId): Fee + suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee - suspend fun addProxy(chain: Chain, accountId: AccountId): Result + suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result - suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): BigInteger + suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): ProxyDepositWithQuantity } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt index df9d13d7a4..65caee4fa9 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt @@ -8,8 +8,10 @@ import io.novafoundation.nova.feature_proxy_api.data.calls.addProxyCall import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance +import io.novafoundation.nova.runtime.ext.emptyAccountId import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers @@ -19,28 +21,30 @@ class RealAddStakingProxyRepository( private val extrinsicService: ExtrinsicService, private val proxyDepositCalculator: ProxyDepositCalculator, private val getProxyRepository: GetProxyRepository -) : io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository { +) : AddStakingProxyRepository { - override suspend fun estimateFee(chain: Chain, accountId: AccountId): Fee { + override suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee { return withContext(Dispatchers.IO) { - extrinsicService.estimateFee(chain, accountId.intoOrigin()) { - addProxyCall(accountId, ProxyType.Staking) + extrinsicService.estimateFee(chain, proxiedAccountId.intoOrigin()) { + addProxyCall(chain.emptyAccountId(), ProxyType.Staking) } } } - override suspend fun addProxy(chain: Chain, accountId: AccountId): Result { + override suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { return withContext(Dispatchers.IO) { - extrinsicService.submitExtrinsic(chain, accountId.intoOrigin()) { - addProxyCall(accountId, ProxyType.Staking) + extrinsicService.submitExtrinsic(chain, proxiedAccountId.intoOrigin()) { + addProxyCall(proxyAccountId, ProxyType.Staking) } } } - override suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): Balance { + override suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): ProxyDepositWithQuantity { val depositConstants = proxyDepositCalculator.getDepositConstants(chain) val currentProxiesCount = getProxyRepository.getProxiesQuantity(chain.id, accountId) - return proxyDepositCalculator.calculateProxyDeposit(depositConstants, currentProxiesCount + 1) + val newQuantity = currentProxiesCount + 1 + val deposit = proxyDepositCalculator.calculateProxyDeposit(depositConstants, newQuantity) + return ProxyDepositWithQuantity(deposit, newQuantity) } } 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 f3d7addb24..e3ee126a43 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 @@ -19,6 +19,7 @@ import io.novafoundation.nova.feature_staking_impl.di.staking.parachain.Parachai import io.novafoundation.nova.feature_staking_impl.di.staking.stakingTypeDetails.StakingTypeDetailsModule import io.novafoundation.nova.feature_staking_impl.di.staking.startMultiStaking.StartMultiStakingModule import io.novafoundation.nova.feature_staking_impl.di.staking.unbond.StakingUnbondModule +import io.novafoundation.nova.feature_staking_impl.di.validations.AddStakingProxyValidationsModule import io.novafoundation.nova.feature_staking_impl.domain.nominationPools.common.rewards.NominationPoolRewardCalculatorFactory import io.novafoundation.nova.feature_staking_impl.presentation.NominationPoolsRouter import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter @@ -60,7 +61,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.con import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.select.di.SelectBondMoreComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.di.ConfirmSetControllerComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.di.SetControllerComponent -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.di.SetStakingProxyComponent +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.di.AddStakingProxyComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.di.StakingComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.di.ConfirmRebondComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.custom.di.CustomRebondComponent @@ -98,7 +99,8 @@ import io.novafoundation.nova.runtime.di.RuntimeApi NominationPoolModule::class, StakingDashboardModule::class, StartMultiStakingModule::class, - StakingTypeDetailsModule::class + StakingTypeDetailsModule::class, + AddStakingProxyValidationsModule::class ] ) @FeatureScope @@ -168,7 +170,7 @@ interface StakingFeatureComponent : StakingFeatureApi { fun setControllerFactory(): SetControllerComponent.Factory - fun setStakingProxyFactory(): SetStakingProxyComponent.Factory + fun setStakingProxyFactory(): AddStakingProxyComponent.Factory fun confirmSetControllerFactory(): ConfirmSetControllerComponent.Factory diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt new file mode 100644 index 0000000000..b33bfd04b4 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt @@ -0,0 +1,35 @@ +package io.novafoundation.nova.feature_staking_impl.di.validations + +import dagger.Module +import dagger.Provides +import io.novafoundation.nova.common.di.scope.FeatureScope +import io.novafoundation.nova.common.validation.ValidationSystem +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.enoughBalanceToPayDeposit +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.maximumProxies +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.sufficientBalanceToPayFee +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.sufficientBalanceToStayAboveEd +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.validAddress +import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughTotalToStayAboveEDValidationFactory + +@Module +class AddStakingProxyValidationsModule { + + @FeatureScope + @Provides + fun provideAddStakingProxyValidationSystem( + getProxyRepository: GetProxyRepository, + enoughTotalToStayAboveEDValidationFactory: EnoughTotalToStayAboveEDValidationFactory + ): AddStakingProxyValidationSystem = ValidationSystem { + validAddress() + + sufficientBalanceToPayFee() + + sufficientBalanceToStayAboveEd(enoughTotalToStayAboveEDValidationFactory) + + maximumProxies(getProxyRepository) + + enoughBalanceToPayDeposit(getProxyRepository) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddProxyValidationSystem.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt similarity index 57% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddProxyValidationSystem.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt index e59d32c405..4381ebac0d 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddProxyValidationSystem.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt @@ -1,23 +1,11 @@ package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy 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.validation.InsufficientBalanceToStayAboveEDError import io.novafoundation.nova.feature_wallet_api.domain.validation.NotEnoughToPayFeesError -import io.novafoundation.nova.common.validation.ValidationSystem -import io.novafoundation.nova.common.validation.ValidationSystemBuilder -import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import java.math.BigDecimal -class AddStakingProxyValidationPayload( - val chain: Chain, - val asset: Asset, - val address: String, - val fee: Fee, - val deposit: Balance, - val newProxyQuantity: Int, -) - sealed interface AddStakingProxyValidationFailure { class NotEnoughToPayFee( @@ -26,6 +14,8 @@ sealed interface AddStakingProxyValidationFailure { override val fee: BigDecimal ) : AddStakingProxyValidationFailure, NotEnoughToPayFeesError + class NotEnoughToStayAboveED(override val asset: Chain.Asset) : AddStakingProxyValidationFailure, InsufficientBalanceToStayAboveEDError + class NotEnoughBalanceToReserveDeposit( val chainAsset: Chain.Asset, val maxUsable: Balance, @@ -36,6 +26,3 @@ sealed interface AddStakingProxyValidationFailure { class MaximumProxiesReached(val chain: Chain, val max: Int) : AddStakingProxyValidationFailure } - -typealias AddStakingProxyValidationSystem = ValidationSystem -typealias AddStakingProxyValidationSystemBuilder = ValidationSystemBuilder diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt new file mode 100644 index 0000000000..16d178f943 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt @@ -0,0 +1,16 @@ +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy + +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity +import io.novafoundation.nova.feature_wallet_api.domain.model.Asset +import io.novafoundation.nova.feature_wallet_api.presentation.model.DecimalFee +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +class AddStakingProxyValidationPayload( + val chain: Chain, + val asset: Asset, + val proxiedAccountId: AccountId, + val address: String, + val fee: DecimalFee, + val depositWithQuantity: ProxyDepositWithQuantity +) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt new file mode 100644 index 0000000000..ff1a119236 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt @@ -0,0 +1,82 @@ +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy + +import io.novafoundation.nova.common.validation.ValidationSystem +import io.novafoundation.nova.common.validation.ValidationSystemBuilder +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.validators.enoughBalanceToPayProxyDeposit +import io.novafoundation.nova.feature_proxy_api.domain.validators.maximumProxiesNotReached +import io.novafoundation.nova.feature_wallet_api.domain.model.balanceCountedTowardsED +import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughTotalToStayAboveEDValidationFactory +import io.novafoundation.nova.feature_wallet_api.domain.validation.sufficientBalance +import io.novafoundation.nova.feature_wallet_api.domain.validation.validAddress +import io.novafoundation.nova.feature_wallet_api.domain.validation.validate +import io.novafoundation.nova.runtime.multiNetwork.ChainWithAsset +import java.math.BigDecimal + +typealias AddStakingProxyValidationSystem = ValidationSystem +typealias AddStakingProxyValidationSystemBuilder = ValidationSystemBuilder + +fun AddStakingProxyValidationSystemBuilder.validAddress() = validAddress( + address = { it.address }, + chain = { it.chain }, + error = { AddStakingProxyValidationFailure.InvalidAddress(it.chain) } +) + +fun AddStakingProxyValidationSystemBuilder.sufficientBalanceToStayAboveEd( + enoughTotalToStayAboveEDValidationFactory: EnoughTotalToStayAboveEDValidationFactory +) = enoughTotalToStayAboveEDValidationFactory.validate( + chainWithAsset = { ChainWithAsset(it.chain, it.asset.token.configuration) }, + balance = { it.asset.balanceCountedTowardsED() }, + fee = { it.fee }, + error = { payload, _ -> + AddStakingProxyValidationFailure.NotEnoughToStayAboveED( + asset = payload.asset.token.configuration + ) + } +) + +fun AddStakingProxyValidationSystemBuilder.sufficientBalanceToPayFee() = + sufficientBalance( + available = { it.asset.free }, + amount = { BigDecimal.ZERO }, + fee = { it.fee }, + error = { context -> + AddStakingProxyValidationFailure.NotEnoughToPayFee( + chainAsset = context.payload.asset.token.configuration, + maxUsable = context.availableToPayFees, + fee = context.fee + ) + } + ) + +fun AddStakingProxyValidationSystemBuilder.maximumProxies( + proxyRepository: GetProxyRepository +) = maximumProxiesNotReached( + chain = { it.chain }, + accountId = { it.proxiedAccountId }, + newProxiedQuantity = { it.depositWithQuantity.quantity }, + error = { payload, max -> + AddStakingProxyValidationFailure.MaximumProxiesReached( + chain = payload.chain, + max = max + ) + }, + proxyRepository = proxyRepository +) + +fun AddStakingProxyValidationSystemBuilder.enoughBalanceToPayDeposit( + proxyRepository: GetProxyRepository +) = enoughBalanceToPayProxyDeposit( + chain = { it.chain }, + accountId = { it.proxiedAccountId }, + newDeposit = { it.depositWithQuantity.deposit }, + availableBalance = { it.asset.freeInPlanks }, + error = { payload, maxUsable -> + AddStakingProxyValidationFailure.NotEnoughBalanceToReserveDeposit( + chainAsset = payload.asset.token.configuration, + maxUsable = maxUsable, + deposit = payload.depositWithQuantity.deposit + ) + }, + proxyRepository = proxyRepository +) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt index e41e7dfd03..8835523705 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt @@ -21,7 +21,7 @@ import kotlinx.android.synthetic.main.fragment_set_controller_account.setControl import kotlinx.android.synthetic.main.fragment_set_controller_account.setControllerController import kotlinx.android.synthetic.main.fragment_set_controller_account.setControllerStash import kotlinx.android.synthetic.main.fragment_set_controller_account.setControllerSwitchToStashWarning -import kotlinx.android.synthetic.main.fragment_set_controller_account.setControllerToolbar +import kotlinx.android.synthetic.main.fragment_set_controller_account.addControllerToolbar class SetControllerFragment : BaseFragment() { @@ -43,7 +43,7 @@ class SetControllerFragment : BaseFragment() { setControllerController.setOnClickListener { viewModel.controllerClicked() } setControllerAdvertisement.setOnLearnMoreClickedListener { viewModel.onMoreClicked() } - setControllerToolbar.setHomeButtonListener { viewModel.backClicked() } + addControllerToolbar.setHomeButtonListener { viewModel.backClicked() } setControllerController.setActionTint(R.color.icon_secondary) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt new file mode 100644 index 0000000000..77db6402fb --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt @@ -0,0 +1,35 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common + +import io.novafoundation.nova.common.base.TitleAndMessage +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.utils.formatting.format +import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure.* +import io.novafoundation.nova.feature_wallet_api.domain.validation.handleNotEnoughFeeError +import io.novafoundation.nova.feature_wallet_api.presentation.formatters.formatPlanks +import io.novafoundation.nova.feature_wallet_api.presentation.validation.handleInsufficientBalanceCommission + +fun mapAddStakingProxyValidationFailureToUi( + resourceManager: ResourceManager, + failure: AddStakingProxyValidationFailure, +): TitleAndMessage { + return when (failure) { + is NotEnoughBalanceToReserveDeposit -> resourceManager.getString(R.string.common_error_not_enough_tokens) to + resourceManager.getString( + R.string.staking_not_enough_balance_to_pay_proxy_deposit_message, + failure.deposit.formatPlanks(failure.chainAsset), + failure.maxUsable.formatPlanks(failure.chainAsset) + ) + + is InvalidAddress -> resourceManager.getString(R.string.common_invalid_address_title) to + resourceManager.getString(R.string.common_invalid_address_message, failure.chain.name) + + is MaximumProxiesReached -> resourceManager.getString(R.string.add_proxy_maximum_reached_error_title) to + resourceManager.getString(R.string.add_proxy_maximum_reached_error_message, failure.max, failure.chain.name) + + is NotEnoughToPayFee -> handleNotEnoughFeeError(failure, resourceManager) + + is NotEnoughToStayAboveED -> handleInsufficientBalanceCommission(failure, resourceManager) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt similarity index 77% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyFragment.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt index 9df75ffa96..877fb98af6 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt @@ -18,16 +18,15 @@ import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.di.StakingFeatureComponent import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.setupFeeLoading import io.novafoundation.nova.feature_wallet_api.presentation.view.showAmount -import kotlinx.android.synthetic.main.fragment_set_controller_account.confirmSetControllerContainer import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyAddress -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyButton +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxyButton import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyContainer -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyDeposit -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyFee -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyTitle -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.stakingProxySelectWallet +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxyDeposit +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxyFee +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxyTitle +import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxySelectWallet -class SetStakingProxyFragment : BaseFragment() { +class AddStakingProxyFragment : BaseFragment() { override fun onCreateView( inflater: LayoutInflater, @@ -39,8 +38,10 @@ class SetStakingProxyFragment : BaseFragment() { override fun initViews() { setStakingProxyContainer.applyStatusBarInsets() + addStakingProxyButton.prepareForProgress(this) - stakingProxySelectWallet.setOnClickListener { viewModel.selectRecipientWallet() } + addStakingProxySelectWallet.setOnClickListener { viewModel.selectRecipientWallet() } + addStakingProxyButton.setOnClickListener { viewModel.onConfirmClick() } } override fun inject() { @@ -53,7 +54,7 @@ class SetStakingProxyFragment : BaseFragment() { .inject(this) } - override fun subscribe(viewModel: SetStakingProxyViewModel) { + override fun subscribe(viewModel: AddStakingProxyViewModel) { setupExternalActions(viewModel) observeValidations(viewModel) @@ -61,19 +62,19 @@ class SetStakingProxyFragment : BaseFragment() { setupExternalAccounts(viewModel.addressInputMixin, setStakingProxyAddress) viewModel.titleFlow.observe { - setStakingProxyTitle.text = it + addStakingProxyTitle.text = it } viewModel.isSelectAddressAvailable.observe { - stakingProxySelectWallet.isInvisible = !it + addStakingProxySelectWallet.isInvisible = !it } - viewModel.proxyDeposit.observe { - setStakingProxyDeposit.showAmount(it) + viewModel.proxyDepositModel.observe { + addStakingProxyDeposit.showAmount(it) } - setupFeeLoading(viewModel.feeMixin, setStakingProxyFee) + setupFeeLoading(viewModel.feeMixin, addStakingProxyFee) - viewModel.continueButtonState.observe(setStakingProxyButton::setState) + viewModel.continueButtonState.observe(addStakingProxyButton::setState) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt similarity index 66% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt index fddfbb01c7..97c8b4a354 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/SetStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt @@ -6,16 +6,22 @@ import io.novafoundation.nova.common.presentation.DescriptiveButtonState import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.flowOf import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationPayload +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.awaitDecimalFee import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.create import io.novafoundation.nova.feature_wallet_api.presentation.model.AmountModel import io.novafoundation.nova.feature_wallet_api.presentation.model.mapAmountToAmountModel @@ -30,13 +36,14 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -class SetStakingProxyViewModel( +class AddStakingProxyViewModel( addressInputMixinFactory: AddressInputMixinFactory, feeLoaderMixinFactory: FeeLoaderMixin.Factory, private val selectedAssetState: AnySelectedAssetOptionSharedState, @@ -48,6 +55,7 @@ class SetStakingProxyViewModel( private val selectAddressRequester: SelectAddressForTransactionRequester, private val addStakingProxyRepository: AddStakingProxyRepository, private val validationExecutor: ValidationExecutor, + private val addStakingProxyValidationSystem: AddStakingProxyValidationSystem ) : BaseViewModel(), ExternalActions by externalActions, Validatable by validationExecutor { @@ -76,34 +84,37 @@ class SetStakingProxyViewModel( accountIdentifierProvider = web3nIdentifiers( destinationChainFlow = selectedAssetState.assetWithChain, inputSpecProvider = inputSpec, - coroutineScope = this@SetStakingProxyViewModel, + coroutineScope = this@AddStakingProxyViewModel, ), - errorDisplayer = this@SetStakingProxyViewModel::showError, - showAccountEvent = this@SetStakingProxyViewModel::showAccountDetails, - coroutineScope = this@SetStakingProxyViewModel, + errorDisplayer = this@AddStakingProxyViewModel::showError, + showAccountEvent = this@AddStakingProxyViewModel::showAccountDetails, + coroutineScope = this@AddStakingProxyViewModel, ) } val isSelectAddressAvailable = flowOf { true } .shareInBackground() - val proxyDeposit: Flow = selectedAssetFlow - .map { asset -> - val metaAccount = accountRepository.getSelectedMetaAccount() - val chain = selectedAssetState.chain() - val accountId = metaAccount.requireAccountIdIn(chain) - val deposit = addStakingProxyRepository.calculateDepositForAddProxy(chain, accountId) - mapAmountToAmountModel(deposit, asset) - } + private val proxyDeposit: Flow = flowOf { + val metaAccount = accountRepository.getSelectedMetaAccount() + val chain = selectedAssetState.chain() + val accountId = metaAccount.requireAccountIdIn(chain) + addStakingProxyRepository.calculateDepositForAddProxy(chain, accountId) + } + .shareInBackground() + + val proxyDepositModel: Flow = combine(proxyDeposit, selectedAssetFlow) { depositwithQuantity, asset -> + mapAmountToAmountModel(depositwithQuantity.deposit, asset) + } .shareInBackground() val feeMixin: FeeLoaderMixin.Presentation = feeLoaderMixinFactory.create(commissionAssetFlow) - private val validationProgressFlow = MutableStateFlow(false) + private val _validationProgressFlow = MutableStateFlow(false) val continueButtonState = combine( addressInputMixin.inputFlow, - validationProgressFlow + _validationProgressFlow ) { addressInput, validationInProgress -> when { validationInProgress -> DescriptiveButtonState.Loading @@ -127,24 +138,42 @@ class SetStakingProxyViewModel( } } - fun onConfirmClick() { + fun onConfirmClick() = launch { + val metaAccount = accountRepository.getSelectedMetaAccount() + val chain = selectedAssetState.chain() + val validationPayload = AddStakingProxyValidationPayload( + chain = chain, + asset = selectedAssetFlow.first(), + address = addressInputMixin.inputFlow.value, + proxiedAccountId = metaAccount.requireAccountIdIn(chain), + fee = feeMixin.awaitDecimalFee(), + depositWithQuantity = proxyDeposit.first() + ) + + validationExecutor.requireValid( + validationSystem = addStakingProxyValidationSystem, + payload = validationPayload, + validationFailureTransformer = { mapAddStakingProxyValidationFailureToUi(resourceManager, it) }, + progressConsumer = _validationProgressFlow.progressConsumer() + ) { + openConfirmScreen() + } + } + private fun openConfirmScreen() { + TODO() } private fun runFeeUpdate() { addressInputMixin.inputFlow.onEach { + val metaAccount = accountRepository.getSelectedMetaAccount() val chain = selectedAssetState.chain() - val accountId = chain.accountIdOrNull(it) - - if (accountId == null) { - feeMixin.setFee(null) - } else { - feeMixin.loadFee( - coroutineScope = this, - feeConstructor = { addStakingProxyRepository.estimateFee(chain, accountId) }, - onRetryCancelled = {} - ) - } + + feeMixin.loadFee( + coroutineScope = this, + feeConstructor = { addStakingProxyRepository.estimateFee(chain, metaAccount.requireAccountIdIn(chain)) }, + onRetryCancelled = {} + ) }.launchIn(this) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyComponent.kt similarity index 55% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyComponent.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyComponent.kt index f86f1d86ea..001467e288 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyComponent.kt @@ -4,21 +4,20 @@ 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.staking.delegation.controller.set.SetControllerFragment -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.SetStakingProxyFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.AddStakingProxyFragment @Subcomponent( modules = [ - SetStakingProxyModule::class + AddStakingProxyModule::class ] ) @ScreenScope -interface SetStakingProxyComponent { +interface AddStakingProxyComponent { @Subcomponent.Factory interface Factory { - fun create(@BindsInstance fragment: Fragment): SetStakingProxyComponent + fun create(@BindsInstance fragment: Fragment): AddStakingProxyComponent } - fun inject(fragment: SetStakingProxyFragment) + fun inject(fragment: AddStakingProxyFragment) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt similarity index 81% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt index 881d43985b..833a95bd92 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/SetStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt @@ -16,17 +16,18 @@ import io.novafoundation.nova.feature_account_api.presenatation.actions.External import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.SetStakingProxyViewModel +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.AddStakingProxyViewModel import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState @Module(includes = [ViewModelModule::class]) -class SetStakingProxyModule { +class AddStakingProxyModule { @Provides @IntoMap - @ViewModelKey(SetStakingProxyViewModel::class) + @ViewModelKey(AddStakingProxyViewModel::class) fun provideViewModel( addressInputMixinFactory: AddressInputMixinFactory, feeLoaderMixinFactory: FeeLoaderMixin.Factory, @@ -38,9 +39,10 @@ class SetStakingProxyModule { resourceManager: ResourceManager, selectAddressCommunicator: SelectAddressCommunicator, addStakingProxyRepository: AddStakingProxyRepository, - validationExecutor: ValidationExecutor + validationExecutor: ValidationExecutor, + addStakingProxyValidationSystem: AddStakingProxyValidationSystem ): ViewModel { - return SetStakingProxyViewModel( + return AddStakingProxyViewModel( addressInputMixinFactory = addressInputMixinFactory, feeLoaderMixinFactory = feeLoaderMixinFactory, selectedAssetState = selectedAssetState, @@ -51,7 +53,8 @@ class SetStakingProxyModule { resourceManager = resourceManager, selectAddressRequester = selectAddressCommunicator, addStakingProxyRepository = addStakingProxyRepository, - validationExecutor = validationExecutor + validationExecutor = validationExecutor, + addStakingProxyValidationSystem = addStakingProxyValidationSystem ) } @@ -59,7 +62,7 @@ class SetStakingProxyModule { fun provideViewModelCreator( fragment: Fragment, viewModelFactory: ViewModelProvider.Factory - ): SetStakingProxyViewModel { - return ViewModelProvider(fragment, viewModelFactory).get(SetStakingProxyViewModel::class.java) + ): AddStakingProxyViewModel { + return ViewModelProvider(fragment, viewModelFactory).get(AddStakingProxyViewModel::class.java) } } diff --git a/feature-staking-impl/src/main/res/layout/fragment_set_controller_account.xml b/feature-staking-impl/src/main/res/layout/fragment_set_controller_account.xml index 33310579ad..83eefdb1ef 100644 --- a/feature-staking-impl/src/main/res/layout/fragment_set_controller_account.xml +++ b/feature-staking-impl/src/main/res/layout/fragment_set_controller_account.xml @@ -9,7 +9,7 @@ tools:background="@color/secondary_screen_background"> @@ -86,12 +86,12 @@ + android:enabled="false" + android:text="@string/common_continue" /> \ No newline at end of file From 36c85109b7879092cd601a815cf41abc2cf781ca Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 9 Jan 2024 05:25:32 +0100 Subject: [PATCH 04/55] Fixed your wallets bottom sheet dialog --- .../account/SelectAddressCommunicatorImpl.kt | 8 +-- .../nova/common/utils/Filters.kt | 5 ++ .../nova/core_db/dao/MetaAccountDao.kt | 3 ++ .../domain/interfaces/AccountRepository.kt | 2 + .../MetaAccountGroupingInteractor.kt | 8 ++- .../wallet/list/SelectAddressCommunicator.kt | 25 +++++---- .../data/repository/AccountRepositoryImpl.kt | 4 ++ .../datasource/AccountDataSource.kt | 2 + .../datasource/AccountDataSourceImpl.kt | 5 ++ .../MetaAccountGroupingInteractorImpl.kt | 30 +++++------ ...aAccountValidForTransactionListingMixin.kt | 21 ++++---- .../selectAddress/SelectAddressFragment.kt | 4 +- .../selectAddress/SelectAddressViewModel.kt | 30 ++++++++--- .../di/SelectAddressComponent.kt | 4 +- .../selectAddress/di/SelectAddressModule.kt | 4 +- .../send/amount/SelectSendViewModel.kt | 52 ++++++++++++++++--- .../send/amount/di/SelectSendModule.kt | 5 +- .../proxy/set/AddStakingProxyFragment.kt | 2 +- .../proxy/set/AddStakingProxyViewModel.kt | 38 +++++++++++--- .../domain/filter/MetaAccountFilter.kt | 19 +++++++ 20 files changed, 204 insertions(+), 67 deletions(-) create mode 100644 feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/filter/MetaAccountFilter.kt diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/account/SelectAddressCommunicatorImpl.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/account/SelectAddressCommunicatorImpl.kt index 9b150eca59..b6477ef293 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/account/SelectAddressCommunicatorImpl.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/account/SelectAddressCommunicatorImpl.kt @@ -3,16 +3,16 @@ package io.novafoundation.nova.app.root.navigation.account import io.novafoundation.nova.app.root.navigation.NavStackInterScreenCommunicator import io.novafoundation.nova.app.root.navigation.NavigationHolder import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionResponder +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressResponder import io.novafoundation.nova.feature_account_impl.presentation.account.list.selectAddress.SelectAddressFragment import io.novafoundation.nova.feature_assets.presentation.AssetsRouter class SelectAddressCommunicatorImpl(private val router: AssetsRouter, navigationHolder: NavigationHolder) : - NavStackInterScreenCommunicator(navigationHolder), + NavStackInterScreenCommunicator(navigationHolder), SelectAddressCommunicator { - override fun openRequest(request: SelectAddressForTransactionRequester.Request) { + override fun openRequest(request: SelectAddressRequester.Request) { super.openRequest(request) router.openSelectAddress(SelectAddressFragment.getBundle(request)) diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/Filters.kt b/common/src/main/java/io/novafoundation/nova/common/utils/Filters.kt index f37e86795b..747a8ed664 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/Filters.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/Filters.kt @@ -26,6 +26,11 @@ interface OptionsFilter : Filter { val options: List } +class EmptyFilter : Filter { + + override fun shouldInclude(model: T) = true +} + fun List.applyFilters(filters: List>): List { return filter { item -> filters.all { filter -> filter.shouldInclude(item) } } } diff --git a/core-db/src/main/java/io/novafoundation/nova/core_db/dao/MetaAccountDao.kt b/core-db/src/main/java/io/novafoundation/nova/core_db/dao/MetaAccountDao.kt index 7f982caeac..88250cdec0 100644 --- a/core-db/src/main/java/io/novafoundation/nova/core_db/dao/MetaAccountDao.kt +++ b/core-db/src/main/java/io/novafoundation/nova/core_db/dao/MetaAccountDao.kt @@ -111,6 +111,9 @@ interface MetaAccountDao { @Query("SELECT id FROM meta_accounts WHERE status = :status") suspend fun getMetaAccountIdsByStatus(status: MetaAccountLocal.Status): List + @Query("SELECT * FROM meta_accounts WHERE status = :status") + suspend fun getMetaAccountsByStatus(status: MetaAccountLocal.Status): List + @Query("SELECT * FROM meta_accounts") suspend fun getMetaAccountsInfo(): List diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/AccountRepository.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/AccountRepository.kt index f1bc438aef..f84660c866 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/AccountRepository.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/AccountRepository.kt @@ -44,6 +44,8 @@ interface AccountRepository { suspend fun allMetaAccounts(): List + suspend fun activeMetaAccounts(): List + suspend fun hasMetaAccounts(): Boolean suspend fun allLightMetaAccounts(): List diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/MetaAccountGroupingInteractor.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/MetaAccountGroupingInteractor.kt index 9ee001d004..c91204bd7b 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/MetaAccountGroupingInteractor.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/MetaAccountGroupingInteractor.kt @@ -1,6 +1,7 @@ package io.novafoundation.nova.feature_account_api.domain.interfaces import io.novafoundation.nova.common.list.GroupedList +import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountWithTotalBalance @@ -14,9 +15,12 @@ interface MetaAccountGroupingInteractor { fun metaAccountWithTotalBalanceFlow(metaId: Long): Flow - fun getMetaAccountsForTransaction(fromId: ChainId, destinationId: ChainId): Flow> + fun getMetaAccountsWithFilter(metaAccountFilter: Filter): Flow> fun updatedProxieds(): Flow> - suspend fun hasAvailableMetaAccountsForDestination(fromId: ChainId, destinationId: ChainId): Boolean + suspend fun hasAvailableMetaAccountsForChain( + chainId: ChainId, + metaAccountFilter: Filter + ): Boolean } diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/wallet/list/SelectAddressCommunicator.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/wallet/list/SelectAddressCommunicator.kt index e8f306e02c..410e6bd3b5 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/wallet/list/SelectAddressCommunicator.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/wallet/list/SelectAddressCommunicator.kt @@ -6,22 +6,29 @@ import io.novafoundation.nova.common.navigation.InterScreenResponder import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import kotlinx.android.parcel.Parcelize -interface SelectAddressForTransactionRequester : - InterScreenRequester { +interface SelectAddressRequester : InterScreenRequester { @Parcelize class Request( - val fromChainId: ChainId, - val destinationChainId: ChainId, - val selectedAddress: String? - ) : Parcelable + val chainId: ChainId, + val selectedAddress: String?, + val filter: Filter + ) : Parcelable { + + sealed interface Filter : Parcelable { + @Parcelize + object Empty : Filter + + @Parcelize + class ExcludeMetaIds(val metaIds: List) : Filter + } + } } -interface SelectAddressForTransactionResponder : - InterScreenResponder { +interface SelectAddressResponder : InterScreenResponder { @Parcelize class Response(val selectedAddress: String) : Parcelable } -interface SelectAddressCommunicator : SelectAddressForTransactionRequester, SelectAddressForTransactionResponder +interface SelectAddressCommunicator : SelectAddressRequester, SelectAddressResponder diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/AccountRepositoryImpl.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/AccountRepositoryImpl.kt index ade4b5d179..6bbc9738c5 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/AccountRepositoryImpl.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/AccountRepositoryImpl.kt @@ -126,6 +126,10 @@ class AccountRepositoryImpl( return accountDataSource.allMetaAccounts() } + override suspend fun activeMetaAccounts(): List { + return accountDataSource.activeMetaAccounts() + } + override suspend fun hasMetaAccounts(): Boolean { return accountDataSource.hasMetaAccounts() } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/datasource/AccountDataSource.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/datasource/AccountDataSource.kt index 7cb2ec80b2..e6ee640acc 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/datasource/AccountDataSource.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/datasource/AccountDataSource.kt @@ -47,6 +47,8 @@ interface AccountDataSource : SecretStoreV1 { suspend fun allMetaAccounts(): List + suspend fun activeMetaAccounts(): List + suspend fun allLightMetaAccounts(): List fun allMetaAccountsFlow(): Flow> diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/datasource/AccountDataSourceImpl.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/datasource/AccountDataSourceImpl.kt index 4e996e62da..b95e706e53 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/datasource/AccountDataSourceImpl.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/datasource/AccountDataSourceImpl.kt @@ -146,6 +146,11 @@ class AccountDataSourceImpl( return metaAccountDao.getJoinedMetaAccountsInfo().map(::mapMetaAccountLocalToMetaAccount) } + override suspend fun activeMetaAccounts(): List { + return metaAccountDao.getMetaAccountsByStatus(MetaAccountLocal.Status.ACTIVE) + .map(::mapMetaAccountLocalToMetaAccount) + } + override suspend fun allLightMetaAccounts(): List { return metaAccountDao.getMetaAccounts().map(::mapMetaAccountLocalToLightMetaAccount) } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/MetaAccountGroupingInteractorImpl.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/MetaAccountGroupingInteractorImpl.kt index cc81ab232b..96dab4773a 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/MetaAccountGroupingInteractorImpl.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/MetaAccountGroupingInteractorImpl.kt @@ -1,10 +1,11 @@ package io.novafoundation.nova.feature_account_impl.domain import io.novafoundation.nova.common.list.GroupedList +import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.common.utils.amountFromPlanks +import io.novafoundation.nova.common.utils.applyFilter import io.novafoundation.nova.common.utils.flowOf import io.novafoundation.nova.common.utils.orZero -import io.novafoundation.nova.common.utils.removed import io.novafoundation.nova.common.utils.sumByBigDecimal import io.novafoundation.nova.feature_account_api.data.proxy.MetaAccountsUpdatesRegistry import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository @@ -14,7 +15,6 @@ import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountAssetBalance import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountWithTotalBalance import io.novafoundation.nova.feature_account_api.domain.model.ProxiedAndProxyMetaAccount -import io.novafoundation.nova.feature_account_api.domain.model.addressIn import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn import io.novafoundation.nova.feature_currency_api.domain.interfaces.CurrencyRepository import io.novafoundation.nova.feature_currency_api.domain.model.Currency @@ -63,10 +63,10 @@ class MetaAccountGroupingInteractorImpl( } } - override fun getMetaAccountsForTransaction(fromId: ChainId, destinationId: ChainId): Flow> = flowOf { - val fromChain = chainRegistry.getChain(fromId) - val destinationChain = chainRegistry.getChain(destinationId) - getValidMetaAccountsForTransaction(fromChain, destinationChain) + override fun getMetaAccountsWithFilter( + metaAccountFilter: Filter + ): Flow> = flowOf { + getValidMetaAccountsForTransaction(metaAccountFilter) .groupBy(MetaAccount::type) .toSortedMap(metaAccountTypeComparator()) } @@ -92,11 +92,13 @@ class MetaAccountGroupingInteractorImpl( } } - override suspend fun hasAvailableMetaAccountsForDestination(fromId: ChainId, destinationId: ChainId): Boolean { - val fromChain = chainRegistry.getChain(fromId) - val destinationChain = chainRegistry.getChain(destinationId) - return getValidMetaAccountsForTransaction(fromChain, destinationChain) - .any { it.hasAccountIn(destinationChain) } + override suspend fun hasAvailableMetaAccountsForChain( + chainId: ChainId, + metaAccountFilter: Filter + ): Boolean { + val chain = chainRegistry.getChain(chainId) + return getValidMetaAccountsForTransaction(metaAccountFilter) + .any { it.hasAccountIn(chain) } } private suspend fun metaAccountWithTotalBalance( @@ -125,11 +127,9 @@ class MetaAccountGroupingInteractorImpl( ) } - private suspend fun getValidMetaAccountsForTransaction(from: Chain, destination: Chain): List { - val selectedMetaAccount = accountRepository.getSelectedMetaAccount() - val fromChainAddress = selectedMetaAccount.addressIn(from) + private suspend fun getValidMetaAccountsForTransaction(metaAccountFilter: Filter): List { return accountRepository.allMetaAccounts() - .removed { fromChainAddress == it.addressIn(destination) } + .applyFilter(metaAccountFilter) .filter { when (it.type) { LightMetaAccount.Type.SECRETS, diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/common/listing/MetaAccountValidForTransactionListingMixin.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/common/listing/MetaAccountValidForTransactionListingMixin.kt index 9c6645ba91..5828135830 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/common/listing/MetaAccountValidForTransactionListingMixin.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/common/listing/MetaAccountValidForTransactionListingMixin.kt @@ -2,6 +2,7 @@ package io.novafoundation.nova.feature_account_impl.presentation.account.common. import io.novafoundation.nova.common.list.toListWithHeaders import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.common.utils.WithCoroutineScopeExtensions import io.novafoundation.nova.common.utils.lazyAsync import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor @@ -25,19 +26,19 @@ class MetaAccountValidForTransactionListingMixinFactory( fun create( coroutineScope: CoroutineScope, - fromChainId: ChainId, - destinationChainId: ChainId, - selectedAddress: String? + chainId: ChainId, + selectedAddress: String?, + metaAccountFilter: Filter ): MetaAccountListingMixin { return MetaAccountValidForTransactionListingMixin( walletUiUseCase = walletUiUseCase, resourceManager = resourceManager, metaAccountGroupingInteractor = metaAccountGroupingInteractor, chainRegistry = chainRegistry, - fromChainId = fromChainId, - destinationChainId = destinationChainId, + chainId = chainId, selectedAddress = selectedAddress, accountTypePresentationMapper = accountTypePresentationMapper, + metaAccountFilter = metaAccountFilter, coroutineScope = coroutineScope ) } @@ -48,16 +49,16 @@ private class MetaAccountValidForTransactionListingMixin( private val resourceManager: ResourceManager, private val metaAccountGroupingInteractor: MetaAccountGroupingInteractor, private val chainRegistry: ChainRegistry, - private val fromChainId: ChainId, - private val destinationChainId: ChainId, + private val chainId: ChainId, private val selectedAddress: String?, private val accountTypePresentationMapper: MetaAccountTypePresentationMapper, + private val metaAccountFilter: Filter, coroutineScope: CoroutineScope, ) : MetaAccountListingMixin, WithCoroutineScopeExtensions by WithCoroutineScopeExtensions(coroutineScope) { - private val destinationChainFlow by coroutineScope.lazyAsync { chainRegistry.getChain(destinationChainId) } + private val chainFlow by coroutineScope.lazyAsync { chainRegistry.getChain(chainId) } - override val metaAccountsFlow = metaAccountGroupingInteractor.getMetaAccountsForTransaction(fromChainId, destinationChainId) + override val metaAccountsFlow = metaAccountGroupingInteractor.getMetaAccountsWithFilter(metaAccountFilter) .map { list -> list.toListWithHeaders( keyMapper = { type, _ -> accountTypePresentationMapper.mapMetaAccountTypeToUi(type) }, @@ -69,7 +70,7 @@ private class MetaAccountValidForTransactionListingMixin( private suspend fun mapMetaAccountToUi(metaAccount: MetaAccount): AccountUi { val icon = walletUiUseCase.walletIcon(metaAccount) - val chainAddress = metaAccount.addressIn(destinationChainFlow.await()) + val chainAddress = metaAccount.addressIn(chainFlow.await()) val isSelected = chainAddress != null && chainAddress == selectedAddress return AccountUi( diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressFragment.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressFragment.kt index edbacc2189..1894942e89 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressFragment.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressFragment.kt @@ -3,7 +3,7 @@ package io.novafoundation.nova.feature_account_impl.presentation.account.list.se import android.os.Bundle import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester import io.novafoundation.nova.feature_account_impl.R import io.novafoundation.nova.feature_account_impl.di.AccountFeatureComponent import io.novafoundation.nova.feature_account_impl.presentation.account.list.WalletListFragment @@ -13,7 +13,7 @@ class SelectAddressFragment : WalletListFragment() { companion object { private const val KEY_REQUEST = "KEY_REQUEST" - fun getBundle(request: SelectAddressForTransactionRequester.Request): Bundle { + fun getBundle(request: SelectAddressRequester.Request): Bundle { return Bundle().apply { putParcelable(KEY_REQUEST, request) } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressViewModel.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressViewModel.kt index 8405dcfe04..39f2882644 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressViewModel.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressViewModel.kt @@ -1,34 +1,50 @@ package io.novafoundation.nova.feature_account_impl.presentation.account.list.selectAddress +import io.novafoundation.nova.common.utils.EmptyFilter +import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInteractor +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.presenatation.account.listing.items.AccountUi import io.novafoundation.nova.feature_account_api.presenatation.account.listing.holders.AccountHolder -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionResponder +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester.Request +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressResponder import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountValidForTransactionListingMixinFactory import io.novafoundation.nova.feature_account_impl.presentation.account.list.WalletListViewModel +import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter import kotlinx.coroutines.launch class SelectAddressViewModel( accountListingMixinFactory: MetaAccountValidForTransactionListingMixinFactory, private val router: AccountRouter, - private val selectAddressResponder: SelectAddressForTransactionResponder, + private val selectAddressResponder: SelectAddressResponder, private val accountInteractor: AccountInteractor, - private val request: SelectAddressForTransactionRequester.Request, + private val request: Request, ) : WalletListViewModel() { - override val walletsListingMixin = accountListingMixinFactory.create(this, request.fromChainId, request.destinationChainId, request.selectedAddress) + override val walletsListingMixin = accountListingMixinFactory.create( + this, + request.chainId, + request.selectedAddress, + mapFilter(request.filter) + ) override val mode: AccountHolder.Mode = AccountHolder.Mode.SWITCH override fun accountClicked(accountModel: AccountUi) { launch { - val address = accountInteractor.getChainAddress(accountModel.id, request.destinationChainId) + val address = accountInteractor.getChainAddress(accountModel.id, request.chainId) if (address != null) { - selectAddressResponder.respond(SelectAddressForTransactionResponder.Response(address)) + selectAddressResponder.respond(SelectAddressResponder.Response(address)) router.back() } } } + + private fun mapFilter(filter: Request.Filter): Filter { + return when (filter) { + Request.Filter.Empty -> EmptyFilter() + is Request.Filter.ExcludeMetaIds -> MetaAccountFilter(MetaAccountFilter.Mode.EXCLUDE, filter.metaIds) + } + } } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressComponent.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressComponent.kt index b11a033f33..7bb85348b1 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressComponent.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressComponent.kt @@ -4,7 +4,7 @@ import androidx.fragment.app.Fragment import dagger.BindsInstance import dagger.Subcomponent import io.novafoundation.nova.common.di.scope.ScreenScope -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester import io.novafoundation.nova.feature_account_impl.presentation.account.list.selectAddress.SelectAddressFragment @Subcomponent( @@ -20,7 +20,7 @@ interface SelectAddressComponent { fun create( @BindsInstance fragment: Fragment, - @BindsInstance request: SelectAddressForTransactionRequester.Request + @BindsInstance request: SelectAddressRequester.Request ): SelectAddressComponent } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressModule.kt index 05ea40d16c..5d1aa851e8 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressModule.kt @@ -13,7 +13,7 @@ import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInter import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountTypePresentationMapper import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountValidForTransactionListingMixinFactory @@ -48,7 +48,7 @@ class SelectAddressModule { router: AccountRouter, selectAddressCommunicator: SelectAddressCommunicator, accountInteractor: AccountInteractor, - request: SelectAddressForTransactionRequester.Request + request: SelectAddressRequester.Request ): ViewModel { return SelectAddressViewModel( accountListingMixinFactory = accountListingMixinFactory, diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt index 70e2e91241..4fbd9cb531 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt @@ -1,11 +1,14 @@ package io.novafoundation.nova.feature_assets.presentation.send.amount import androidx.lifecycle.viewModelScope +import io.novafoundation.nova.common.address.intoKey import io.novafoundation.nova.common.base.BaseViewModel import io.novafoundation.nova.common.list.headers.TextHeader import io.novafoundation.nova.common.mixin.actionAwaitable.ActionAwaitableMixin import io.novafoundation.nova.common.mixin.api.Validatable import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.utils.EmptyFilter +import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.common.utils.inBackground import io.novafoundation.nova.common.utils.mapList import io.novafoundation.nova.common.utils.singleReplaySharedFlow @@ -14,9 +17,14 @@ import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.ButtonState import io.novafoundation.nova.feature_account_api.data.mappers.mapChainToUi import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount +import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn +import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_account_api.view.ChainChipModel @@ -34,6 +42,7 @@ import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.t import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.AssetTransferPayload import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.BaseAssetTransfer import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.WeightedAssetTransfer +import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_wallet_api.domain.interfaces.CrossChainTransfersUseCase import io.novafoundation.nova.feature_wallet_api.domain.model.Asset import io.novafoundation.nova.feature_wallet_api.domain.model.Token @@ -74,9 +83,10 @@ class SelectSendViewModel( private val initialRecipientAddress: String?, private val validationExecutor: ValidationExecutor, private val resourceManager: ResourceManager, - private val selectAddressRequester: SelectAddressForTransactionRequester, + private val selectAddressRequester: SelectAddressRequester, private val externalActions: ExternalActions.Presentation, private val crossChainTransfersUseCase: CrossChainTransfersUseCase, + private val accountRepository: AccountRepository, actionAwaitableMixinFactory: ActionAwaitableMixin.Factory, feeLoaderMixinFactory: FeeLoaderMixin.Factory, selectedAccountUseCase: SelectedAccountUseCase, @@ -118,7 +128,8 @@ class SelectSendViewModel( .shareInBackground() val isSelectAddressAvailable = combine(originChain, destinationChain) { originChain, destinationChain -> - metaAccountGroupingInteractor.hasAvailableMetaAccountsForDestination(originChain.id, destinationChain.id) + val metaAccountFilter = getMetaAccountsFilter(originChain, destinationChain) + metaAccountGroupingInteractor.hasAvailableMetaAccountsForChain(destinationChain.id, metaAccountFilter) } .shareInBackground() @@ -239,9 +250,10 @@ class SelectSendViewModel( fun selectRecipientWallet() { launch { val selectedAddress = addressInputMixin.inputFlow.value - val currentOriginChain = originChain.first() - val currentDestinationChain = destinationChain.first() - val request = SelectAddressForTransactionRequester.Request(currentOriginChain.id, currentDestinationChain.id, selectedAddress) + val originChain = originChain.first() + val destinationChain = destinationChain.first() + val filter = getMetaAccountsFilterPayload(originChain, destinationChain) + val request = SelectAddressRequester.Request(destinationChain.id, selectedAddress, filter) selectAddressRequester.openRequest(request) } } @@ -493,6 +505,34 @@ class SelectSendViewModel( } } + + private suspend fun getMetaAccountsFilterPayload(origin: Chain, desination: Chain): SelectAddressRequester.Request.Filter { + val isCrossChain = origin.id != desination.id + return if (isCrossChain) { + SelectAddressRequester.Request.Filter.Empty + } else { + val destinationAccountId = selectedAccount.first().requireAccountIdIn(desination) + val notOriginMetaAccounts = accountRepository.activeMetaAccounts() + .filter { it.accountIdIn(origin)?.intoKey() == destinationAccountId.intoKey() } + .map { it.id } + + SelectAddressRequester.Request.Filter.ExcludeMetaIds(notOriginMetaAccounts) + } + } + + private suspend fun getMetaAccountsFilter(origin: Chain, desination: Chain): Filter { + val filterPayload = getMetaAccountsFilterPayload(origin, desination) + + return when (filterPayload) { + is SelectAddressRequester.Request.Filter.Empty -> EmptyFilter() + + is SelectAddressRequester.Request.Filter.ExcludeMetaIds -> MetaAccountFilter( + MetaAccountFilter.Mode.EXCLUDE, + filterPayload.metaIds + ) + } + } + private class CrossChainDirection( val chainWithAsset: ChainWithAsset, val balances: Asset? diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt index 062ee11bb1..091d9ac9ad 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt @@ -11,6 +11,7 @@ import io.novafoundation.nova.common.di.viewmodel.ViewModelModule import io.novafoundation.nova.common.mixin.actionAwaitable.ActionAwaitableMixin import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator @@ -50,6 +51,7 @@ class SelectSendModule { selectedAccountUseCase: SelectedAccountUseCase, addressInputMixinFactory: AddressInputMixinFactory, amountChooserMixinFactory: AmountChooserMixin.Factory, + accountRepository: AccountRepository ): ViewModel { return SelectSendViewModel( chainRegistry = chainRegistry, @@ -68,7 +70,8 @@ class SelectSendModule { feeLoaderMixinFactory = feeLoaderMixinFactory, selectedAccountUseCase = selectedAccountUseCase, addressInputMixinFactory = addressInputMixinFactory, - amountChooserMixinFactory = amountChooserMixinFactory + amountChooserMixinFactory = amountChooserMixinFactory, + accountRepository = accountRepository ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt index 877fb98af6..a5fe332479 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt @@ -40,7 +40,7 @@ class AddStakingProxyFragment : BaseFragment() { setStakingProxyContainer.applyStatusBarInsets() addStakingProxyButton.prepareForProgress(this) - addStakingProxySelectWallet.setOnClickListener { viewModel.selectRecipientWallet() } + addStakingProxySelectWallet.setOnClickListener { viewModel.selectAuthorityWallet() } addStakingProxyButton.setOnClickListener { viewModel.onConfirmClick() } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt index 97c8b4a354..df78659cb2 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt @@ -1,5 +1,6 @@ package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set +import io.novafoundation.nova.common.address.intoKey import io.novafoundation.nova.common.base.BaseViewModel import io.novafoundation.nova.common.mixin.api.Validatable import io.novafoundation.nova.common.presentation.DescriptiveButtonState @@ -8,8 +9,10 @@ import io.novafoundation.nova.common.utils.flowOf import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn +import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressForTransactionRequester +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity @@ -20,18 +23,20 @@ import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase +import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.awaitDecimalFee import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.create import io.novafoundation.nova.feature_wallet_api.presentation.model.AmountModel import io.novafoundation.nova.feature_wallet_api.presentation.model.mapAmountToAmountModel -import io.novafoundation.nova.runtime.ext.accountIdOrNull import io.novafoundation.nova.runtime.ext.commissionAsset +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState import io.novafoundation.nova.runtime.state.assetWithChain import io.novafoundation.nova.runtime.state.chain import io.novafoundation.nova.runtime.state.selectedAssetFlow import io.novafoundation.nova.runtime.state.selectedChainFlow +import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -52,7 +57,7 @@ class AddStakingProxyViewModel( private val accountRepository: AccountRepository, private val assetUseCase: ArbitraryAssetUseCase, private val resourceManager: ResourceManager, - private val selectAddressRequester: SelectAddressForTransactionRequester, + private val selectAddressRequester: SelectAddressRequester, private val addStakingProxyRepository: AddStakingProxyRepository, private val validationExecutor: ValidationExecutor, private val addStakingProxyValidationSystem: AddStakingProxyValidationSystem @@ -127,13 +132,18 @@ class AddStakingProxyViewModel( init { runFeeUpdate() + + subscribeOnSelectAddress() } - fun selectRecipientWallet() { + fun selectAuthorityWallet() { launch { - val selectedAddress = addressInputMixin.inputFlow.value + val metaAccount = accountRepository.getSelectedMetaAccount() val chain = selectedAssetState.chain() - val request = SelectAddressForTransactionRequester.Request(chain.id, chain.id, selectedAddress) + val proxiedAccountId = metaAccount.requireAccountIdIn(chain) + val selectedAddress = addressInputMixin.inputFlow.value + val filter = filterMetaAccountsWithSameAccountId(chain, proxiedAccountId) + val request = SelectAddressRequester.Request(chain.id, selectedAddress, filter) selectAddressRequester.openRequest(request) } } @@ -164,6 +174,14 @@ class AddStakingProxyViewModel( TODO() } + private fun subscribeOnSelectAddress() { + selectAddressRequester.responseFlow + .onEach { + addressInputMixin.inputFlow.value = it.selectedAddress + } + .launchIn(this) + } + private fun runFeeUpdate() { addressInputMixin.inputFlow.onEach { val metaAccount = accountRepository.getSelectedMetaAccount() @@ -183,4 +201,12 @@ class AddStakingProxyViewModel( externalActions.showExternalActions(ExternalActions.Type.Address(address), chain) } } + + private suspend fun filterMetaAccountsWithSameAccountId(chain: Chain, accountId: AccountId): SelectAddressRequester.Request.Filter { + val filteredMetaAccounts = accountRepository.activeMetaAccounts() + .filter { it.accountIdIn(chain)?.intoKey() == accountId.intoKey() } + .map { it.id } + + return SelectAddressRequester.Request.Filter.ExcludeMetaIds(filteredMetaAccounts) + } } diff --git a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/filter/MetaAccountFilter.kt b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/filter/MetaAccountFilter.kt new file mode 100644 index 0000000000..5354501f8f --- /dev/null +++ b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/filter/MetaAccountFilter.kt @@ -0,0 +1,19 @@ +package io.novafoundation.nova.feature_wallet_api.domain.filter + +import io.novafoundation.nova.common.utils.Filter +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount + +class MetaAccountFilter(private val mode: Mode, private val metaIds: List) : Filter { + + enum class Mode { + INCLUDE, + EXCLUDE + } + + override fun shouldInclude(model: MetaAccount): Boolean { + return when (mode) { + Mode.INCLUDE -> metaIds.contains(model.id) + Mode.EXCLUDE -> !metaIds.contains(model.id) + } + } +} From 2f037c79e09d0807ec1d22b41ca6a70e7cb2b7c1 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 9 Jan 2024 05:52:42 +0100 Subject: [PATCH 05/55] Minor changes --- .../nova/common/view/YourWalletsView.kt | 18 ------------------ common/src/main/res/values/strings.xml | 3 +++ .../di/AccountFeatureApi.kt | 1 - .../data/mappers/Mappers.kt | 18 +++++++++--------- .../send/amount/SelectSendViewModel.kt | 2 -- .../data/calls/ExtrinsicBuilderExt.kt | 1 - .../data/common/ProxyDepositCalculator.kt | 4 ---- .../data/repository/RealGetProxyRepository.kt | 1 - .../di/ProxyFeatureHolder.kt | 2 -- .../data/proxy/AddStakingProxyRepository.kt | 2 -- .../proxy/RealAddStakingProxyRepository.kt | 2 -- .../di/StakingFeatureDependencies.kt | 3 +++ .../AddProxyValidationFailureHandling.kt | 1 - .../proxy/set/AddStakingProxyFragment.kt | 3 +++ .../proxy/set/AddStakingProxyViewModel.kt | 16 ++++++++++++---- .../proxy/set/di/AddStakingProxyModule.kt | 7 +++++-- .../NominationPoolsStakeActionsComponent.kt | 9 --------- .../ParachainStakeActionsComponent.kt | 2 +- .../RelaychainStakeActionsComponent.kt | 2 +- 19 files changed, 37 insertions(+), 60 deletions(-) diff --git a/common/src/main/java/io/novafoundation/nova/common/view/YourWalletsView.kt b/common/src/main/java/io/novafoundation/nova/common/view/YourWalletsView.kt index 26c6daf113..5d77521a4f 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/YourWalletsView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/YourWalletsView.kt @@ -1,34 +1,16 @@ package io.novafoundation.nova.common.view import android.content.Context -import android.content.res.ColorStateList -import android.graphics.drawable.Drawable import android.util.AttributeSet import android.view.Gravity import android.view.View -import android.widget.ImageView import android.widget.LinearLayout -import android.widget.TextView -import androidx.annotation.ColorInt -import androidx.annotation.ColorRes -import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.setPadding -import coil.ImageLoader -import coil.load import io.novafoundation.nova.common.R import io.novafoundation.nova.common.utils.dp -import io.novafoundation.nova.common.utils.getResourceIdOrNull import io.novafoundation.nova.common.utils.getRippleMask import io.novafoundation.nova.common.utils.getRoundedCornerDrawable -import io.novafoundation.nova.common.utils.setTextOrHide -import io.novafoundation.nova.common.utils.setVisible import io.novafoundation.nova.common.utils.withRippleMask -import kotlinx.android.synthetic.main.view_go_next.view.goNextActionImage -import kotlinx.android.synthetic.main.view_go_next.view.goNextBadgeText -import kotlinx.android.synthetic.main.view_go_next.view.goNextDivider -import kotlinx.android.synthetic.main.view_go_next.view.goNextIcon -import kotlinx.android.synthetic.main.view_go_next.view.goNextProgress -import kotlinx.android.synthetic.main.view_go_next.view.goNextTitle class YourWalletsView @JvmOverloads constructor( context: Context, diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 0426a5d83b..d6e2f1f682 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,6 +1,9 @@ + Proxy deposit + The deposit stays reserved on your account until the proxy is removed. + Maximum number of proxies has been reached You have reached the limit of %s added proxies in %s. Remove proxies to add new ones. diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt index b40ceb466b..feb3725a42 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt @@ -81,7 +81,6 @@ interface AccountFeatureApi { fun ledgerAddAccountRepository(): LedgerAddAccountRepository - val evmTransactionService: EvmTransactionService val identityMixinFactory: IdentityMixin.Factory diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/mappers/Mappers.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/mappers/Mappers.kt index 035e50c674..4855059dd1 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/mappers/Mappers.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/mappers/Mappers.kt @@ -42,21 +42,21 @@ fun mapCryptoTypeToCryptoTypeModel( ): CryptoTypeModel { val name = when (encryptionType) { CryptoType.SR25519 -> "${resourceManager.getString(R.string.sr25519_selection_title)} ${ - resourceManager.getString( - R.string.sr25519_selection_subtitle - ) + resourceManager.getString( + R.string.sr25519_selection_subtitle + ) }" CryptoType.ED25519 -> "${resourceManager.getString(R.string.ed25519_selection_title)} ${ - resourceManager.getString( - R.string.ed25519_selection_subtitle - ) + resourceManager.getString( + R.string.ed25519_selection_subtitle + ) }" CryptoType.ECDSA -> "${resourceManager.getString(R.string.ecdsa_selection_title)} ${ - resourceManager.getString( - R.string.ecdsa_selection_subtitle - ) + resourceManager.getString( + R.string.ecdsa_selection_subtitle + ) }" } diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt index 4fbd9cb531..4fd485a389 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt @@ -22,7 +22,6 @@ import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountG import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn -import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions @@ -505,7 +504,6 @@ class SelectSendViewModel( } } - private suspend fun getMetaAccountsFilterPayload(origin: Chain, desination: Chain): SelectAddressRequester.Request.Filter { val isCrossChain = origin.id != desination.id return if (isCrossChain) { diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt index f948b3d2ac..5504d33eed 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt @@ -8,7 +8,6 @@ import jp.co.soramitsu.fearless_utils.runtime.definitions.types.composite.DictEn import jp.co.soramitsu.fearless_utils.runtime.definitions.types.instances.AddressInstanceConstructor import jp.co.soramitsu.fearless_utils.runtime.extrinsic.ExtrinsicBuilder - fun ExtrinsicBuilder.addProxyCall(proxyAccountId: AccountId, proxyType: ProxyType): ExtrinsicBuilder { return call( Modules.PROXY, diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt index de018dc158..cc00a7be8b 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt @@ -1,10 +1,6 @@ package io.novafoundation.nova.feature_proxy_api.data.common -import io.novafoundation.nova.common.utils.numberConstant -import io.novafoundation.nova.common.utils.proxy -import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain -import io.novafoundation.nova.runtime.multiNetwork.getRuntime import java.math.BigInteger class DepositBaseAndFactor( diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt index 9aa71e7a38..64c3490f58 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt @@ -20,7 +20,6 @@ import jp.co.soramitsu.fearless_utils.runtime.AccountId import jp.co.soramitsu.fearless_utils.runtime.metadata.module import jp.co.soramitsu.fearless_utils.runtime.metadata.storage - private class OnChainProxiedModel( val proxies: List, val deposit: BigInteger diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureHolder.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureHolder.kt index 055221d857..24efb1ce8e 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureHolder.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureHolder.kt @@ -3,8 +3,6 @@ package io.novafoundation.nova.feature_proxy_impl.di import io.novafoundation.nova.common.di.FeatureApiHolder import io.novafoundation.nova.common.di.FeatureContainer import io.novafoundation.nova.common.di.scope.ApplicationScope -import io.novafoundation.nova.feature_proxy_impl.di.DaggerProxyFeatureComponent -import io.novafoundation.nova.feature_proxy_impl.di.DaggerProxyFeatureComponent_VoteFeatureDependenciesComponent import io.novafoundation.nova.runtime.di.RuntimeApi import javax.inject.Inject diff --git a/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt b/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt index b3eeb0df18..ac29f6ef73 100644 --- a/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt +++ b/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt @@ -3,9 +3,7 @@ package io.novafoundation.nova.feature_staking_api.data.proxy import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity -import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain -import java.math.BigInteger import jp.co.soramitsu.fearless_utils.runtime.AccountId interface AddStakingProxyRepository { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt index 65caee4fa9..2db497ab2f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt @@ -10,7 +10,6 @@ import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepo import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType -import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.runtime.ext.emptyAccountId import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId @@ -33,7 +32,6 @@ class RealAddStakingProxyRepository( override suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { return withContext(Dispatchers.IO) { - extrinsicService.submitExtrinsic(chain, proxiedAccountId.intoOrigin()) { addProxyCall(proxyAccountId, ProxyType.Staking) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt index fedead1805..e128d0b031 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt @@ -16,6 +16,7 @@ import io.novafoundation.nova.common.resources.ContextManager import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.multiResult.PartialRetriableMixin import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher import io.novafoundation.nova.core.storage.StorageCache import io.novafoundation.nova.core_db.dao.AccountStakingDao import io.novafoundation.nova.core_db.dao.ExternalBalanceDao @@ -172,4 +173,6 @@ interface StakingFeatureDependencies { val proxyDepositCalculator: ProxyDepositCalculator val getProxyRepository: GetProxyRepository + + val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt index 77db6402fb..5a82349bce 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt @@ -2,7 +2,6 @@ package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegat import io.novafoundation.nova.common.base.TitleAndMessage import io.novafoundation.nova.common.resources.ResourceManager -import io.novafoundation.nova.common.utils.formatting.format import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure.* diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt index a5fe332479..17bb32bd69 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt @@ -9,6 +9,7 @@ import io.novafoundation.nova.common.base.BaseFragment import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.common.mixin.impl.observeValidations import io.novafoundation.nova.common.utils.applyStatusBarInsets +import io.novafoundation.nova.common.view.bottomSheet.description.observeDescription import io.novafoundation.nova.common.view.setState import io.novafoundation.nova.feature_account_api.presenatation.actions.setupExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.setupAddressInput @@ -42,6 +43,7 @@ class AddStakingProxyFragment : BaseFragment() { addStakingProxySelectWallet.setOnClickListener { viewModel.selectAuthorityWallet() } addStakingProxyButton.setOnClickListener { viewModel.onConfirmClick() } + addStakingProxyDeposit.setOnClickListener { viewModel.showProxyDepositDescription() } } override fun inject() { @@ -57,6 +59,7 @@ class AddStakingProxyFragment : BaseFragment() { override fun subscribe(viewModel: AddStakingProxyViewModel) { setupExternalActions(viewModel) observeValidations(viewModel) + observeDescription(viewModel) setupAddressInput(viewModel.addressInputMixin, setStakingProxyAddress) setupExternalAccounts(viewModel.addressInputMixin, setStakingProxyAddress) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt index df78659cb2..9824de2a48 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt @@ -8,9 +8,9 @@ import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.flowOf import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.validation.progressConsumer +import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn -import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions @@ -23,7 +23,6 @@ import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase -import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.awaitDecimalFee import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.create @@ -60,8 +59,10 @@ class AddStakingProxyViewModel( private val selectAddressRequester: SelectAddressRequester, private val addStakingProxyRepository: AddStakingProxyRepository, private val validationExecutor: ValidationExecutor, - private val addStakingProxyValidationSystem: AddStakingProxyValidationSystem + private val addStakingProxyValidationSystem: AddStakingProxyValidationSystem, + private val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, ) : BaseViewModel(), + DescriptionBottomSheetLauncher by descriptionBottomSheetLauncher, ExternalActions by externalActions, Validatable by validationExecutor { @@ -132,10 +133,17 @@ class AddStakingProxyViewModel( init { runFeeUpdate() - + subscribeOnSelectAddress() } + fun showProxyDepositDescription() { + descriptionBottomSheetLauncher.launchDescriptionBottomSheet( + titleRes = R.string.add_proxy_deposit_description_title, + descriptionRes = R.string.add_proxy_deposit_description_message + ) + } + fun selectAuthorityWallet() { launch { val metaAccount = accountRepository.getSelectedMetaAccount() diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt index 833a95bd92..c1e9496961 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt @@ -10,6 +10,7 @@ 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.common.validation.ValidationExecutor +import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions @@ -40,7 +41,8 @@ class AddStakingProxyModule { selectAddressCommunicator: SelectAddressCommunicator, addStakingProxyRepository: AddStakingProxyRepository, validationExecutor: ValidationExecutor, - addStakingProxyValidationSystem: AddStakingProxyValidationSystem + addStakingProxyValidationSystem: AddStakingProxyValidationSystem, + descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher ): ViewModel { return AddStakingProxyViewModel( addressInputMixinFactory = addressInputMixinFactory, @@ -54,7 +56,8 @@ class AddStakingProxyModule { selectAddressRequester = selectAddressCommunicator, addStakingProxyRepository = addStakingProxyRepository, validationExecutor = validationExecutor, - addStakingProxyValidationSystem = addStakingProxyValidationSystem + addStakingProxyValidationSystem = addStakingProxyValidationSystem, + descriptionBottomSheetLauncher = descriptionBottomSheetLauncher ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt index 0568981638..0c4ccc40fd 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt @@ -10,8 +10,6 @@ import io.novafoundation.nova.feature_staking_impl.data.StakingOption import io.novafoundation.nova.feature_staking_impl.data.chain import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network.blockhain.models.PoolMember import io.novafoundation.nova.feature_staking_impl.domain.nominationPools.common.NominationPoolSharedComputation -import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_ADD_PROXY -import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_PROXIES import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_BOND_MORE import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_UNBOND import io.novafoundation.nova.feature_staking_impl.presentation.NominationPoolsRouter @@ -22,7 +20,6 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.com import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsEvent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsState -import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.addStakingProxy import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.bondMore import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.unbond import kotlinx.coroutines.CoroutineScope @@ -79,8 +76,6 @@ private open class NominationPoolsStakeActionsComponent( when (action.id) { SYSTEM_MANAGE_STAKING_BOND_MORE -> router.openSetupBondMore() SYSTEM_MANAGE_STAKING_UNBOND -> router.openSetupUnbond() - SYSTEM_ADD_PROXY -> router.openSetStakingProxy() - SYSTEM_MANAGE_PROXIES -> TODO() } } @@ -95,9 +90,5 @@ private open class NominationPoolsStakeActionsComponent( private fun availablePoolMemberActions(): List = buildList { add(ManageStakeAction.bondMore(resourceManager)) add(ManageStakeAction.unbond(resourceManager)) - - if (stakingOption.chain.supportProxy) { - add(ManageStakeAction.addStakingProxy(resourceManager)) - } } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt index 769c3836ac..1e3442fe39 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt @@ -119,7 +119,7 @@ internal open class ParachainStakeActionsComponent( add(ManageStakeAction.collators(resourceManager, collatorsCount)) if (stakingOption.chain.supportProxy) { - add(ManageStakeAction.addStakingProxy(resourceManager)) //TODO: handle case when proxy is already set + add(ManageStakeAction.addStakingProxy(resourceManager)) // TODO: handle case when proxy is already set } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt index c1145e7360..0cae81d7d0 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt @@ -145,7 +145,7 @@ private class RelaychainStakeActionsComponent( add(ManageStakeAction.Companion::controller) if (stakingOption.chain.supportProxy) { - add(ManageStakeAction.Companion::addStakingProxy) //TODO: handle case when proxy is already set + add(ManageStakeAction.Companion::addStakingProxy) // TODO: handle case when proxy is already set } }.map { it.invoke(resourceManager) } } From 88aa6bfbd9fd0c3e59ba5dc1e71f2a85c98e9b46 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 9 Jan 2024 05:55:42 +0100 Subject: [PATCH 06/55] Update ProxyCallFilterFactory.kt --- .../signer/proxy/ProxyCallFilterFactory.kt | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxyCallFilterFactory.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxyCallFilterFactory.kt index df6404d7cb..89a9f6dcd5 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxyCallFilterFactory.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxyCallFilterFactory.kt @@ -6,16 +6,17 @@ import io.novafoundation.nova.feature_account_impl.data.signer.proxy.callFilter. import io.novafoundation.nova.feature_account_impl.data.signer.proxy.callFilter.AnyOfCallFilter import io.novafoundation.nova.feature_account_impl.data.signer.proxy.callFilter.EverythingFilter import io.novafoundation.nova.feature_account_impl.data.signer.proxy.callFilter.WhiteListFilter +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import jp.co.soramitsu.fearless_utils.runtime.definitions.types.generics.GenericCall class ProxyCallFilterFactory { - fun getCallFilterFor(proxyType: ProxyAccount.ProxyType): CallFilter { + fun getCallFilterFor(proxyType: ProxyType): CallFilter { return when (proxyType) { - ProxyAccount.ProxyType.Any, - is ProxyAccount.ProxyType.Other -> EverythingFilter() + ProxyType.Any, + is ProxyType.Other -> EverythingFilter() - ProxyAccount.ProxyType.NonTransfer -> AnyOfCallFilter( + ProxyType.NonTransfer -> AnyOfCallFilter( WhiteListFilter(Modules.SYSTEM), WhiteListFilter(Modules.SCHEDULER), WhiteListFilter(Modules.BABE), @@ -46,7 +47,7 @@ class ProxyCallFilterFactory { WhiteListFilter(Modules.FAST_UNSTAKE) ) - ProxyAccount.ProxyType.Governance -> AnyOfCallFilter( + ProxyType.Governance -> AnyOfCallFilter( WhiteListFilter(Modules.TREASURY), WhiteListFilter(Modules.BOUNTIES), WhiteListFilter(Modules.UTILITY), @@ -56,7 +57,7 @@ class ProxyCallFilterFactory { WhiteListFilter(Modules.WHITELIST) ) - ProxyAccount.ProxyType.Staking -> AnyOfCallFilter( + ProxyType.Staking -> AnyOfCallFilter( WhiteListFilter(Modules.STAKING), WhiteListFilter(Modules.SESSION), WhiteListFilter(Modules.UTILITY), @@ -65,19 +66,19 @@ class ProxyCallFilterFactory { WhiteListFilter(Modules.NOMINATION_POOLS) ) - ProxyAccount.ProxyType.NominationPools -> AnyOfCallFilter( + ProxyType.NominationPools -> AnyOfCallFilter( WhiteListFilter(Modules.NOMINATION_POOLS), WhiteListFilter(Modules.UTILITY) ) - ProxyAccount.ProxyType.IdentityJudgement -> AnyOfCallFilter( + ProxyType.IdentityJudgement -> AnyOfCallFilter( WhiteListFilter(Modules.IDENTITY, listOf("provide_judgement")), WhiteListFilter(Modules.UTILITY) ) - ProxyAccount.ProxyType.CancelProxy -> WhiteListFilter(Modules.PROXY, listOf("reject_announcement")) + ProxyType.CancelProxy -> WhiteListFilter(Modules.PROXY, listOf("reject_announcement")) - ProxyAccount.ProxyType.Auction -> AnyOfCallFilter( + ProxyType.Auction -> AnyOfCallFilter( WhiteListFilter(Modules.AUCTIONS), WhiteListFilter(Modules.CROWDLOAN), WhiteListFilter(Modules.REGISTRAR), @@ -87,7 +88,7 @@ class ProxyCallFilterFactory { } } -fun ProxyCallFilterFactory.getFirstMatchedTypeOrNull(call: GenericCall.Instance, proxyTypes: List): ProxyAccount.ProxyType? { +fun ProxyCallFilterFactory.getFirstMatchedTypeOrNull(call: GenericCall.Instance, proxyTypes: List): ProxyType? { return proxyTypes.firstOrNull { val callFilter = this.getCallFilterFor(it) callFilter.canExecute(call) From a2dea6308385b8c27e1a6f16ef6853aa0037ab77 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 9 Jan 2024 06:46:46 +0100 Subject: [PATCH 07/55] Clean code --- .../nova/app/root/di/RootDependencies.kt | 2 +- .../nova/app/root/di/RootFeatureModule.kt | 2 +- .../nova/app/root/domain/RootInteractor.kt | 2 +- .../NominationPoolsStakingNavigator.kt | 4 ---- .../parachain/ParachainStakingNavigator.kt | 4 ++-- .../relaychain/RelayStakingNavigator.kt | 4 ++-- .../res/navigation/staking_main_graph.xml | 6 +++--- .../data/proxy/ProxySyncService.kt | 6 ++++++ .../data/proxy/sync/ProxySyncService.kt | 6 ------ .../di/AccountFeatureApi.kt | 2 +- .../proxy/{sync => }/RealProxySyncService.kt | 11 ++-------- .../addAccount/BaseAddAccountRepository.kt | 2 +- .../ledger/RealLedgerAddAccountRepository.kt | 2 +- .../ParitySignerAddAccountRepository.kt | 2 +- .../secrets/JsonAddAccountRepository.kt | 2 +- .../secrets/MnemonicAddAccountRepository.kt | 2 +- .../secrets/SecretsAddAccountRepository.kt | 2 +- .../secrets/SeedAddAccountRepository.kt | 2 +- .../WatchOnlyAddAccountRepository.kt | 2 +- .../signer/proxy/ProxyCallFilterFactory.kt | 1 - .../di/AccountFeatureModule.kt | 4 ++-- .../di/AddAccountsModule.kt | 2 +- .../data/repository/GetProxyRepository.kt | 2 +- ...EnoughAmountToPayProxyDepositValidation.kt | 5 ++--- ... => MaximumProxiesNotReachedValidation.kt} | 6 +++--- .../data/repository/RealGetProxyRepository.kt | 2 +- .../di/StakingFeatureDependencies.kt | 3 +++ .../proxy/AddStakingProxyValidationFailure.kt | 2 +- .../delegation/proxy/Declarations.kt | 2 +- .../presentation/NominationPoolsRouter.kt | 2 -- .../presentation/ParachainStakingRouter.kt | 2 +- .../presentation/StakingRouter.kt | 2 +- .../controller/set/SetControllerFragment.kt | 4 ++-- .../AddProxyValidationFailureHandling.kt | 2 +- .../proxy/set/AddStakingProxyFragment.kt | 16 +++++++-------- .../proxy/set/AddStakingProxyViewModel.kt | 20 ++++++++++++++++--- .../proxy/set/di/AddStakingProxyModule.kt | 7 +++++-- .../NominationPoolsStakeActionsComponent.kt | 10 +++++----- .../ParachainStakeActionsComponent.kt | 2 +- .../RelaychainStakeActionsComponent.kt | 2 +- ...oxy.xml => fragment_add_staking_proxy.xml} | 2 +- .../fragment_set_controller_account.xml | 2 +- .../assets/transfers/validations/Common.kt | 9 ++++----- 43 files changed, 90 insertions(+), 86 deletions(-) create mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/ProxySyncService.kt delete mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/sync/ProxySyncService.kt rename feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/{sync => }/RealProxySyncService.kt (94%) rename feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/{MaximumProxiesNotReachedValidator.kt => MaximumProxiesNotReachedValidation.kt} (90%) rename feature-staking-impl/src/main/res/layout/{fragment_set_staking_proxy.xml => fragment_add_staking_proxy.xml} (98%) diff --git a/app/src/main/java/io/novafoundation/nova/app/root/di/RootDependencies.kt b/app/src/main/java/io/novafoundation/nova/app/root/di/RootDependencies.kt index 2a35d2b664..5eea5fa6ed 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/di/RootDependencies.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/di/RootDependencies.kt @@ -10,7 +10,7 @@ import io.novafoundation.nova.common.utils.coroutines.RootScope import io.novafoundation.nova.common.utils.sequrity.AutomaticInteractionGate import io.novafoundation.nova.common.utils.sequrity.BackgroundAccessObserver import io.novafoundation.nova.common.utils.systemCall.SystemCallExecutor -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxyExtrinsicValidationRequestBus import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.account.common.EncryptionDefaults diff --git a/app/src/main/java/io/novafoundation/nova/app/root/di/RootFeatureModule.kt b/app/src/main/java/io/novafoundation/nova/app/root/di/RootFeatureModule.kt index d7d8e8040f..acdb0015f2 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/di/RootFeatureModule.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/di/RootFeatureModule.kt @@ -5,7 +5,7 @@ import dagger.Provides import io.novafoundation.nova.app.root.di.busHandler.RequestBusHandlerModule import io.novafoundation.nova.app.root.domain.RootInteractor import io.novafoundation.nova.common.di.scope.FeatureScope -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_assets.data.network.BalancesUpdateSystem import io.novafoundation.nova.feature_wallet_api.domain.interfaces.WalletRepository diff --git a/app/src/main/java/io/novafoundation/nova/app/root/domain/RootInteractor.kt b/app/src/main/java/io/novafoundation/nova/app/root/domain/RootInteractor.kt index 48b5609a6e..d5a3fa40a8 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/domain/RootInteractor.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/domain/RootInteractor.kt @@ -1,7 +1,7 @@ package io.novafoundation.nova.app.root.domain import io.novafoundation.nova.core.updater.Updater -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_assets.data.network.BalancesUpdateSystem import io.novafoundation.nova.feature_buy_impl.domain.providers.ExternalProvider diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/nominationPools/NominationPoolsStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/nominationPools/NominationPoolsStakingNavigator.kt index bc2be82d0b..43cd6f6fb3 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/nominationPools/NominationPoolsStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/nominationPools/NominationPoolsStakingNavigator.kt @@ -38,8 +38,4 @@ class NominationPoolsStakingNavigator( override fun returnToMain() { commonNavigator.returnToMain() } - - override fun openSetStakingProxy() { - performNavigation(R.id.action_open_setStakingProxyFragment) - } } diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/parachain/ParachainStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/parachain/ParachainStakingNavigator.kt index 3f7b041d5c..38be483e81 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/parachain/ParachainStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/parachain/ParachainStakingNavigator.kt @@ -73,7 +73,7 @@ class ParachainStakingNavigator( args = YieldBoostConfirmFragment.getBundle(payload) ) - override fun openSetStakingProxy() { - performNavigation(R.id.action_open_setStakingProxyFragment) + override fun openAddStakingProxy() { + performNavigation(R.id.action_open_addStakingProxyFragment) } } diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt index 6b341cf1fa..4e6531b216 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt @@ -223,7 +223,7 @@ class RelayStakingNavigator( } } - override fun openSetStakingProxy() { - performNavigation(R.id.action_open_setStakingProxyFragment) + override fun openAddStakingProxy() { + performNavigation(R.id.action_open_addStakingProxyFragment) } } diff --git a/app/src/main/res/navigation/staking_main_graph.xml b/app/src/main/res/navigation/staking_main_graph.xml index 553e964e56..19f9ea5ede 100644 --- a/app/src/main/res/navigation/staking_main_graph.xml +++ b/app/src/main/res/navigation/staking_main_graph.xml @@ -30,15 +30,15 @@ app:popExitAnim="@anim/fragment_close_exit" /> diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/ProxySyncService.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/ProxySyncService.kt new file mode 100644 index 0000000000..b54663ec26 --- /dev/null +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/ProxySyncService.kt @@ -0,0 +1,6 @@ +package io.novafoundation.nova.feature_account_api.data.proxy + +interface ProxySyncService { + + fun startSyncing() +} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/sync/ProxySyncService.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/sync/ProxySyncService.kt deleted file mode 100644 index 7f412880a2..0000000000 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/proxy/sync/ProxySyncService.kt +++ /dev/null @@ -1,6 +0,0 @@ -package io.novafoundation.nova.feature_account_api.data.proxy.sync - -interface ProxySyncService { - - fun startSyncing() -} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt index feb3725a42..72ca04deb9 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt @@ -5,7 +5,7 @@ import io.novafoundation.nova.common.sequrity.TwoFactorVerificationExecutor import io.novafoundation.nova.common.utils.MutableSharedState import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.EvmTransactionService import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxyExtrinsicValidationRequestBus import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository import io.novafoundation.nova.feature_account_api.data.repository.addAccount.ledger.LedgerAddAccountRepository diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/sync/RealProxySyncService.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt similarity index 94% rename from feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/sync/RealProxySyncService.kt rename to feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt index abd424c775..7a3f515f61 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/sync/RealProxySyncService.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_account_impl.data.proxy.sync +package io.novafoundation.nova.feature_account_impl.data.proxy import android.util.Log import io.novafoundation.nova.common.address.AccountIdKey @@ -13,7 +13,7 @@ import io.novafoundation.nova.core_db.model.chain.account.ProxyAccountLocal import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy import io.novafoundation.nova.feature_account_api.data.proxy.MetaAccountsUpdatesRegistry import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.identity.Identity import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository @@ -25,7 +25,6 @@ import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import io.novafoundation.nova.runtime.multiNetwork.findChains -import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -141,12 +140,6 @@ class RealProxySyncService( return chainRegistry.findChains { it.supportProxy } } - private fun Chain.getAvailableAccountIds2(metaAccounts: List): List { - return metaAccounts.mapNotNull { metaAccount -> - metaAccount.accountIdIn(chain = this) - } - } - private fun Chain.getAvailableAccountIds(metaAccounts: List): GroupedList { return metaAccounts.mapNotNull { metaAccount -> val accountId = metaAccount.accountIdIn(chain = this) diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/BaseAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/BaseAddAccountRepository.kt index bf17941a76..b2467f2e36 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/BaseAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/BaseAddAccountRepository.kt @@ -1,7 +1,7 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.addAccount.AddAccountRepository -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService abstract class BaseAddAccountRepository( private val proxySyncService: ProxySyncService diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/ledger/RealLedgerAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/ledger/RealLedgerAddAccountRepository.kt index f4f6c93abd..db8a06b083 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/ledger/RealLedgerAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/ledger/RealLedgerAddAccountRepository.kt @@ -5,8 +5,8 @@ import io.novafoundation.nova.common.data.secrets.v2.SecretStoreV2 import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.model.chain.account.ChainAccountLocal import io.novafoundation.nova.core_db.model.chain.account.MetaAccountLocal +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.BaseAddAccountRepository -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.addAccount.ledger.LedgerAddAccountRepository import io.novafoundation.nova.feature_account_api.data.repository.addAccount.ledger.LedgerAddAccountRepository.Payload import io.novafoundation.nova.feature_ledger_api.data.repository.LedgerDerivationPath diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/paritySigner/ParitySignerAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/paritySigner/ParitySignerAddAccountRepository.kt index d58b26a925..c9caff9060 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/paritySigner/ParitySignerAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/paritySigner/ParitySignerAddAccountRepository.kt @@ -3,7 +3,7 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.p import io.novafoundation.nova.core.model.CryptoType import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.model.chain.account.MetaAccountLocal -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.model.PolkadotVaultVariant import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.BaseAddAccountRepository import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/JsonAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/JsonAddAccountRepository.kt index 18a32a3d61..1513108ce3 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/JsonAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/JsonAddAccountRepository.kt @@ -2,7 +2,7 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.s import io.novafoundation.nova.common.data.mappers.mapEncryptionToCryptoType import io.novafoundation.nova.common.utils.removeHexPrefix -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.advancedEncryption.AdvancedEncryption import io.novafoundation.nova.feature_account_api.domain.model.AddAccountType import io.novafoundation.nova.feature_account_api.domain.model.ImportJsonMetaData diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/MnemonicAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/MnemonicAddAccountRepository.kt index 686264ed7a..56738c682c 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/MnemonicAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/MnemonicAddAccountRepository.kt @@ -1,6 +1,6 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.advancedEncryption.AdvancedEncryption import io.novafoundation.nova.feature_account_api.domain.model.AddAccountType import io.novafoundation.nova.feature_account_impl.data.repository.datasource.AccountDataSource diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SecretsAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SecretsAddAccountRepository.kt index ef4e3224a4..9c710fe5cc 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SecretsAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SecretsAddAccountRepository.kt @@ -2,7 +2,7 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.s import android.database.sqlite.SQLiteConstraintException import io.novafoundation.nova.core.model.CryptoType -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.BaseAddAccountRepository import io.novafoundation.nova.feature_account_api.domain.account.advancedEncryption.AdvancedEncryption import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountAlreadyExistsException diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SeedAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SeedAddAccountRepository.kt index 85c97a5e84..fdafbcdc67 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SeedAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/secrets/SeedAddAccountRepository.kt @@ -1,6 +1,6 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.advancedEncryption.AdvancedEncryption import io.novafoundation.nova.feature_account_api.domain.model.AddAccountType import io.novafoundation.nova.feature_account_impl.data.repository.datasource.AccountDataSource diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/watchOnly/WatchOnlyAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/watchOnly/WatchOnlyAddAccountRepository.kt index 0c73e58178..e27f5400e9 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/watchOnly/WatchOnlyAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/watchOnly/WatchOnlyAddAccountRepository.kt @@ -3,7 +3,7 @@ package io.novafoundation.nova.feature_account_impl.data.repository.addAccount.w import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.model.chain.account.ChainAccountLocal import io.novafoundation.nova.core_db.model.chain.account.MetaAccountLocal -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.BaseAddAccountRepository import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import jp.co.soramitsu.fearless_utils.runtime.AccountId diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxyCallFilterFactory.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxyCallFilterFactory.kt index 89a9f6dcd5..8d1638787d 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxyCallFilterFactory.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxyCallFilterFactory.kt @@ -1,7 +1,6 @@ package io.novafoundation.nova.feature_account_impl.data.signer.proxy import io.novafoundation.nova.common.utils.Modules -import io.novafoundation.nova.feature_account_api.domain.model.ProxyAccount import io.novafoundation.nova.feature_account_impl.data.signer.proxy.callFilter.CallFilter import io.novafoundation.nova.feature_account_impl.data.signer.proxy.callFilter.AnyOfCallFilter import io.novafoundation.nova.feature_account_impl.data.signer.proxy.callFilter.EverythingFilter diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt index 374a0328da..51ced342a1 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt @@ -28,10 +28,10 @@ import io.novafoundation.nova.runtime.ethereum.gas.GasPriceProviderFactory import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.EvmTransactionService import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService import io.novafoundation.nova.feature_account_api.data.proxy.MetaAccountsUpdatesRegistry +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository import io.novafoundation.nova.feature_account_api.data.signer.SignerProvider -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor @@ -74,7 +74,7 @@ import io.novafoundation.nova.feature_account_api.domain.account.common.Encrypti import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.account.identity.OnChainIdentity import io.novafoundation.nova.feature_account_impl.data.proxy.RealMetaAccountsUpdatesRegistry -import io.novafoundation.nova.feature_account_impl.data.proxy.sync.RealProxySyncService +import io.novafoundation.nova.feature_account_impl.data.proxy.RealProxySyncService import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.JsonAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.MnemonicAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.SeedAddAccountRepository diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AddAccountsModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AddAccountsModule.kt index d4e9636229..ad738bf6be 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AddAccountsModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AddAccountsModule.kt @@ -5,7 +5,7 @@ import dagger.Provides import io.novafoundation.nova.common.data.secrets.v2.SecretStoreV2 import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.core_db.dao.MetaAccountDao -import io.novafoundation.nova.feature_account_api.data.proxy.sync.ProxySyncService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.addAccount.ledger.LedgerAddAccountRepository import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.datasource.AccountDataSource diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt index f4df269efd..2d44cfcbbc 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt @@ -15,5 +15,5 @@ interface GetProxyRepository { suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int - suspend fun getProxDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger + suspend fun getProxyDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt index 3555ea71b4..a942b4f598 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt @@ -21,13 +21,12 @@ class EnoughAmountToPayProxyDepositValidation( override suspend fun validate(value: P): ValidationStatus { val availableBalance = availableBalance(value) - val currentDeposit = proxyRepository.getProxDeposit(chain(value).id, accountId(value)) + val currentDeposit = proxyRepository.getProxyDeposit(chain(value).id, accountId(value)) val deltaDeposit = (newDeposit(value) - currentDeposit).atLeastZero() return validOrError(deltaDeposit <= availableBalance) { - val maxUsable = availableBalance - deltaDeposit - error(value, maxUsable) + error(value, availableBalance) } } } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidator.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt similarity index 90% rename from feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidator.kt rename to feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt index c19fa5cb79..8614f2ad0d 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidator.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt @@ -8,7 +8,7 @@ import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyReposito import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId -class MaximumProxiesNotReachedValidator( +class MaximumProxiesNotReachedValidation( private val chain: (P) -> Chain, private val accountId: (P) -> AccountId, private val newProxiedQuantity: (P) -> Int, @@ -20,7 +20,7 @@ class MaximumProxiesNotReachedValidator( val newProxiesQuantity = newProxiedQuantity(value) val maximumProxiesQuantiy = proxyRepository.getProxiesQuantity(chain(value).id, accountId(value)) - return validOrError(newProxiesQuantity <= newProxiesQuantity) { + return validOrError(newProxiesQuantity <= maximumProxiesQuantiy) { error(value, maximumProxiesQuantiy) } } @@ -34,7 +34,7 @@ fun ValidationSystemBuilder.maximumProxiesNotReached( proxyRepository: GetProxyRepository ) { validate( - MaximumProxiesNotReachedValidator( + MaximumProxiesNotReachedValidation( chain = chain, accountId = accountId, newProxiedQuantity = newProxiedQuantity, diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt index 64c3490f58..e1bc121d99 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt @@ -65,7 +65,7 @@ class RealGetProxyRepository( return proxied.proxies.size } - override suspend fun getProxDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger { + override suspend fun getProxyDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger { val proxied = getAllProxiesFor(chainId, proxiedAccountId) return proxied.deposit diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt index e128d0b031..74eee825dd 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt @@ -26,6 +26,7 @@ import io.novafoundation.nova.core_db.dao.StakingTotalRewardDao import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase import io.novafoundation.nova.feature_account_api.domain.updaters.AccountUpdateScope import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase @@ -175,4 +176,6 @@ interface StakingFeatureDependencies { val getProxyRepository: GetProxyRepository val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher + + val metaAccountGroupingInteractor: MetaAccountGroupingInteractor } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt index 4381ebac0d..e462f2179f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt @@ -18,7 +18,7 @@ sealed interface AddStakingProxyValidationFailure { class NotEnoughBalanceToReserveDeposit( val chainAsset: Chain.Asset, - val maxUsable: Balance, + val availableBalance: Balance, val deposit: Balance ) : AddStakingProxyValidationFailure diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt index ff1a119236..9ffef01ae5 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt @@ -74,7 +74,7 @@ fun AddStakingProxyValidationSystemBuilder.enoughBalanceToPayDeposit( error = { payload, maxUsable -> AddStakingProxyValidationFailure.NotEnoughBalanceToReserveDeposit( chainAsset = payload.asset.token.configuration, - maxUsable = maxUsable, + availableBalance = maxUsable, deposit = payload.depositWithQuantity.deposit ) }, diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/NominationPoolsRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/NominationPoolsRouter.kt index 5651dd40b4..c506a97243 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/NominationPoolsRouter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/NominationPoolsRouter.kt @@ -21,6 +21,4 @@ interface NominationPoolsRouter : ReturnableRouter { fun returnToStakingMain() fun returnToMain() - - fun openSetStakingProxy() } 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 83920d4d32..0692ecbf12 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 @@ -38,7 +38,7 @@ interface ParachainStakingRouter { fun openSetupYieldBoost() fun openConfirmYieldBoost(payload: YieldBoostConfirmPayload) - fun openSetStakingProxy() + fun openAddStakingProxy() } fun ParachainStakingRouter.openStartStaking(flowMode: StartParachainStakingMode) = openStartStaking(StartParachainStakingPayload(flowMode)) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt index 26cd327050..3eab303bce 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt @@ -94,5 +94,5 @@ interface StakingRouter { fun finishRedeemFlow(redeemConsequences: RedeemConsequences) - fun openSetStakingProxy() + fun openAddStakingProxy() } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt index 8835523705..e41e7dfd03 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerFragment.kt @@ -21,7 +21,7 @@ import kotlinx.android.synthetic.main.fragment_set_controller_account.setControl import kotlinx.android.synthetic.main.fragment_set_controller_account.setControllerController import kotlinx.android.synthetic.main.fragment_set_controller_account.setControllerStash import kotlinx.android.synthetic.main.fragment_set_controller_account.setControllerSwitchToStashWarning -import kotlinx.android.synthetic.main.fragment_set_controller_account.addControllerToolbar +import kotlinx.android.synthetic.main.fragment_set_controller_account.setControllerToolbar class SetControllerFragment : BaseFragment() { @@ -43,7 +43,7 @@ class SetControllerFragment : BaseFragment() { setControllerController.setOnClickListener { viewModel.controllerClicked() } setControllerAdvertisement.setOnLearnMoreClickedListener { viewModel.onMoreClicked() } - addControllerToolbar.setHomeButtonListener { viewModel.backClicked() } + setControllerToolbar.setHomeButtonListener { viewModel.backClicked() } setControllerController.setActionTint(R.color.icon_secondary) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt index 5a82349bce..3b729ce226 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt @@ -18,7 +18,7 @@ fun mapAddStakingProxyValidationFailureToUi( resourceManager.getString( R.string.staking_not_enough_balance_to_pay_proxy_deposit_message, failure.deposit.formatPlanks(failure.chainAsset), - failure.maxUsable.formatPlanks(failure.chainAsset) + failure.availableBalance.formatPlanks(failure.chainAsset) ) is InvalidAddress -> resourceManager.getString(R.string.common_invalid_address_title) to diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt index 17bb32bd69..134c74e30f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt @@ -19,13 +19,13 @@ import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.di.StakingFeatureComponent import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.setupFeeLoading import io.novafoundation.nova.feature_wallet_api.presentation.view.showAmount -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyAddress -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxyButton -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.setStakingProxyContainer -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxyDeposit -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxyFee -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxyTitle -import kotlinx.android.synthetic.main.fragment_set_staking_proxy.addStakingProxySelectWallet +import kotlinx.android.synthetic.main.fragment_add_staking_proxy.setStakingProxyAddress +import kotlinx.android.synthetic.main.fragment_add_staking_proxy.addStakingProxyButton +import kotlinx.android.synthetic.main.fragment_add_staking_proxy.setStakingProxyContainer +import kotlinx.android.synthetic.main.fragment_add_staking_proxy.addStakingProxyDeposit +import kotlinx.android.synthetic.main.fragment_add_staking_proxy.addStakingProxyFee +import kotlinx.android.synthetic.main.fragment_add_staking_proxy.addStakingProxyTitle +import kotlinx.android.synthetic.main.fragment_add_staking_proxy.addStakingProxySelectWallet class AddStakingProxyFragment : BaseFragment() { @@ -34,7 +34,7 @@ class AddStakingProxyFragment : BaseFragment() { container: ViewGroup?, savedInstanceState: Bundle?, ): View? { - return inflater.inflate(R.layout.fragment_set_staking_proxy, container, false) + return inflater.inflate(R.layout.fragment_add_staking_proxy, container, false) } override fun initViews() { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt index 9824de2a48..a09703c064 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt @@ -10,6 +10,7 @@ import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester @@ -23,6 +24,7 @@ import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase +import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.awaitDecimalFee import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.create @@ -61,6 +63,7 @@ class AddStakingProxyViewModel( private val validationExecutor: ValidationExecutor, private val addStakingProxyValidationSystem: AddStakingProxyValidationSystem, private val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, + private val metaAccountGroupingInteractor: MetaAccountGroupingInteractor, ) : BaseViewModel(), DescriptionBottomSheetLauncher by descriptionBottomSheetLauncher, ExternalActions by externalActions, @@ -98,7 +101,12 @@ class AddStakingProxyViewModel( ) } - val isSelectAddressAvailable = flowOf { true } + val isSelectAddressAvailable = flowOf { + val selectedMetaAccount = accountRepository.getSelectedMetaAccount() + val chain = selectedAssetState.chain() + val filter = metaAccountsFilter(chain, selectedMetaAccount.requireAccountIdIn(chain)) + metaAccountGroupingInteractor.hasAvailableMetaAccountsForChain(selectedAssetState.chainId(), filter) + } .shareInBackground() private val proxyDeposit: Flow = flowOf { @@ -150,7 +158,7 @@ class AddStakingProxyViewModel( val chain = selectedAssetState.chain() val proxiedAccountId = metaAccount.requireAccountIdIn(chain) val selectedAddress = addressInputMixin.inputFlow.value - val filter = filterMetaAccountsWithSameAccountId(chain, proxiedAccountId) + val filter = getMetaAccountsFilterPayload(chain, proxiedAccountId) val request = SelectAddressRequester.Request(chain.id, selectedAddress, filter) selectAddressRequester.openRequest(request) } @@ -210,11 +218,17 @@ class AddStakingProxyViewModel( } } - private suspend fun filterMetaAccountsWithSameAccountId(chain: Chain, accountId: AccountId): SelectAddressRequester.Request.Filter { + private suspend fun getMetaAccountsFilterPayload(chain: Chain, accountId: AccountId): SelectAddressRequester.Request.Filter.ExcludeMetaIds { val filteredMetaAccounts = accountRepository.activeMetaAccounts() .filter { it.accountIdIn(chain)?.intoKey() == accountId.intoKey() } .map { it.id } return SelectAddressRequester.Request.Filter.ExcludeMetaIds(filteredMetaAccounts) } + + private suspend fun metaAccountsFilter(chain: Chain, accountId: AccountId): MetaAccountFilter { + val metaAccountsFilterPayload = getMetaAccountsFilterPayload(chain, accountId) + + return MetaAccountFilter(MetaAccountFilter.Mode.EXCLUDE, metaAccountsFilterPayload.metaIds) + } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt index c1e9496961..3705c9c04d 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt @@ -12,6 +12,7 @@ import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory @@ -42,7 +43,8 @@ class AddStakingProxyModule { addStakingProxyRepository: AddStakingProxyRepository, validationExecutor: ValidationExecutor, addStakingProxyValidationSystem: AddStakingProxyValidationSystem, - descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher + descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, + metaAccountGroupingInteractor: MetaAccountGroupingInteractor ): ViewModel { return AddStakingProxyViewModel( addressInputMixinFactory = addressInputMixinFactory, @@ -57,7 +59,8 @@ class AddStakingProxyModule { addStakingProxyRepository = addStakingProxyRepository, validationExecutor = validationExecutor, addStakingProxyValidationSystem = addStakingProxyValidationSystem, - descriptionBottomSheetLauncher = descriptionBottomSheetLauncher + descriptionBottomSheetLauncher = descriptionBottomSheetLauncher, + metaAccountGroupingInteractor = metaAccountGroupingInteractor ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt index 0c4ccc40fd..13747b8e1d 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/nominationPools/NominationPoolsStakeActionsComponent.kt @@ -46,7 +46,7 @@ class NominationPoolsStakeActionsComponentFactory( private open class NominationPoolsStakeActionsComponent( nominationPoolSharedComputation: NominationPoolSharedComputation, - private val stakingOption: StakingOption, + stakingOption: StakingOption, private val router: NominationPoolsRouter, private val hostContext: ComponentHostContext, private val resourceManager: ResourceManager, @@ -87,8 +87,8 @@ private open class NominationPoolsStakeActionsComponent( } } - private fun availablePoolMemberActions(): List = buildList { - add(ManageStakeAction.bondMore(resourceManager)) - add(ManageStakeAction.unbond(resourceManager)) - } + private fun availablePoolMemberActions(): List = listOf( + ManageStakeAction.bondMore(resourceManager), + ManageStakeAction.unbond(resourceManager) + ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt index 1e3442fe39..794149a6b8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt @@ -98,7 +98,7 @@ internal open class ParachainStakeActionsComponent( SYSTEM_MANAGE_VALIDATORS -> router.openCurrentCollators() SYSTEM_MANAGE_STAKING_BOND_MORE -> router.openStartStaking(StartParachainStakingMode.BOND_MORE) SYSTEM_MANAGE_STAKING_UNBOND -> openUnbondIfValid() - SYSTEM_ADD_PROXY -> router.openSetStakingProxy() + SYSTEM_ADD_PROXY -> router.openAddStakingProxy() SYSTEM_MANAGE_PROXIES -> TODO() } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt index 0cae81d7d0..2d402e263a 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt @@ -124,7 +124,7 @@ private class RelaychainStakeActionsComponent( SYSTEM_MANAGE_CONTROLLER -> router.openControllerAccount() SYSTEM_MANAGE_VALIDATORS -> router.openCurrentValidators() SYSTEM_MANAGE_REWARD_DESTINATION -> router.openChangeRewardDestination() - SYSTEM_ADD_PROXY -> router.openSetStakingProxy() + SYSTEM_ADD_PROXY -> router.openAddStakingProxy() SYSTEM_MANAGE_PROXIES -> TODO() } } diff --git a/feature-staking-impl/src/main/res/layout/fragment_set_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_add_staking_proxy.xml similarity index 98% rename from feature-staking-impl/src/main/res/layout/fragment_set_staking_proxy.xml rename to feature-staking-impl/src/main/res/layout/fragment_add_staking_proxy.xml index da978f6554..751c2fc41b 100644 --- a/feature-staking-impl/src/main/res/layout/fragment_set_staking_proxy.xml +++ b/feature-staking-impl/src/main/res/layout/fragment_add_staking_proxy.xml @@ -9,7 +9,7 @@ tools:background="@color/secondary_screen_background"> Date: Tue, 9 Jan 2024 06:55:37 +0100 Subject: [PATCH 08/55] Update strings.xml --- common/src/main/res/values-ru/strings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/common/src/main/res/values-ru/strings.xml b/common/src/main/res/values-ru/strings.xml index 5dc69c1011..7ecdd9d514 100644 --- a/common/src/main/res/values-ru/strings.xml +++ b/common/src/main/res/values-ru/strings.xml @@ -536,7 +536,6 @@ Сеть: %s\nМнемоника: %s Подождите, пока будет рассчитана комиссия Расчет комиссии в процессе - Выберите токен для получения Детали обмена Макс: Вы платите From fc6263e8e0cadc23bdae81e2c9fa939e714f7900 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 9 Jan 2024 06:59:40 +0100 Subject: [PATCH 09/55] Update AddProxyValidationFailureHandling.kt --- .../proxy/common/AddProxyValidationFailureHandling.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt index 3b729ce226..f7641f6bb2 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt @@ -4,7 +4,11 @@ import io.novafoundation.nova.common.base.TitleAndMessage import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure.* +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure.NotEnoughBalanceToReserveDeposit +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure.InvalidAddress +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure.MaximumProxiesReached +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure.NotEnoughToPayFee +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationFailure.NotEnoughToStayAboveED import io.novafoundation.nova.feature_wallet_api.domain.validation.handleNotEnoughFeeError import io.novafoundation.nova.feature_wallet_api.presentation.formatters.formatPlanks import io.novafoundation.nova.feature_wallet_api.presentation.validation.handleInsufficientBalanceCommission From 326dfd2d1b6ad1596a3282ef9f645848d82db45d Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 9 Jan 2024 07:52:50 +0100 Subject: [PATCH 10/55] Fixed bugs --- .../data/repository/GetProxyRepository.kt | 3 +++ .../validators/MaximumProxiesNotReachedValidation.kt | 2 +- .../data/repository/RealGetProxyRepository.kt | 12 ++++++++++++ .../delegation/proxy/set/AddStakingProxyViewModel.kt | 1 - 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt index 2d44cfcbbc..21757fc56a 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt @@ -3,6 +3,7 @@ package io.novafoundation.nova.feature_proxy_api.data.repository import io.novafoundation.nova.common.address.AccountIdKey import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import java.math.BigInteger import jp.co.soramitsu.fearless_utils.runtime.AccountId @@ -16,4 +17,6 @@ interface GetProxyRepository { suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int suspend fun getProxyDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger + + suspend fun maxProxiesQuantity(chain: Chain): Int } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt index 8614f2ad0d..55082f9c47 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt @@ -18,7 +18,7 @@ class MaximumProxiesNotReachedValidation( override suspend fun validate(value: P): ValidationStatus { val newProxiesQuantity = newProxiedQuantity(value) - val maximumProxiesQuantiy = proxyRepository.getProxiesQuantity(chain(value).id, accountId(value)) + val maximumProxiesQuantiy = proxyRepository.maxProxiesQuantity(chain(value)) return validOrError(newProxiesQuantity <= maximumProxiesQuantiy) { error(value, maximumProxiesQuantiy) diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt index e1bc121d99..fc7760d7be 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt @@ -8,12 +8,16 @@ import io.novafoundation.nova.common.data.network.runtime.binding.castToList import io.novafoundation.nova.common.data.network.runtime.binding.castToStruct import io.novafoundation.nova.common.data.network.runtime.binding.getTyped import io.novafoundation.nova.common.utils.Modules +import io.novafoundation.nova.common.utils.numberConstant +import io.novafoundation.nova.common.utils.proxy import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_proxy_api.domain.model.fromString import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId +import io.novafoundation.nova.runtime.multiNetwork.getRuntime import io.novafoundation.nova.runtime.storage.source.StorageDataSource import java.math.BigInteger import jp.co.soramitsu.fearless_utils.runtime.AccountId @@ -71,6 +75,12 @@ class RealGetProxyRepository( return proxied.deposit } + override suspend fun maxProxiesQuantity(chain: Chain): Int { + val runtime = chainRegistry.getRuntime(chain.id) + val constantQuery = runtime.metadata.proxy() + return constantQuery.numberConstant("MaxProxies", runtime).toInt() + } + private suspend fun getAllProxiesFor(chainId: ChainId, accountId: AccountId): OnChainProxiedModel { return remoteSource.query(chainId) { runtime.metadata.module(Modules.PROXY) @@ -101,6 +111,8 @@ class RealGetProxyRepository( } private fun bindProxyAccounts(dynamicInstance: Any?): OnChainProxiedModel { + if (dynamicInstance == null) return OnChainProxiedModel(emptyList(), BigInteger.ZERO) + val root = dynamicInstance.castToList() val proxies = root[0].castToList() diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt index a09703c064..55c51c6ec1 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt @@ -187,7 +187,6 @@ class AddStakingProxyViewModel( } private fun openConfirmScreen() { - TODO() } private fun subscribeOnSelectAddress() { From bbbe035841d2cc381e64143a8616d5b624c7a828 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Wed, 10 Jan 2024 12:34:50 +0100 Subject: [PATCH 11/55] AddProxyConfirmation screen --- .../relaychain/RelayStakingNavigator.kt | 9 + .../res/navigation/staking_main_graph.xml | 17 +- .../nova/common/view/TableCellView.kt | 3 + common/src/main/res/values/attrs.xml | 1 + common/src/main/res/values/strings.xml | 9 + .../di/StakingFeatureComponent.kt | 3 + .../proxy/AddStakingProxyValidationPayload.kt | 2 +- .../delegation/proxy/Declarations.kt | 2 +- .../presentation/StakingRouter.kt | 3 + .../common/ProxyDepositDescriptionSetupExt.kt | 11 ++ .../confirm/ConfirmAddStakingProxyFragment.kt | 87 ++++++++++ .../confirm/ConfirmAddStakingProxyPayload.kt | 14 ++ .../ConfirmAddStakingProxyViewModel.kt | 163 ++++++++++++++++++ .../di/ConfirmAddStakingProxyComponent.kt | 27 +++ .../di/ConfirmAddStakingProxyModule.kt | 70 ++++++++ .../proxy/set/AddStakingProxyViewModel.kt | 25 ++- .../proxy/set/di/AddStakingProxyModule.kt | 7 +- .../fragment_confirm_add_staking_proxy.xml | 114 ++++++++++++ 18 files changed, 555 insertions(+), 12 deletions(-) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/ProxyDepositDescriptionSetupExt.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyFragment.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyPayload.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyComponent.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt create mode 100644 feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt index 4e6531b216..30d777f041 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt @@ -21,6 +21,8 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.sel import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.select.SelectBondMorePayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerFragment import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.model.StakingStoryModel import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondFragment import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondPayload @@ -226,4 +228,11 @@ class RelayStakingNavigator( override fun openAddStakingProxy() { performNavigation(R.id.action_open_addStakingProxyFragment) } + + override fun openConfirmAddStakingProxy(payload: ConfirmAddStakingProxyPayload) { + performNavigation( + R.id.action_addStakingProxyFragment_to_confirmAddStakingProxyFragment, + ConfirmAddStakingProxyFragment.getBundle(payload) + ) + } } diff --git a/app/src/main/res/navigation/staking_main_graph.xml b/app/src/main/res/navigation/staking_main_graph.xml index 19f9ea5ede..857e1d26fc 100644 --- a/app/src/main/res/navigation/staking_main_graph.xml +++ b/app/src/main/res/navigation/staking_main_graph.xml @@ -40,7 +40,22 @@ + android:label="StakingFragment"> + + + + + + + diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index d6e2f1f682..375d015a9b 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,6 +1,15 @@ + Staking operations + + Delegating wallet + Delegating account + Grant access type + Delegate to + + Add delegation + Proxy deposit The deposit stays reserved on your account until the proxy is removed. 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 e3ee126a43..87cbe0f915 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 @@ -61,6 +61,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.con import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.select.di.SelectBondMoreComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.di.ConfirmSetControllerComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.di.SetControllerComponent +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.di.ConfirmAddStakingProxyComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.di.AddStakingProxyComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.di.StakingComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.di.ConfirmRebondComponent @@ -174,6 +175,8 @@ interface StakingFeatureComponent : StakingFeatureApi { fun confirmSetControllerFactory(): ConfirmSetControllerComponent.Factory + fun confirmAddStakingProxyFactory(): ConfirmAddStakingProxyComponent.Factory + fun rebondCustomFactory(): CustomRebondComponent.Factory fun currentValidatorsFactory(): CurrentValidatorsComponent.Factory diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt index 16d178f943..aa8ba8ff93 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt @@ -10,7 +10,7 @@ class AddStakingProxyValidationPayload( val chain: Chain, val asset: Asset, val proxiedAccountId: AccountId, - val address: String, + val proxyAddress: String, val fee: DecimalFee, val depositWithQuantity: ProxyDepositWithQuantity ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt index 9ffef01ae5..5f697352e3 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt @@ -17,7 +17,7 @@ typealias AddStakingProxyValidationSystem = ValidationSystem fun AddStakingProxyValidationSystemBuilder.validAddress() = validAddress( - address = { it.address }, + address = { it.proxyAddress }, chain = { it.chain }, error = { AddStakingProxyValidationFailure.InvalidAddress(it.chain) } ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt index 3eab303bce..f89167ed9e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt @@ -6,6 +6,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.payouts.model.Pe import io.novafoundation.nova.feature_staking_impl.presentation.pools.common.SelectingPoolPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.confirm.ConfirmBondMorePayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.model.StakingStoryModel import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.rewardDestination.confirm.parcel.ConfirmRewardDestinationPayload @@ -95,4 +96,6 @@ interface StakingRouter { fun finishRedeemFlow(redeemConsequences: RedeemConsequences) fun openAddStakingProxy() + + fun openConfirmAddStakingProxy(payload: ConfirmAddStakingProxyPayload) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/ProxyDepositDescriptionSetupExt.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/ProxyDepositDescriptionSetupExt.kt new file mode 100644 index 0000000000..0d17934050 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/ProxyDepositDescriptionSetupExt.kt @@ -0,0 +1,11 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common + +import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher +import io.novafoundation.nova.feature_staking_impl.R + +fun DescriptionBottomSheetLauncher.launchProxyDepositDescription() { + launchDescriptionBottomSheet( + titleRes = R.string.add_proxy_deposit_description_title, + descriptionRes = R.string.add_proxy_deposit_description_message + ) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyFragment.kt new file mode 100644 index 0000000000..1778e23922 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyFragment.kt @@ -0,0 +1,87 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import io.novafoundation.nova.common.base.BaseFragment +import io.novafoundation.nova.common.di.FeatureUtils +import io.novafoundation.nova.common.mixin.impl.observeValidations +import io.novafoundation.nova.common.utils.applyStatusBarInsets +import io.novafoundation.nova.common.view.bottomSheet.description.observeDescription +import io.novafoundation.nova.common.view.setProgress +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.showWallet +import io.novafoundation.nova.feature_account_api.presenatation.actions.setupExternalActions +import io.novafoundation.nova.feature_account_api.view.showAddress +import io.novafoundation.nova.feature_account_api.view.showChain +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_wallet_api.presentation.view.showAmount +import kotlinx.android.synthetic.main.fragment_confirm_add_staking_proxy.confirmAddStakingProxyButton +import kotlinx.android.synthetic.main.fragment_confirm_add_staking_proxy.confirmAddStakingProxyDelegationAccount +import kotlinx.android.synthetic.main.fragment_confirm_add_staking_proxy.confirmAddStakingProxyDeposit +import kotlinx.android.synthetic.main.fragment_confirm_add_staking_proxy.confirmAddStakingProxyNetwork +import kotlinx.android.synthetic.main.fragment_confirm_add_staking_proxy.confirmAddStakingProxyNetworkFee +import kotlinx.android.synthetic.main.fragment_confirm_add_staking_proxy.confirmAddStakingProxyProxiedAccount +import kotlinx.android.synthetic.main.fragment_confirm_add_staking_proxy.confirmAddStakingProxyToolbar +import kotlinx.android.synthetic.main.fragment_confirm_add_staking_proxy.confirmAddStakingProxyWallet + +class ConfirmAddStakingProxyFragment : BaseFragment() { + companion object { + + private const val PAYLOAD_KEY = "PAYLOAD_KEY" + + fun getBundle(payload: ConfirmAddStakingProxyPayload) = Bundle().apply { + putParcelable(PAYLOAD_KEY, payload) + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_confirm_add_staking_proxy, container, false) + } + + override fun initViews() { + confirmAddStakingProxyToolbar.applyStatusBarInsets() + + confirmAddStakingProxyToolbar.setHomeButtonListener { viewModel.back() } + + confirmAddStakingProxyButton.setOnClickListener { viewModel.confirmClicked() } + confirmAddStakingProxyButton.prepareForProgress(viewLifecycleOwner) + + confirmAddStakingProxyProxiedAccount.setOnValueClickListener { viewModel.proxiedAccountClicked() } + confirmAddStakingProxyDeposit.setOnClickListener { viewModel.depositClicked() } + confirmAddStakingProxyDelegationAccount.setOnClickListener { viewModel.proxyAccountClicked() } + } + + override fun inject() { + val payload = argument(PAYLOAD_KEY) + + FeatureUtils.getFeature( + requireContext(), + StakingFeatureApi::class.java + ) + .confirmAddStakingProxyFactory() + .create(this, payload) + .inject(this) + } + + override fun subscribe(viewModel: ConfirmAddStakingProxyViewModel) { + observeValidations(viewModel) + setupExternalActions(viewModel) + observeDescription(viewModel) + + viewModel.chainModel.observe { confirmAddStakingProxyNetwork.showChain(it) } + viewModel.walletUiFlow.observe { confirmAddStakingProxyWallet.showWallet(it) } + viewModel.proxiedAccountModel.observe { confirmAddStakingProxyProxiedAccount.showAddress(it) } + viewModel.proxyDeposit.observe { confirmAddStakingProxyDeposit.showAmount(it) } + viewModel.feeModelFlow.observe { confirmAddStakingProxyNetworkFee.showAmount(it) } + viewModel.proxyAccountModel.observe { confirmAddStakingProxyDelegationAccount.showAddress(it) } + + viewModel.validationProgressFlow.observe(confirmAddStakingProxyButton::setProgress) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyPayload.kt new file mode 100644 index 0000000000..7b767dc731 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyPayload.kt @@ -0,0 +1,14 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm + +import android.os.Parcelable +import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeParcelModel +import kotlinx.android.parcel.Parcelize + +@Parcelize +class ConfirmAddStakingProxyPayload( + val fee: FeeParcelModel, + val proxyAddress: String, + val newProxyDeposit: Balance, + val newProxyQuantity: Int +) : Parcelable diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt new file mode 100644 index 0000000000..3a663a3486 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt @@ -0,0 +1,163 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm + +import io.novafoundation.nova.common.address.AddressIconGenerator +import io.novafoundation.nova.common.base.BaseViewModel +import io.novafoundation.nova.common.mixin.api.Validatable +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.utils.flowOf +import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.common.validation.progressConsumer +import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher +import io.novafoundation.nova.feature_account_api.data.mappers.mapChainToUi +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_account_api.domain.model.requireAddressIn +import io.novafoundation.nova.feature_account_api.presenatation.account.icon.createAccountAddressModel +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity +import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationPayload +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.launchProxyDepositDescription +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi +import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.mapFeeFromParcel +import io.novafoundation.nova.feature_wallet_api.presentation.model.mapAmountToAmountModel +import io.novafoundation.nova.runtime.ext.accountIdOf +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState +import io.novafoundation.nova.runtime.state.chain +import io.novafoundation.nova.runtime.state.selectedAssetFlow +import io.novafoundation.nova.runtime.state.selectedChainFlow +import jp.co.soramitsu.fearless_utils.runtime.AccountId +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch + +class ConfirmAddStakingProxyViewModel( + private val router: StakingRouter, + private val addressIconGenerator: AddressIconGenerator, + private val payload: ConfirmAddStakingProxyPayload, + private val accountRepository: AccountRepository, + private val resourceManager: ResourceManager, + private val externalActions: ExternalActions.Presentation, + private val validationExecutor: ValidationExecutor, + private val selectedAssetState: AnySelectedAssetOptionSharedState, + private val assetUseCase: ArbitraryAssetUseCase, + private val addStakingProxyValidationSystem: AddStakingProxyValidationSystem, + private val addStakingProxyRepository: AddStakingProxyRepository, + private val walletUiUseCase: WalletUiUseCase, + private val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, +) : BaseViewModel(), + DescriptionBottomSheetLauncher by descriptionBottomSheetLauncher, + Validatable by validationExecutor, + ExternalActions by externalActions { + + private val selectedMetaAccountFlow = accountRepository.selectedMetaAccountFlow() + .shareInBackground() + + private val chainFlow = selectedAssetState.selectedChainFlow() + .shareInBackground() + + @OptIn(ExperimentalCoroutinesApi::class) + private val assetFlow = selectedAssetState.selectedAssetFlow() + .flatMapLatest { assetUseCase.assetFlow(it) } + .shareInBackground() + + private val decimalFeeFlow = flowOf { mapFeeFromParcel(payload.fee) } + .shareInBackground() + + val chainModel = chainFlow.map { chain -> + mapChainToUi(chain) + } + + val walletUiFlow = selectedMetaAccountFlow.map { walletUiUseCase.walletUiFor(it) } + + val proxiedAccountModel = combine(selectedMetaAccountFlow, chainFlow) { metaAccount, chain -> + val address = metaAccount.requireAddressIn(chain) + + generateAccountAddressModel(chain, address) + } + + val proxyDeposit = assetFlow.map { asset -> + mapAmountToAmountModel(payload.newProxyDeposit, asset) + } + + val feeModelFlow = combine(assetFlow, decimalFeeFlow) { asset, decimalFee -> + mapAmountToAmountModel(decimalFee.networkFee.amount, asset) + } + + val proxyAccountModel = chainFlow.map { chain -> + generateAccountAddressModel(chain, payload.proxyAddress) + } + + val validationProgressFlow = MutableStateFlow(false) + + fun back() { + router.back() + } + + fun confirmClicked() = launch { + val metaAccount = accountRepository.getSelectedMetaAccount() + val chain = selectedAssetState.chain() + val validationPayload = AddStakingProxyValidationPayload( + chain = chain, + asset = assetFlow.first(), + proxyAddress = payload.proxyAddress, + proxiedAccountId = metaAccount.requireAccountIdIn(chain), + fee = decimalFeeFlow.first(), + depositWithQuantity = ProxyDepositWithQuantity( + deposit = payload.newProxyDeposit, + quantity = payload.newProxyQuantity + ) + ) + + validationExecutor.requireValid( + validationSystem = addStakingProxyValidationSystem, + payload = validationPayload, + validationFailureTransformer = { mapAddStakingProxyValidationFailureToUi(resourceManager, it) }, + progressConsumer = validationProgressFlow.progressConsumer() + ) { + sendTransaction(it.chain, it.proxiedAccountId, it.chain.accountIdOf(it.proxyAddress)) + } + } + + private fun sendTransaction(chain: Chain, proxiedAccount: AccountId, proxyAccount: AccountId) = launch { + val result = addStakingProxyRepository.addProxy(chain, proxiedAccount, proxyAccount) + + validationProgressFlow.value = false + + if (result.isSuccess) { + router.returnToStakingMain() + } + } + + private suspend fun generateAccountAddressModel(chain: Chain, address: String) = addressIconGenerator.createAccountAddressModel( + chain = chain, + address = address, + ) + + fun proxiedAccountClicked() { + launch { + showExternalActions(proxiedAccountModel.first().address) + } + } + + fun depositClicked() { + descriptionBottomSheetLauncher.launchProxyDepositDescription() + } + + fun proxyAccountClicked() { + showExternalActions(payload.proxyAddress) + } + + private fun showExternalActions(address: String) = launch { + externalActions.showExternalActions(ExternalActions.Type.Address(address), selectedAssetState.chain()) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyComponent.kt new file mode 100644 index 0000000000..aa9852515d --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyComponent.kt @@ -0,0 +1,27 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.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.staking.delegation.proxy.confirm.ConfirmAddStakingProxyFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload + +@Subcomponent( + modules = [ + ConfirmAddStakingProxyModule::class + ] +) +@ScreenScope +interface ConfirmAddStakingProxyComponent { + + @Subcomponent.Factory + interface Factory { + fun create( + @BindsInstance fragment: Fragment, + @BindsInstance payload: ConfirmAddStakingProxyPayload, + ): ConfirmAddStakingProxyComponent + } + + fun inject(fragment: ConfirmAddStakingProxyFragment) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt new file mode 100644 index 0000000000..51754b8b39 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt @@ -0,0 +1,70 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.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.viewmodel.ViewModelKey +import io.novafoundation.nova.common.di.viewmodel.ViewModelModule +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyViewModel +import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase +import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState + +@Module(includes = [ViewModelModule::class]) +class ConfirmAddStakingProxyModule { + @Provides + @IntoMap + @ViewModelKey(ConfirmAddStakingProxyViewModel::class) + fun provideViewModule( + router: StakingRouter, + addressIconGenerator: AddressIconGenerator, + payload: ConfirmAddStakingProxyPayload, + accountRepository: AccountRepository, + resourceManager: ResourceManager, + externalActions: ExternalActions.Presentation, + validationExecutor: ValidationExecutor, + selectedAssetState: AnySelectedAssetOptionSharedState, + assetUseCase: ArbitraryAssetUseCase, + addStakingProxyValidationSystem: AddStakingProxyValidationSystem, + addStakingProxyRepository: AddStakingProxyRepository, + walletUiUseCase: WalletUiUseCase, + descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, + ): ViewModel { + return ConfirmAddStakingProxyViewModel( + router = router, + addressIconGenerator = addressIconGenerator, + payload = payload, + accountRepository = accountRepository, + resourceManager = resourceManager, + externalActions = externalActions, + validationExecutor = validationExecutor, + selectedAssetState = selectedAssetState, + assetUseCase = assetUseCase, + addStakingProxyValidationSystem = addStakingProxyValidationSystem, + addStakingProxyRepository = addStakingProxyRepository, + walletUiUseCase = walletUiUseCase, + descriptionBottomSheetLauncher = descriptionBottomSheetLauncher + ) + } + + @Provides + fun provideViewModelCreator( + fragment: Fragment, + viewModelFactory: ViewModelProvider.Factory + ): ConfirmAddStakingProxyViewModel { + return ViewModelProvider(fragment, viewModelFactory).get(ConfirmAddStakingProxyViewModel::class.java) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt index 55c51c6ec1..e563acd91c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt @@ -22,12 +22,16 @@ import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationPayload import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.launchProxyDepositDescription import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.awaitDecimalFee import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.create +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.mapFeeToParcel import io.novafoundation.nova.feature_wallet_api.presentation.model.AmountModel import io.novafoundation.nova.feature_wallet_api.presentation.model.mapAmountToAmountModel import io.novafoundation.nova.runtime.ext.commissionAsset @@ -64,6 +68,7 @@ class AddStakingProxyViewModel( private val addStakingProxyValidationSystem: AddStakingProxyValidationSystem, private val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, private val metaAccountGroupingInteractor: MetaAccountGroupingInteractor, + private val stakingRouter: StakingRouter ) : BaseViewModel(), DescriptionBottomSheetLauncher by descriptionBottomSheetLauncher, ExternalActions by externalActions, @@ -146,10 +151,7 @@ class AddStakingProxyViewModel( } fun showProxyDepositDescription() { - descriptionBottomSheetLauncher.launchDescriptionBottomSheet( - titleRes = R.string.add_proxy_deposit_description_title, - descriptionRes = R.string.add_proxy_deposit_description_message - ) + descriptionBottomSheetLauncher.launchProxyDepositDescription() } fun selectAuthorityWallet() { @@ -170,7 +172,7 @@ class AddStakingProxyViewModel( val validationPayload = AddStakingProxyValidationPayload( chain = chain, asset = selectedAssetFlow.first(), - address = addressInputMixin.inputFlow.value, + proxyAddress = addressInputMixin.inputFlow.value, proxiedAccountId = metaAccount.requireAccountIdIn(chain), fee = feeMixin.awaitDecimalFee(), depositWithQuantity = proxyDeposit.first() @@ -182,11 +184,20 @@ class AddStakingProxyViewModel( validationFailureTransformer = { mapAddStakingProxyValidationFailureToUi(resourceManager, it) }, progressConsumer = _validationProgressFlow.progressConsumer() ) { - openConfirmScreen() + openConfirmScreen(it) } } - private fun openConfirmScreen() { + private fun openConfirmScreen(validationPayload: AddStakingProxyValidationPayload) { + val screenPayload = validationPayload.run { + ConfirmAddStakingProxyPayload( + fee = mapFeeToParcel(validationPayload.fee), + proxyAddress = proxyAddress, + newProxyDeposit = depositWithQuantity.deposit, + newProxyQuantity = depositWithQuantity.quantity + ) + } + stakingRouter.openConfirmAddStakingProxy(screenPayload) } private fun subscribeOnSelectAddress() { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt index 3705c9c04d..7f3f86b2f3 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt @@ -19,6 +19,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInp import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.AddStakingProxyViewModel import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin @@ -44,7 +45,8 @@ class AddStakingProxyModule { validationExecutor: ValidationExecutor, addStakingProxyValidationSystem: AddStakingProxyValidationSystem, descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, - metaAccountGroupingInteractor: MetaAccountGroupingInteractor + metaAccountGroupingInteractor: MetaAccountGroupingInteractor, + stakingRouter: StakingRouter ): ViewModel { return AddStakingProxyViewModel( addressInputMixinFactory = addressInputMixinFactory, @@ -60,7 +62,8 @@ class AddStakingProxyModule { validationExecutor = validationExecutor, addStakingProxyValidationSystem = addStakingProxyValidationSystem, descriptionBottomSheetLauncher = descriptionBottomSheetLauncher, - metaAccountGroupingInteractor = metaAccountGroupingInteractor + metaAccountGroupingInteractor = metaAccountGroupingInteractor, + stakingRouter = stakingRouter ) } diff --git a/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml new file mode 100644 index 0000000000..fc4cadd307 --- /dev/null +++ b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 599bc22473f50e535f77fe1cd71fc19a0aecc190 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 12 Jan 2024 03:39:13 +0100 Subject: [PATCH 12/55] Staking proxy list --- .../relaychain/RelayStakingNavigator.kt | 8 +- .../res/navigation/staking_main_graph.xml | 21 ++++- common/src/main/res/values-ru/strings.xml | 2 +- common/src/main/res/values/strings.xml | 9 +- .../CustomizableExternalActionsSheet.kt | 31 +++++++ .../detail/main/DelegateDetailsViewModel.kt | 2 +- .../create/common/NewDelegationTitle.kt | 2 +- .../referenda/list/ReferendaListViewModel.kt | 2 +- .../res/layout/fragment_delegate_details.xml | 2 +- .../res/layout/fragment_delegate_list.xml | 2 +- .../fragment_new_delegation_choose_amount.xml | 2 +- .../fragment_new_delegation_confirm.xml | 2 +- .../res/layout/fragment_your_delegations.xml | 2 +- .../main/res/layout/item_referenda_header.xml | 2 +- .../data/repository/GetProxyRepository.kt | 5 ++ .../data/repository/RealGetProxyRepository.kt | 28 +++++- .../di/StakingFeatureComponent.kt | 7 +- .../di/StakingFeatureModule.kt | 11 +++ .../proxy/list/StakingProxyListInteractor.kt | 40 +++++++++ .../proxy/list/model/StakingProxyAccount.kt | 9 ++ .../presentation/StakingRouter.kt | 4 +- .../confirm/ConfirmAddStakingProxyFragment.kt | 2 +- .../confirm/ConfirmAddStakingProxyPayload.kt | 2 +- .../ConfirmAddStakingProxyViewModel.kt | 2 +- .../di/ConfirmAddStakingProxyComponent.kt | 6 +- .../di/ConfirmAddStakingProxyModule.kt | 6 +- .../{ => add}/set/AddStakingProxyFragment.kt | 2 +- .../{ => add}/set/AddStakingProxyViewModel.kt | 4 +- .../set/di/AddStakingProxyComponent.kt | 4 +- .../{ => add}/set/di/AddStakingProxyModule.kt | 4 +- .../proxy/list/StakingProxyListAdapter.kt | 89 +++++++++++++++++++ .../proxy/list/StakingProxyListFragment.kt | 89 +++++++++++++++++++ .../proxy/list/StakingProxyListViewModel.kt | 87 ++++++++++++++++++ .../list/di/StakingProxyListComponent.kt | 23 +++++ .../proxy/list/di/StakingProxyListModule.kt | 53 +++++++++++ .../list/model/StakingProxyListModels.kt | 12 +++ .../stakeActions/ManageStakeAction.kt | 5 +- .../RelaychainStakeActionsComponent.kt | 63 +++++++++---- .../main/di/components/RelaychainModule.kt | 8 +- .../layout/fragment_staking_proxy_list.xml | 37 ++++++++ .../src/main/res/layout/item_proxy.xml | 64 +++++++++++++ .../src/main/res/layout/item_proxy_group.xml | 13 +++ 42 files changed, 709 insertions(+), 59 deletions(-) create mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/actions/CustomizableExternalActionsSheet.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/{ => add}/confirm/ConfirmAddStakingProxyFragment.kt (99%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/{ => add}/confirm/ConfirmAddStakingProxyPayload.kt (92%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/{ => add}/confirm/ConfirmAddStakingProxyViewModel.kt (99%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/{ => add}/confirm/di/ConfirmAddStakingProxyComponent.kt (81%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/{ => add}/confirm/di/ConfirmAddStakingProxyModule.kt (95%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/{ => add}/set/AddStakingProxyFragment.kt (99%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/{ => add}/set/AddStakingProxyViewModel.kt (99%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/{ => add}/set/di/AddStakingProxyComponent.kt (86%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/{ => add}/set/di/AddStakingProxyModule.kt (97%) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListAdapter.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListFragment.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListComponent.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/model/StakingProxyListModels.kt create mode 100644 feature-staking-impl/src/main/res/layout/fragment_staking_proxy_list.xml create mode 100644 feature-staking-impl/src/main/res/layout/item_proxy.xml create mode 100644 feature-staking-impl/src/main/res/layout/item_proxy_group.xml diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt index 30d777f041..19b1298b7e 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt @@ -21,8 +21,8 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.sel import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.select.SelectBondMorePayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerFragment import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyFragment -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.model.StakingStoryModel import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondFragment import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondPayload @@ -235,4 +235,8 @@ class RelayStakingNavigator( ConfirmAddStakingProxyFragment.getBundle(payload) ) } + + override fun openStakingProxyList() { + performNavigation(R.id.action_open_stakingProxyList) + } } diff --git a/app/src/main/res/navigation/staking_main_graph.xml b/app/src/main/res/navigation/staking_main_graph.xml index 857e1d26fc..4003d87f1a 100644 --- a/app/src/main/res/navigation/staking_main_graph.xml +++ b/app/src/main/res/navigation/staking_main_graph.xml @@ -37,10 +37,23 @@ app:popEnterAnim="@anim/fragment_close_enter" app:popExitAnim="@anim/fragment_close_exit" /> + + + + + android:name="io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.set.AddStakingProxyFragment" + android:label="AddStakingProxyFragment"> + android:name="io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyFragment" + android:label="ConfirmAddStakingProxyFragment" /> Поиск по адресу или имени Недопустимый формат адреса. Убедитесь, что адрес принадлежит правильной сети результаты поиска: %d - Добавить делегацию + Добавить делегацию Голоса за все время Делегат Все аккаунты diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 375d015a9b..c9b4c34763 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,6 +1,13 @@ + + + Add delegation + + Delegated authorities (proxy) + Revoke access + Staking operations Delegating wallet @@ -587,8 +594,6 @@ Organizations Individuals - Add delegation - Organization Individual diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/actions/CustomizableExternalActionsSheet.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/actions/CustomizableExternalActionsSheet.kt new file mode 100644 index 0000000000..1a0ae7f0af --- /dev/null +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/actions/CustomizableExternalActionsSheet.kt @@ -0,0 +1,31 @@ +package io.novafoundation.nova.feature_account_api.presenatation.actions + +import android.content.Context +import android.os.Bundle +import androidx.annotation.DrawableRes +import io.novafoundation.nova.common.view.bottomSheet.list.fixed.textItem + +class ExternalActionModel( + @DrawableRes val iconRes: Int, + val title: String, + val onClick: () -> Unit +) + +class CustomizableExternalActionsSheet( + context: Context, + payload: ExternalActions.Payload, + onCopy: CopyCallback, + onViewExternal: ExternalViewCallback, + val additionalOptions: List +) : ExternalActionsSheet(context, payload, onCopy, onViewExternal) { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + additionalOptions.forEach { externalActionModel -> + textItem(externalActionModel.iconRes, externalActionModel.title) { + externalActionModel.onClick() + } + } + } +} diff --git a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/delegation/delegate/detail/main/DelegateDetailsViewModel.kt b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/delegation/delegate/detail/main/DelegateDetailsViewModel.kt index 7eddf9c460..7df9e9b46d 100644 --- a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/delegation/delegate/detail/main/DelegateDetailsViewModel.kt +++ b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/delegation/delegate/detail/main/DelegateDetailsViewModel.kt @@ -104,7 +104,7 @@ class DelegateDetailsViewModel( when { data == null -> DescriptiveButtonState.Gone data.userDelegations.isNotEmpty() -> DescriptiveButtonState.Gone - else -> DescriptiveButtonState.Enabled(resourceManager.getString(R.string.delegation_add_delegation)) + else -> DescriptiveButtonState.Enabled(resourceManager.getString(R.string.common_add_delegation)) } }.shareWhileSubscribed() diff --git a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/delegation/delegation/create/common/NewDelegationTitle.kt b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/delegation/delegation/create/common/NewDelegationTitle.kt index 82ca55df2f..1e0df7098d 100644 --- a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/delegation/delegation/create/common/NewDelegationTitle.kt +++ b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/delegation/delegation/create/common/NewDelegationTitle.kt @@ -4,7 +4,7 @@ import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.feature_governance_impl.R internal fun ResourceManager.newDelegationTitle(isEditMode: Boolean): String { - val resId = if (isEditMode) R.string.delegation_edit_delegation else R.string.delegation_add_delegation + val resId = if (isEditMode) R.string.delegation_edit_delegation else R.string.common_add_delegation return getString(resId) } diff --git a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/referenda/list/ReferendaListViewModel.kt b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/referenda/list/ReferendaListViewModel.kt index 37a4393221..1255499bf7 100644 --- a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/referenda/list/ReferendaListViewModel.kt +++ b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/presentation/referenda/list/ReferendaListViewModel.kt @@ -143,7 +143,7 @@ class ReferendaListViewModel( DelegatedState.NotDelegated -> GovernanceLocksModel( amount = null, - title = resourceManager.getString(R.string.delegation_add_delegation), + title = resourceManager.getString(R.string.common_add_delegation), hasUnlockableLocks = false ) diff --git a/feature-governance-impl/src/main/res/layout/fragment_delegate_details.xml b/feature-governance-impl/src/main/res/layout/fragment_delegate_details.xml index 941a7c611f..f3dd22d019 100644 --- a/feature-governance-impl/src/main/res/layout/fragment_delegate_details.xml +++ b/feature-governance-impl/src/main/res/layout/fragment_delegate_details.xml @@ -174,7 +174,7 @@ android:layout_gravity="bottom" android:layout_marginHorizontal="16dp" android:layout_marginBottom="16dp" - android:text="@string/delegation_add_delegation" /> + android:text="@string/common_add_delegation" /> + app:titleText="@string/common_add_delegation" /> + app:titleText="@string/common_add_delegation" /> + app:titleText="@string/common_add_delegation" /> diff --git a/feature-governance-impl/src/main/res/layout/item_referenda_header.xml b/feature-governance-impl/src/main/res/layout/item_referenda_header.xml index 86c5425d44..a71e3b3a7f 100644 --- a/feature-governance-impl/src/main/res/layout/item_referenda_header.xml +++ b/feature-governance-impl/src/main/res/layout/item_referenda_header.xml @@ -44,7 +44,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:governanceLocksView_icon="@drawable/ic_delegate_outline" - app:governanceLocksView_label="@string/delegation_add_delegation" /> + app:governanceLocksView_label="@string/common_add_delegation" /> diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt index 21757fc56a..91e9dc62d9 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt @@ -7,6 +7,7 @@ import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import java.math.BigInteger import jp.co.soramitsu.fearless_utils.runtime.AccountId +import kotlinx.coroutines.flow.Flow interface GetProxyRepository { @@ -19,4 +20,8 @@ interface GetProxyRepository { suspend fun getProxyDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger suspend fun maxProxiesQuantity(chain: Chain): Int + + fun proxiesByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow> + + fun proxiesQuantityByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow } diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt index fc7760d7be..150fe5bb8d 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt @@ -23,6 +23,9 @@ import java.math.BigInteger import jp.co.soramitsu.fearless_utils.runtime.AccountId import jp.co.soramitsu.fearless_utils.runtime.metadata.module import jp.co.soramitsu.fearless_utils.runtime.metadata.storage +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map private class OnChainProxiedModel( val proxies: List, @@ -37,11 +40,11 @@ private class OnChainProxyModel( class RealGetProxyRepository( private val remoteSource: StorageDataSource, - private val chainRegistry: ChainRegistry + private val chainRegistry: ChainRegistry, ) : GetProxyRepository { override suspend fun getAllProxiesForAccounts(chainId: ChainId, accountIds: Set): List { - val delegatorToProxies = receiveAllProxies(chainId) + val delegatorToProxies = receiveAllProxiesInChain(chainId) return delegatorToProxies .mapNotNull { (delegator, proxied) -> @@ -81,6 +84,25 @@ class RealGetProxyRepository( return constantQuery.numberConstant("MaxProxies", runtime).toInt() } + override fun proxiesByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow> { + return remoteSource.subscribe(chain.id) { + runtime.metadata.module(Modules.PROXY) + .storage("Proxies") + .observe( + accountId, + binding = { bindProxyAccounts(it) } + ) + }.map { + it.proxies.filter { it.proxyType == proxyType.name } + .map { ProxiedWithProxy.Proxy(it.accountId.value, it.proxyType) } + } + } + + override fun proxiesQuantityByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow { + return proxiesByTypeFlow(chain, accountId, proxyType) + .map { it.size } + } + private suspend fun getAllProxiesFor(chainId: ChainId, accountId: AccountId): OnChainProxiedModel { return remoteSource.query(chainId) { runtime.metadata.module(Modules.PROXY) @@ -94,7 +116,7 @@ class RealGetProxyRepository( } } - private suspend fun receiveAllProxies(chainId: ChainId): Map { + private suspend fun receiveAllProxiesInChain(chainId: ChainId): Map { return remoteSource.query(chainId) { runtime.metadata.module(Modules.PROXY) .storage("Proxies") 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 87cbe0f915..5595d19c3c 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 @@ -61,8 +61,9 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.con import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.select.di.SelectBondMoreComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.di.ConfirmSetControllerComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.set.di.SetControllerComponent -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.di.ConfirmAddStakingProxyComponent -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.di.AddStakingProxyComponent +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.di.ConfirmAddStakingProxyComponent +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.set.di.AddStakingProxyComponent +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.di.StakingProxyListComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.di.StakingComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.di.ConfirmRebondComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.custom.di.CustomRebondComponent @@ -173,6 +174,8 @@ interface StakingFeatureComponent : StakingFeatureApi { fun setStakingProxyFactory(): AddStakingProxyComponent.Factory + fun stakingProxyListFactory(): StakingProxyListComponent.Factory + fun confirmSetControllerFactory(): ConfirmSetControllerComponent.Factory fun confirmAddStakingProxyFactory(): ConfirmAddStakingProxyComponent.Factory diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt index 1d9b199487..bc0977e5c8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt @@ -79,6 +79,7 @@ import io.novafoundation.nova.feature_staking_impl.domain.rewards.RewardCalculat import io.novafoundation.nova.feature_staking_impl.domain.setup.ChangeValidatorsInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.bond.BondMoreInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.StakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.rebond.RebondInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.redeem.RedeemInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.rewardDestination.ChangeRewardDestinationInteractor @@ -620,4 +621,14 @@ class StakingFeatureModule { getProxyRepository ) } + + @Provides + @FeatureScope + fun provideStakingProxyListInteractor( + accountRepository: AccountRepository, + getProxyRepository: GetProxyRepository + ) = StakingProxyListInteractor( + accountRepository, + getProxyRepository + ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt new file mode 100644 index 0000000000..e24e991ed5 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt @@ -0,0 +1,40 @@ +package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list + +import io.novafoundation.nova.common.address.intoKey +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.model.StakingProxyAccount +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import jp.co.soramitsu.fearless_utils.runtime.AccountId +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine + +class StakingProxyListInteractor( + val accountRepository: AccountRepository, + val getProxyRepository: GetProxyRepository +) { + + fun stakingProxyListFlow(chain: Chain, accountId: AccountId): Flow> { + return combine( + accountRepository.activeMetaAccountsFlow(), + getProxyRepository.proxiesByTypeFlow(chain, accountId, ProxyType.Staking) + ) { metaAccounts, proxies -> + val accountIdToMetaAccount = metaAccounts + .filter { it.hasAccountIn(chain) } + .associateBy { + it.requireAccountIdIn(chain).intoKey() + } + + proxies.map { proxy -> + val proxyAccountId = proxy.accountId + StakingProxyAccount( + accountIdToMetaAccount[proxyAccountId.intoKey()], + proxyAccountId + ) + } + } + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt new file mode 100644 index 0000000000..4c182c6cd4 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt @@ -0,0 +1,9 @@ +package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.model + +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +class StakingProxyAccount( + val metaAccount: MetaAccount?, + val proxyAccountId: AccountId +) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt index f89167ed9e..81ba1acac9 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt @@ -6,7 +6,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.payouts.model.Pe import io.novafoundation.nova.feature_staking_impl.presentation.pools.common.SelectingPoolPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.confirm.ConfirmBondMorePayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.model.StakingStoryModel import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.rewardDestination.confirm.parcel.ConfirmRewardDestinationPayload @@ -98,4 +98,6 @@ interface StakingRouter { fun openAddStakingProxy() fun openConfirmAddStakingProxy(payload: ConfirmAddStakingProxyPayload) + + fun openStakingProxyList() } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyFragment.kt similarity index 99% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyFragment.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyFragment.kt index 1778e23922..d5bd1ff681 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyFragment.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm import android.os.Bundle import android.view.LayoutInflater diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyPayload.kt similarity index 92% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyPayload.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyPayload.kt index 7b767dc731..a656b52a34 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyPayload.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyPayload.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm import android.os.Parcelable import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt similarity index 99% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt index 3a663a3486..884222c079 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm import io.novafoundation.nova.common.address.AddressIconGenerator import io.novafoundation.nova.common.base.BaseViewModel diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/di/ConfirmAddStakingProxyComponent.kt similarity index 81% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyComponent.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/di/ConfirmAddStakingProxyComponent.kt index aa9852515d..54b085126b 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/di/ConfirmAddStakingProxyComponent.kt @@ -1,11 +1,11 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.di +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.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.staking.delegation.proxy.confirm.ConfirmAddStakingProxyFragment -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyPayload @Subcomponent( modules = [ diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/di/ConfirmAddStakingProxyModule.kt similarity index 95% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/di/ConfirmAddStakingProxyModule.kt index 51754b8b39..5888ec23b5 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/di/ConfirmAddStakingProxyModule.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.di +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.di import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModel @@ -18,8 +18,8 @@ import io.novafoundation.nova.feature_account_api.presenatation.actions.External import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyViewModel import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyFragment.kt similarity index 99% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyFragment.kt index 134c74e30f..03b318d02c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyFragment.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.set import android.os.Bundle import android.view.LayoutInflater diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt similarity index 99% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt index e563acd91c..e5a02c2cd6 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.set import io.novafoundation.nova.common.address.intoKey import io.novafoundation.nova.common.base.BaseViewModel @@ -25,7 +25,7 @@ import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.launchProxyDepositDescription import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyPayload import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyComponent.kt similarity index 86% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyComponent.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyComponent.kt index 001467e288..46645e8c70 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyComponent.kt @@ -1,10 +1,10 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.di +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.set.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.staking.delegation.proxy.set.AddStakingProxyFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.set.AddStakingProxyFragment @Subcomponent( modules = [ diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyModule.kt similarity index 97% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyModule.kt index 7f3f86b2f3..d52c43c95c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyModule.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.di +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.set.di import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModel @@ -20,7 +20,7 @@ import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepo import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.AddStakingProxyViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.set.AddStakingProxyViewModel import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListAdapter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListAdapter.kt new file mode 100644 index 0000000000..ed94707035 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListAdapter.kt @@ -0,0 +1,89 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list + +import android.view.View +import android.view.ViewGroup +import coil.ImageLoader +import io.novafoundation.nova.common.list.BaseGroupedDiffCallback +import io.novafoundation.nova.common.list.GroupedListAdapter +import io.novafoundation.nova.common.list.GroupedListHolder +import io.novafoundation.nova.common.utils.inflateChild +import io.novafoundation.nova.feature_account_api.presenatation.chain.loadChainIcon +import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.model.StakingProxyGroupRvItem +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.model.StakingProxyRvItem +import kotlinx.android.synthetic.main.item_proxy.view.itemStakingProxyAccountTitle +import kotlinx.android.synthetic.main.item_proxy.view.itemStakingProxyChainIcon +import kotlinx.android.synthetic.main.item_proxy.view.itemStakingProxyIcon +import kotlinx.android.synthetic.main.item_proxy_group.view.itemProxyGroup + +class StakingProxyListAdapter( + private val handler: Handler, + private val imageLoader: ImageLoader +) : GroupedListAdapter(DiffCallback()) { + + interface Handler { + fun onProxyClick(item: StakingProxyRvItem) + } + + override fun createGroupViewHolder(parent: ViewGroup): GroupedListHolder { + val view = parent.inflateChild(R.layout.item_proxy_group) + return StakingProxyGroupHolder(view) + } + + override fun createChildViewHolder(parent: ViewGroup): GroupedListHolder { + val view = parent.inflateChild(R.layout.item_proxy) + return StakingProxyHolder(handler, imageLoader, view) + } + + override fun bindGroup(holder: GroupedListHolder, group: StakingProxyGroupRvItem) { + require(holder is StakingProxyGroupHolder) + holder.bind(group) + } + + override fun bindChild(holder: GroupedListHolder, child: StakingProxyRvItem) { + require(holder is StakingProxyHolder) + holder.bind(child) + } +} + +private class DiffCallback : BaseGroupedDiffCallback(StakingProxyGroupRvItem::class.java) { + + override fun areGroupItemsTheSame(oldItem: StakingProxyGroupRvItem, newItem: StakingProxyGroupRvItem): Boolean { + return oldItem.text == newItem.text + } + + override fun areGroupContentsTheSame(oldItem: StakingProxyGroupRvItem, newItem: StakingProxyGroupRvItem): Boolean { + return true + } + + override fun areChildItemsTheSame(oldItem: StakingProxyRvItem, newItem: StakingProxyRvItem): Boolean { + return oldItem.accountAddress == newItem.accountAddress + } + + override fun areChildContentsTheSame(oldItem: StakingProxyRvItem, newItem: StakingProxyRvItem): Boolean { + return true + } +} + +class StakingProxyGroupHolder( + containerView: View, +) : GroupedListHolder(containerView) { + + fun bind(item: StakingProxyGroupRvItem) = with(containerView) { + itemProxyGroup.text = item.text + } +} + +class StakingProxyHolder( + private val eventHandler: StakingProxyListAdapter.Handler, + private val imageLoader: ImageLoader, + containerView: View, +) : GroupedListHolder(containerView) { + + fun bind(item: StakingProxyRvItem) = with(containerView) { + setOnClickListener { eventHandler.onProxyClick(item) } + itemStakingProxyIcon.setImageDrawable(item.accountIcon) + itemStakingProxyChainIcon.loadChainIcon(item.chainIconUrl, imageLoader) + itemStakingProxyAccountTitle.text = item.accountTitle + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListFragment.kt new file mode 100644 index 0000000000..2a159c53ff --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListFragment.kt @@ -0,0 +1,89 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import coil.ImageLoader +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.feature_account_api.presenatation.actions.CustomizableExternalActionsSheet +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActionModel +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_account_api.presenatation.actions.copyAddressClicked +import io.novafoundation.nova.feature_account_api.presenatation.actions.setupExternalActions +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.presentation.staking.delegation.proxy.list.model.StakingProxyRvItem +import javax.inject.Inject +import kotlinx.android.synthetic.main.fragment_staking_proxy_list.stakingProxyList +import kotlinx.android.synthetic.main.fragment_staking_proxy_list.stakingProxyListAddProxyButton +import kotlinx.android.synthetic.main.fragment_staking_proxy_list.stakingProxyListToolbar + +class StakingProxyListFragment : BaseFragment(), StakingProxyListAdapter.Handler { + + @Inject + protected lateinit var imageLoader: ImageLoader + + private val adapter by lazy(LazyThreadSafetyMode.NONE) { StakingProxyListAdapter(this, imageLoader) } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View? { + return inflater.inflate(R.layout.fragment_staking_proxy_list, container, false) + } + + override fun initViews() { + stakingProxyListToolbar.applyStatusBarInsets() + stakingProxyListToolbar.setHomeButtonListener { viewModel.backClicked() } + stakingProxyListAddProxyButton.prepareForProgress(this) + + stakingProxyListAddProxyButton.setOnClickListener { viewModel.addProxyClicked() } + + stakingProxyList.adapter = adapter + } + + override fun inject() { + FeatureUtils.getFeature( + requireContext(), + StakingFeatureApi::class.java + ) + .stakingProxyListFactory() + .create(this) + .inject(this) + } + + override fun subscribe(viewModel: StakingProxyListViewModel) { + setupExternalActions(viewModel) { context, payload -> + CustomizableExternalActionsSheet( + context, + payload, + onCopy = viewModel::copyAddressClicked, + onViewExternal = viewModel::viewExternalClicked, + additionalOptions = rewokeAccessExternalAction(payload) + ) + } + + viewModel.proxyModels.observe { + adapter.submitList(it) + } + } + + override fun onProxyClick(item: StakingProxyRvItem) { + viewModel.proxiClicked(item) + } + + private fun rewokeAccessExternalAction(payload: ExternalActions.Payload): List { + return listOf( + ExternalActionModel( + R.drawable.ic_delete_symbol, + getString(R.string.common_proxy_rewoke_access), + onClick = { viewModel.rewokeAccess(payload) } + ) + ) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt new file mode 100644 index 0000000000..7f2b0a3b88 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt @@ -0,0 +1,87 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list + +import io.novafoundation.nova.common.address.AddressIconGenerator +import io.novafoundation.nova.common.address.AddressIconGenerator.Companion.SIZE_BIG +import io.novafoundation.nova.common.base.BaseViewModel +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_account_api.presenatation.actions.showAddressActions +import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.StakingProxyListInteractor +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.model.StakingProxyAccount +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.model.StakingProxyGroupRvItem +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.model.StakingProxyRvItem +import io.novafoundation.nova.runtime.ext.addressOf +import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState +import io.novafoundation.nova.runtime.state.chain +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch + +class StakingProxyListViewModel( + private val selectedAssetState: AnySelectedAssetOptionSharedState, + private val externalActions: ExternalActions.Presentation, + private val accountRepository: AccountRepository, + private val stakingProxyListInteractor: StakingProxyListInteractor, + private val resourceManager: ResourceManager, + private val stakingRouter: StakingRouter, + private val addressIconGenerator: AddressIconGenerator +) : BaseViewModel(), ExternalActions by externalActions { + + val selectedMetaAccount = accountRepository.selectedMetaAccountFlow() + .shareInBackground() + + val proxies = selectedMetaAccount.flatMapLatest { + val chain = selectedAssetState.chain() + val accountId = it.requireAccountIdIn(chain) + stakingProxyListInteractor.stakingProxyListFlow(chain, accountId) + } + .shareInBackground() + + val proxyModels: Flow> = proxies.map { + mapToProxyList(it) + } + .shareInBackground() + + fun backClicked() { + stakingRouter.back() + } + + fun addProxyClicked() { + stakingRouter.openAddStakingProxy() + } + + fun proxiClicked(item: StakingProxyRvItem) { + launch { + val chain = selectedAssetState.chain() + externalActions.showAddressActions(item.accountAddress, chain) + } + } + + fun rewokeAccess(payload: ExternalActions.Payload) { + } + + private suspend fun mapToProxyList(proxies: List): List { + val chain = selectedAssetState.chain() + return buildList { + val groupTitle = resourceManager.getString(R.string.staking_proxies_group_title) + add(StakingProxyGroupRvItem(groupTitle)) + + val proxyRvItems = proxies.map { stakingProxyAccount -> + val accountAddress = chain.addressOf(stakingProxyAccount.proxyAccountId) + StakingProxyRvItem( + addressIconGenerator.createAddressIcon(stakingProxyAccount.proxyAccountId, SIZE_BIG), + chain.icon, + stakingProxyAccount.metaAccount?.name ?: accountAddress, + accountAddress + ) + } + + addAll(proxyRvItems) + } + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListComponent.kt new file mode 100644 index 0000000000..c47fa60b30 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListComponent.kt @@ -0,0 +1,23 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.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.staking.delegation.proxy.list.StakingProxyListFragment + +@Subcomponent( + modules = [ + StakingProxyListModule::class + ] +) +@ScreenScope +interface StakingProxyListComponent { + + @Subcomponent.Factory + interface Factory { + fun create(@BindsInstance fragment: Fragment): StakingProxyListComponent + } + + fun inject(fragment: StakingProxyListFragment) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt new file mode 100644 index 0000000000..9817146824 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt @@ -0,0 +1,53 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.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.viewmodel.ViewModelKey +import io.novafoundation.nova.common.di.viewmodel.ViewModelModule +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.StakingProxyListInteractor +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.StakingProxyListViewModel +import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState + +@Module(includes = [ViewModelModule::class]) +class StakingProxyListModule { + + @Provides + @IntoMap + @ViewModelKey(StakingProxyListViewModel::class) + fun provideViewModel( + selectedAssetState: AnySelectedAssetOptionSharedState, + externalActions: ExternalActions.Presentation, + accountRepository: AccountRepository, + resourceManager: ResourceManager, + stakingRouter: StakingRouter, + addressIconGenerator: AddressIconGenerator, + stakingProxyListInteractor: StakingProxyListInteractor + ): ViewModel { + return StakingProxyListViewModel( + selectedAssetState = selectedAssetState, + externalActions = externalActions, + accountRepository = accountRepository, + resourceManager = resourceManager, + stakingRouter = stakingRouter, + addressIconGenerator = addressIconGenerator, + stakingProxyListInteractor = stakingProxyListInteractor + ) + } + + @Provides + fun provideViewModelCreator( + fragment: Fragment, + viewModelFactory: ViewModelProvider.Factory + ): StakingProxyListViewModel { + return ViewModelProvider(fragment, viewModelFactory).get(StakingProxyListViewModel::class.java) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/model/StakingProxyListModels.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/model/StakingProxyListModels.kt new file mode 100644 index 0000000000..9f88f3d135 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/model/StakingProxyListModels.kt @@ -0,0 +1,12 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.model + +import android.graphics.drawable.Drawable + +class StakingProxyGroupRvItem(val text: String) + +class StakingProxyRvItem( + val accountIcon: Drawable, + val chainIconUrl: String, + val accountTitle: String, + val accountAddress: String +) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt index 6e834ebe9f..72fe727809 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt @@ -77,10 +77,11 @@ fun ManageStakeAction.Companion.addStakingProxy(resourceManager: ResourceManager ) } -fun ManageStakeAction.Companion.stakingProxies(resourceManager: ResourceManager): ManageStakeAction { +fun ManageStakeAction.Companion.stakingProxies(resourceManager: ResourceManager, delegations: String): ManageStakeAction { return ManageStakeAction( id = SYSTEM_MANAGE_PROXIES, label = resourceManager.getString(R.string.staking_action_your_proxies), - iconRes = R.drawable.ic_people_outline + iconRes = R.drawable.ic_people_outline, + badge = delegations ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt index 2d402e263a..cadd611022 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt @@ -4,6 +4,10 @@ import androidx.lifecycle.MutableLiveData import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.Event import io.novafoundation.nova.common.utils.WithCoroutineScopeExtensions +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_staking_api.domain.model.relaychain.StakingState import io.novafoundation.nova.feature_staking_impl.data.StakingOption import io.novafoundation.nova.feature_staking_impl.data.chain @@ -30,13 +34,16 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.com import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.controller import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.payouts import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.rewardDestination +import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.stakingProxies import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.unbond import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.validators import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.mainStakingValidationFailure import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.transformLatest +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.launch class RelaychainStakeActionsComponentFactory( @@ -44,6 +51,8 @@ class RelaychainStakeActionsComponentFactory( private val resourceManager: ResourceManager, private val stakeActionsValidations: Map, private val router: StakingRouter, + private val accountRepository: AccountRepository, + private val getProxyRepository: GetProxyRepository ) { fun create( @@ -55,7 +64,9 @@ class RelaychainStakeActionsComponentFactory( router = router, stakeActionsValidations = stakeActionsValidations, stakingOption = stakingOption, - hostContext = hostContext + hostContext = hostContext, + accountRepository = accountRepository, + getProxyRepository = getProxyRepository ) } @@ -64,23 +75,35 @@ private class RelaychainStakeActionsComponent( private val resourceManager: ResourceManager, private val router: StakingRouter, private val stakeActionsValidations: Map, - private val hostContext: ComponentHostContext, private val stakingOption: StakingOption, + private val accountRepository: AccountRepository, + private val getProxyRepository: GetProxyRepository ) : StakeActionsComponent, CoroutineScope by hostContext.scope, WithCoroutineScopeExtensions by WithCoroutineScopeExtensions(hostContext.scope) { override val events = MutableLiveData>() + @OptIn(ExperimentalCoroutinesApi::class) + private val stakingProxiesQuantity = accountRepository.selectedMetaAccountFlow() + .flatMapLatest { metaAccount -> + val chain = stakingOption.assetWithChain.chain + val accountId = metaAccount.requireAccountIdIn(chain) + getProxyRepository.proxiesQuantityByTypeFlow(chain, accountId, ProxyType.Staking) + } + private val selectedAccountStakingStateFlow = stakingSharedComputation.selectedAccountStakingStateFlow( assetWithChain = stakingOption.assetWithChain, scope = hostContext.scope ) - override val state = selectedAccountStakingStateFlow.transformLatest { stakingState -> + override val state = combineTransform( + selectedAccountStakingStateFlow, + stakingProxiesQuantity + ) { stakingState, proxiesQuantity -> if (stakingState is StakingState.Stash) { - emit(StakeActionsState(availableActionsFor(stakingState))) + emit(StakeActionsState(availableActionsFor(stakingState, proxiesQuantity))) } else { emit(null) } @@ -125,27 +148,35 @@ private class RelaychainStakeActionsComponent( SYSTEM_MANAGE_VALIDATORS -> router.openCurrentValidators() SYSTEM_MANAGE_REWARD_DESTINATION -> router.openChangeRewardDestination() SYSTEM_ADD_PROXY -> router.openAddStakingProxy() - SYSTEM_MANAGE_PROXIES -> TODO() + SYSTEM_MANAGE_PROXIES -> router.openStakingProxyList() } } - private fun availableActionsFor(stakingState: StakingState.Stash): List = buildList { - add(ManageStakeAction.Companion::bondMore) - add(ManageStakeAction.Companion::unbond) - add(ManageStakeAction.Companion::rewardDestination) + private fun availableActionsFor(stakingState: StakingState.Stash, proxiesQuantity: Int): List = buildList { + add(ManageStakeAction.bondMore(resourceManager)) + add(ManageStakeAction.unbond(resourceManager)) + add(ManageStakeAction.rewardDestination(resourceManager)) if (stakingState !is StakingState.Stash.None) { - add(ManageStakeAction.Companion::payouts) + add(ManageStakeAction.payouts(resourceManager)) } if (stakingState !is StakingState.Stash.Validator) { - add(ManageStakeAction.Companion::validators) + add(ManageStakeAction.validators(resourceManager)) } - add(ManageStakeAction.Companion::controller) - if (stakingOption.chain.supportProxy) { - add(ManageStakeAction.Companion::addStakingProxy) // TODO: handle case when proxy is already set + add(proxiesAction(proxiesQuantity)) + } + + add(ManageStakeAction.controller(resourceManager)) + } + + private fun proxiesAction(proxiesQuantity: Int): ManageStakeAction { + return if (proxiesQuantity == 0) { + ManageStakeAction.addStakingProxy(resourceManager) + } else { + ManageStakeAction.stakingProxies(resourceManager, proxiesQuantity.toString()) } - }.map { it.invoke(resourceManager) } + } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/di/components/RelaychainModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/di/components/RelaychainModule.kt index 6440ad1328..b9f7ccf18e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/di/components/RelaychainModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/di/components/RelaychainModule.kt @@ -5,6 +5,8 @@ import dagger.Provides import io.novafoundation.nova.common.di.scope.ScreenScope import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor import io.novafoundation.nova.feature_staking_impl.domain.alerts.AlertsInteractor import io.novafoundation.nova.feature_staking_impl.domain.common.StakingSharedComputation @@ -66,11 +68,15 @@ class RelaychainModule { resourceManager: ResourceManager, stakeActionsValidations: Map<@JvmSuppressWildcards String, StakeActionsValidationSystem>, router: StakingRouter, + accountRepository: AccountRepository, + getProxyRepository: GetProxyRepository ) = RelaychainStakeActionsComponentFactory( stakingSharedComputation = stakingSharedComputation, resourceManager = resourceManager, stakeActionsValidations = stakeActionsValidations, - router = router + router = router, + accountRepository = accountRepository, + getProxyRepository = getProxyRepository ) @Provides diff --git a/feature-staking-impl/src/main/res/layout/fragment_staking_proxy_list.xml b/feature-staking-impl/src/main/res/layout/fragment_staking_proxy_list.xml new file mode 100644 index 0000000000..b0f58d2fbf --- /dev/null +++ b/feature-staking-impl/src/main/res/layout/fragment_staking_proxy_list.xml @@ -0,0 +1,37 @@ + + + + + + + + + + \ No newline at end of file diff --git a/feature-staking-impl/src/main/res/layout/item_proxy.xml b/feature-staking-impl/src/main/res/layout/item_proxy.xml new file mode 100644 index 0000000000..363ad6c761 --- /dev/null +++ b/feature-staking-impl/src/main/res/layout/item_proxy.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/feature-staking-impl/src/main/res/layout/item_proxy_group.xml b/feature-staking-impl/src/main/res/layout/item_proxy_group.xml new file mode 100644 index 0000000000..e023874e0a --- /dev/null +++ b/feature-staking-impl/src/main/res/layout/item_proxy_group.xml @@ -0,0 +1,13 @@ + + \ No newline at end of file From c99b9ef746537de252eb0fdf737eeb1ee2d593e8 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 12 Jan 2024 03:53:26 +0100 Subject: [PATCH 13/55] Clean code --- common/src/main/res/drawable/ic_delete.xml | 10 ++++++++++ common/src/main/res/values/strings.xml | 1 - .../delegation/proxy/list/StakingProxyListFragment.kt | 5 ++--- .../delegation/proxy/list/StakingProxyListViewModel.kt | 2 +- .../main/components/stakeActions/ManageStakeAction.kt | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 common/src/main/res/drawable/ic_delete.xml diff --git a/common/src/main/res/drawable/ic_delete.xml b/common/src/main/res/drawable/ic_delete.xml new file mode 100644 index 0000000000..59a04a89f8 --- /dev/null +++ b/common/src/main/res/drawable/ic_delete.xml @@ -0,0 +1,10 @@ + + + diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index c9b4c34763..862e4a3242 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,7 +1,6 @@ - Add delegation diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListFragment.kt index 2a159c53ff..7331467104 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListFragment.kt @@ -40,7 +40,6 @@ class StakingProxyListFragment : BaseFragment(), Stak override fun initViews() { stakingProxyListToolbar.applyStatusBarInsets() stakingProxyListToolbar.setHomeButtonListener { viewModel.backClicked() } - stakingProxyListAddProxyButton.prepareForProgress(this) stakingProxyListAddProxyButton.setOnClickListener { viewModel.addProxyClicked() } @@ -74,13 +73,13 @@ class StakingProxyListFragment : BaseFragment(), Stak } override fun onProxyClick(item: StakingProxyRvItem) { - viewModel.proxiClicked(item) + viewModel.proxyClicked(item) } private fun rewokeAccessExternalAction(payload: ExternalActions.Payload): List { return listOf( ExternalActionModel( - R.drawable.ic_delete_symbol, + R.drawable.ic_delete, getString(R.string.common_proxy_rewoke_access), onClick = { viewModel.rewokeAccess(payload) } ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt index 7f2b0a3b88..bf01eeb996 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt @@ -55,7 +55,7 @@ class StakingProxyListViewModel( stakingRouter.openAddStakingProxy() } - fun proxiClicked(item: StakingProxyRvItem) { + fun proxyClicked(item: StakingProxyRvItem) { launch { val chain = selectedAssetState.chain() externalActions.showAddressActions(item.accountAddress, chain) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt index 72fe727809..4d05f40eb0 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/ManageStakeAction.kt @@ -81,7 +81,7 @@ fun ManageStakeAction.Companion.stakingProxies(resourceManager: ResourceManager, return ManageStakeAction( id = SYSTEM_MANAGE_PROXIES, label = resourceManager.getString(R.string.staking_action_your_proxies), - iconRes = R.drawable.ic_people_outline, + iconRes = R.drawable.ic_delegate_outline, badge = delegations ) } From a6b342a723381c56c96c124db97cbd9c88ae92f5 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 12 Jan 2024 04:07:39 +0100 Subject: [PATCH 14/55] Fixed bugs --- .../src/main/res/drawable/ic_clear_pin_code_outline.xml | 0 .../presenatation/actions/CustomizableExternalActionsSheet.kt | 2 +- feature-account-impl/src/main/res/layout/pincode_view.xml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename feature-account-impl/src/main/res/drawable/ic_delete.xml => common/src/main/res/drawable/ic_clear_pin_code_outline.xml (100%) diff --git a/feature-account-impl/src/main/res/drawable/ic_delete.xml b/common/src/main/res/drawable/ic_clear_pin_code_outline.xml similarity index 100% rename from feature-account-impl/src/main/res/drawable/ic_delete.xml rename to common/src/main/res/drawable/ic_clear_pin_code_outline.xml diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/actions/CustomizableExternalActionsSheet.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/actions/CustomizableExternalActionsSheet.kt index 1a0ae7f0af..e74de5f64d 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/actions/CustomizableExternalActionsSheet.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/actions/CustomizableExternalActionsSheet.kt @@ -23,7 +23,7 @@ class CustomizableExternalActionsSheet( super.onCreate(savedInstanceState) additionalOptions.forEach { externalActionModel -> - textItem(externalActionModel.iconRes, externalActionModel.title) { + textItem(externalActionModel.iconRes, externalActionModel.title, showArrow = true) { externalActionModel.onClick() } } diff --git a/feature-account-impl/src/main/res/layout/pincode_view.xml b/feature-account-impl/src/main/res/layout/pincode_view.xml index b020c4eda0..9c4161862e 100644 --- a/feature-account-impl/src/main/res/layout/pincode_view.xml +++ b/feature-account-impl/src/main/res/layout/pincode_view.xml @@ -109,7 +109,7 @@ android:id="@+id/btnDelete" style="@style/Widget.Nova.Button.PinCodeControlButton" android:layout_margin="@dimen/pin_code_view_spacing" - android:src="@drawable/ic_delete" + android:src="@drawable/ic_clear_pin_code_outline" android:tint="@color/color_delete_button" /> From bdc5087366d44c2dfeb64a889a2c4f7cec29fd55 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 12 Jan 2024 08:46:34 +0100 Subject: [PATCH 15/55] Confirm remove proxy --- .../relaychain/RelayStakingNavigator.kt | 7 + .../res/navigation/staking_main_graph.xml | 13 ++ common/src/main/res/values/strings.xml | 2 + .../data/calls/ExtrinsicBuilderExt.kt | 23 ++- .../di/StakingFeatureComponent.kt | 7 +- .../di/StakingFeatureModule.kt | 8 + .../di/StakingValidationModule.kt | 6 +- .../AddStakingProxyValidationsModule.kt | 12 +- .../RemoveStakingProxyValidationsModule.kt | 26 +++ .../remove/RemoveStakingProxyInteractor.kt | 41 +++++ .../AddStakingProxyValidationFailure.kt | 2 +- .../AddStakingProxyValidationPayload.kt | 2 +- .../proxy/{ => add}/Declarations.kt | 2 +- .../delegation/proxy/remove/Declarations.kt | 41 +++++ .../RemoveStakingProxyValidationFailure.kt | 17 ++ .../RemoveStakingProxyValidationPayload.kt | 14 ++ .../presentation/StakingRouter.kt | 3 + .../confirm/ConfirmAddStakingProxyFragment.kt | 2 +- .../ConfirmAddStakingProxyViewModel.kt | 4 +- .../di/ConfirmAddStakingProxyModule.kt | 2 +- .../proxy/add/set/AddStakingProxyViewModel.kt | 4 +- .../proxy/add/set/di/AddStakingProxyModule.kt | 2 +- .../AddProxyValidationFailureHandling.kt | 12 +- ...RemoveStakingProxyValidationFailureToUi.kt | 20 +++ .../proxy/list/StakingProxyListViewModel.kt | 8 +- .../ConfirmRemoveStakingProxyFragment.kt | 82 +++++++++ .../ConfirmRemoveStakingProxyPayload.kt | 9 + .../ConfirmRemoveStakingProxyViewModel.kt | 161 ++++++++++++++++++ .../di/ConfirmRemoveStakingProxyComponent.kt | 27 +++ .../di/ConfirmRemoveStakingProxyModule.kt | 70 ++++++++ .../fragment_confirm_revoke_staking_proxy.xml | 105 ++++++++++++ 31 files changed, 702 insertions(+), 32 deletions(-) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/RemoveStakingProxyValidationsModule.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/{ => add}/AddStakingProxyValidationFailure.kt (97%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/{ => add}/AddStakingProxyValidationPayload.kt (95%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/{ => add}/Declarations.kt (99%) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/RemoveStakingProxyValidationFailure.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/RemoveStakingProxyValidationPayload.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/RemoveStakingProxyValidationFailureToUi.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyFragment.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyPayload.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/di/ConfirmRemoveStakingProxyComponent.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/di/ConfirmRemoveStakingProxyModule.kt create mode 100644 feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt index 19b1298b7e..1cf4a04603 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/staking/relaychain/RelayStakingNavigator.kt @@ -23,6 +23,8 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegati import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyFragment import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.ConfirmRemoveStakingProxyFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.ConfirmRemoveStakingProxyPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.model.StakingStoryModel import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondFragment import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondPayload @@ -239,4 +241,9 @@ class RelayStakingNavigator( override fun openStakingProxyList() { performNavigation(R.id.action_open_stakingProxyList) } + + override fun openConfirmRemoveStakingProxy(payload: ConfirmRemoveStakingProxyPayload) { + val arguments = ConfirmRemoveStakingProxyFragment.getBundle(payload) + performNavigation(R.id.action_open_confirmRemoveStakingProxyFragment, arguments) + } } diff --git a/app/src/main/res/navigation/staking_main_graph.xml b/app/src/main/res/navigation/staking_main_graph.xml index 4003d87f1a..e92cda80a4 100644 --- a/app/src/main/res/navigation/staking_main_graph.xml +++ b/app/src/main/res/navigation/staking_main_graph.xml @@ -45,6 +45,14 @@ app:popEnterAnim="@anim/fragment_close_enter" app:popExitAnim="@anim/fragment_close_exit" /> + + + + + Revoke access + Add delegation diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt index 5504d33eed..e483f3fa1b 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/calls/ExtrinsicBuilderExt.kt @@ -4,6 +4,7 @@ import io.novafoundation.nova.common.utils.Modules import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import java.math.BigInteger import jp.co.soramitsu.fearless_utils.runtime.AccountId +import jp.co.soramitsu.fearless_utils.runtime.RuntimeSnapshot import jp.co.soramitsu.fearless_utils.runtime.definitions.types.composite.DictEnum import jp.co.soramitsu.fearless_utils.runtime.definitions.types.instances.AddressInstanceConstructor import jp.co.soramitsu.fearless_utils.runtime.extrinsic.ExtrinsicBuilder @@ -12,10 +13,22 @@ fun ExtrinsicBuilder.addProxyCall(proxyAccountId: AccountId, proxyType: ProxyTyp return call( Modules.PROXY, "add_proxy", - mapOf( - "delegate" to AddressInstanceConstructor.constructInstance(runtime.typeRegistry, proxyAccountId), - "proxy_type" to DictEnum.Entry(proxyType.name, null), - "delay" to BigInteger.ZERO - ) + argumentsForProxy(runtime, proxyAccountId, proxyType) + ) +} + +fun ExtrinsicBuilder.removeProxyCall(proxyAccountId: AccountId, proxyType: ProxyType): ExtrinsicBuilder { + return call( + Modules.PROXY, + "remove_proxy", + argumentsForProxy(runtime, proxyAccountId, proxyType) + ) +} + +private fun argumentsForProxy(runtime: RuntimeSnapshot, proxyAccountId: AccountId, proxyType: ProxyType): Map { + return mapOf( + "delegate" to AddressInstanceConstructor.constructInstance(runtime.typeRegistry, proxyAccountId), + "proxy_type" to DictEnum.Entry(proxyType.name, null), + "delay" to BigInteger.ZERO ) } 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 5595d19c3c..ddc78b117c 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 @@ -19,7 +19,6 @@ import io.novafoundation.nova.feature_staking_impl.di.staking.parachain.Parachai import io.novafoundation.nova.feature_staking_impl.di.staking.stakingTypeDetails.StakingTypeDetailsModule import io.novafoundation.nova.feature_staking_impl.di.staking.startMultiStaking.StartMultiStakingModule import io.novafoundation.nova.feature_staking_impl.di.staking.unbond.StakingUnbondModule -import io.novafoundation.nova.feature_staking_impl.di.validations.AddStakingProxyValidationsModule import io.novafoundation.nova.feature_staking_impl.domain.nominationPools.common.rewards.NominationPoolRewardCalculatorFactory import io.novafoundation.nova.feature_staking_impl.presentation.NominationPoolsRouter import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter @@ -64,6 +63,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegati import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.di.ConfirmAddStakingProxyComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.set.di.AddStakingProxyComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.di.StakingProxyListComponent +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.di.ConfirmRemoveStakingProxyComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.di.StakingComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.di.ConfirmRebondComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.custom.di.CustomRebondComponent @@ -101,8 +101,7 @@ import io.novafoundation.nova.runtime.di.RuntimeApi NominationPoolModule::class, StakingDashboardModule::class, StartMultiStakingModule::class, - StakingTypeDetailsModule::class, - AddStakingProxyValidationsModule::class + StakingTypeDetailsModule::class ] ) @FeatureScope @@ -180,6 +179,8 @@ interface StakingFeatureComponent : StakingFeatureApi { fun confirmAddStakingProxyFactory(): ConfirmAddStakingProxyComponent.Factory + fun confirmRevokeStakingProxyFactory(): ConfirmRemoveStakingProxyComponent.Factory + fun rebondCustomFactory(): CustomRebondComponent.Factory fun currentValidatorsFactory(): CurrentValidatorsComponent.Factory diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt index bc0977e5c8..2391ec74ec 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt @@ -80,6 +80,8 @@ import io.novafoundation.nova.feature_staking_impl.domain.setup.ChangeValidators import io.novafoundation.nova.feature_staking_impl.domain.staking.bond.BondMoreInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.StakingProxyListInteractor +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.remove.RealRemoveStakingProxyInteractor +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.remove.RemoveStakingProxyInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.rebond.RebondInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.redeem.RedeemInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.rewardDestination.ChangeRewardDestinationInteractor @@ -631,4 +633,10 @@ class StakingFeatureModule { accountRepository, getProxyRepository ) + + @Provides + @FeatureScope + fun removeStakingProxyInteractor( + extrinsicService: ExtrinsicService + ): RemoveStakingProxyInteractor = RealRemoveStakingProxyInteractor(extrinsicService) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingValidationModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingValidationModule.kt index aa47d956bb..431d5ed12c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingValidationModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingValidationModule.kt @@ -1,10 +1,12 @@ package io.novafoundation.nova.feature_staking_impl.di import dagger.Module +import io.novafoundation.nova.feature_staking_impl.di.validations.AddStakingProxyValidationsModule import io.novafoundation.nova.feature_staking_impl.di.validations.BondMoreValidationsModule import io.novafoundation.nova.feature_staking_impl.di.validations.MakePayoutValidationsModule import io.novafoundation.nova.feature_staking_impl.di.validations.RebondValidationsModule import io.novafoundation.nova.feature_staking_impl.di.validations.RedeemValidationsModule +import io.novafoundation.nova.feature_staking_impl.di.validations.RemoveStakingProxyValidationsModule import io.novafoundation.nova.feature_staking_impl.di.validations.RewardDestinationValidationsModule import io.novafoundation.nova.feature_staking_impl.di.validations.SetControllerValidationsModule import io.novafoundation.nova.feature_staking_impl.di.validations.SetupStakingValidationsModule @@ -21,7 +23,9 @@ import io.novafoundation.nova.feature_staking_impl.di.validations.UnbondValidati RebondValidationsModule::class, SetControllerValidationsModule::class, RewardDestinationValidationsModule::class, - StakeActionsValidationModule::class + StakeActionsValidationModule::class, + AddStakingProxyValidationsModule::class, + RemoveStakingProxyValidationsModule::class ] ) class StakingValidationModule diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt index b33bfd04b4..29cbbb7eaf 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt @@ -5,12 +5,12 @@ import dagger.Provides import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.common.validation.ValidationSystem import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.enoughBalanceToPayDeposit -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.maximumProxies -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.sufficientBalanceToPayFee -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.sufficientBalanceToStayAboveEd -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.validAddress +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.enoughBalanceToPayDeposit +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.maximumProxies +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.sufficientBalanceToPayFee +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.sufficientBalanceToStayAboveEd +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.validAddress import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughTotalToStayAboveEDValidationFactory @Module diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/RemoveStakingProxyValidationsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/RemoveStakingProxyValidationsModule.kt new file mode 100644 index 0000000000..d956efa241 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/RemoveStakingProxyValidationsModule.kt @@ -0,0 +1,26 @@ +package io.novafoundation.nova.feature_staking_impl.di.validations + +import dagger.Module +import dagger.Provides +import io.novafoundation.nova.common.di.scope.FeatureScope +import io.novafoundation.nova.common.validation.ValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.sufficientBalanceToPayFee +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.sufficientBalanceToStayAboveEd +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.remove.RemoveStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.remove.sufficientBalanceToPayFee +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.remove.sufficientBalanceToStayAboveEd +import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughTotalToStayAboveEDValidationFactory + +@Module +class RemoveStakingProxyValidationsModule { + + @FeatureScope + @Provides + fun provideAddStakingProxyValidationSystem( + enoughTotalToStayAboveEDValidationFactory: EnoughTotalToStayAboveEDValidationFactory + ): RemoveStakingProxyValidationSystem = ValidationSystem { + sufficientBalanceToPayFee() + + sufficientBalanceToStayAboveEd(enoughTotalToStayAboveEDValidationFactory) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt new file mode 100644 index 0000000000..3b418d63e8 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt @@ -0,0 +1,41 @@ +package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.remove + +import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.intoOrigin +import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService +import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission +import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_proxy_api.data.calls.removeProxyCall +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.runtime.ext.emptyAccountId +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import jp.co.soramitsu.fearless_utils.runtime.AccountId +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +interface RemoveStakingProxyInteractor { + + suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee + + suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result +} + +class RealRemoveStakingProxyInteractor( + private val extrinsicService: ExtrinsicService +) : RemoveStakingProxyInteractor { + + override suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee { + return withContext(Dispatchers.IO) { + extrinsicService.estimateFee(chain, proxiedAccountId.intoOrigin()) { + removeProxyCall(chain.emptyAccountId(), ProxyType.Staking) + } + } + } + + override suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { + return withContext(Dispatchers.IO) { + extrinsicService.submitExtrinsic(chain, proxiedAccountId.intoOrigin()) { + removeProxyCall(proxyAccountId, ProxyType.Staking) + } + } + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt similarity index 97% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt index e462f2179f..22d1122cd1 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.feature_wallet_api.domain.validation.InsufficientBalanceToStayAboveEDError diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationPayload.kt similarity index 95% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationPayload.kt index aa8ba8ff93..08cfeafa6a 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationPayload.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationPayload.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity import io.novafoundation.nova.feature_wallet_api.domain.model.Asset diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt similarity index 99% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt index 5f697352e3..d39fbc1a48 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add import io.novafoundation.nova.common.validation.ValidationSystem import io.novafoundation.nova.common.validation.ValidationSystemBuilder diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt new file mode 100644 index 0000000000..8e255829a2 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt @@ -0,0 +1,41 @@ +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.remove + +import io.novafoundation.nova.common.validation.ValidationSystem +import io.novafoundation.nova.common.validation.ValidationSystemBuilder +import io.novafoundation.nova.feature_wallet_api.domain.model.balanceCountedTowardsED +import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughTotalToStayAboveEDValidationFactory +import io.novafoundation.nova.feature_wallet_api.domain.validation.sufficientBalance +import io.novafoundation.nova.feature_wallet_api.domain.validation.validate +import io.novafoundation.nova.runtime.multiNetwork.ChainWithAsset +import java.math.BigDecimal + +typealias RemoveStakingProxyValidationSystem = ValidationSystem +typealias RemoveStakingProxyValidationSystemBuilder = ValidationSystemBuilder + +fun RemoveStakingProxyValidationSystemBuilder.sufficientBalanceToStayAboveEd( + enoughTotalToStayAboveEDValidationFactory: EnoughTotalToStayAboveEDValidationFactory +) = enoughTotalToStayAboveEDValidationFactory.validate( + chainWithAsset = { ChainWithAsset(it.chain, it.asset.token.configuration) }, + balance = { it.asset.balanceCountedTowardsED() }, + fee = { it.fee }, + error = { payload, _ -> + RemoveStakingProxyValidationFailure.NotEnoughToStayAboveED( + asset = payload.asset.token.configuration + ) + } +) + +fun RemoveStakingProxyValidationSystemBuilder.sufficientBalanceToPayFee() { + return sufficientBalance( + available = { it.asset.free }, + amount = { BigDecimal.ZERO }, + fee = { it.fee }, + error = { context -> + RemoveStakingProxyValidationFailure.NotEnoughToPayFee( + chainAsset = context.payload.asset.token.configuration, + maxUsable = context.availableToPayFees, + fee = context.fee + ) + } + ) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/RemoveStakingProxyValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/RemoveStakingProxyValidationFailure.kt new file mode 100644 index 0000000000..0a80ac80bb --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/RemoveStakingProxyValidationFailure.kt @@ -0,0 +1,17 @@ +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.remove + +import io.novafoundation.nova.feature_wallet_api.domain.validation.InsufficientBalanceToStayAboveEDError +import io.novafoundation.nova.feature_wallet_api.domain.validation.NotEnoughToPayFeesError +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import java.math.BigDecimal + +sealed interface RemoveStakingProxyValidationFailure { + + class NotEnoughToPayFee( + override val chainAsset: Chain.Asset, + override val maxUsable: BigDecimal, + override val fee: BigDecimal + ) : RemoveStakingProxyValidationFailure, NotEnoughToPayFeesError + + class NotEnoughToStayAboveED(override val asset: Chain.Asset) : RemoveStakingProxyValidationFailure, InsufficientBalanceToStayAboveEDError +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/RemoveStakingProxyValidationPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/RemoveStakingProxyValidationPayload.kt new file mode 100644 index 0000000000..1909ea1ea2 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/RemoveStakingProxyValidationPayload.kt @@ -0,0 +1,14 @@ +package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.remove + +import io.novafoundation.nova.feature_wallet_api.domain.model.Asset +import io.novafoundation.nova.feature_wallet_api.presentation.model.DecimalFee +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +class RemoveStakingProxyValidationPayload( + val chain: Chain, + val asset: Asset, + val proxiedAccountId: AccountId, + val proxyAddress: String, + val fee: DecimalFee +) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt index 81ba1acac9..04bea06c6d 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StakingRouter.kt @@ -7,6 +7,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.pools.common.Sel import io.novafoundation.nova.feature_staking_impl.presentation.staking.bond.confirm.ConfirmBondMorePayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.controller.confirm.ConfirmSetControllerPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.ConfirmRemoveStakingProxyPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.model.StakingStoryModel import io.novafoundation.nova.feature_staking_impl.presentation.staking.rebond.confirm.ConfirmRebondPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.rewardDestination.confirm.parcel.ConfirmRewardDestinationPayload @@ -100,4 +101,6 @@ interface StakingRouter { fun openConfirmAddStakingProxy(payload: ConfirmAddStakingProxyPayload) fun openStakingProxyList() + + fun openConfirmRemoveStakingProxy(payload: ConfirmRemoveStakingProxyPayload) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyFragment.kt index d5bd1ff681..ef02c9724e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyFragment.kt @@ -53,7 +53,7 @@ class ConfirmAddStakingProxyFragment : BaseFragment handleNotEnoughFeeError(failure, resourceManager) + + is NotEnoughToStayAboveED -> handleInsufficientBalanceCommission(failure, resourceManager) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt index bf01eeb996..3105613fdf 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt @@ -4,6 +4,7 @@ import io.novafoundation.nova.common.address.AddressIconGenerator import io.novafoundation.nova.common.address.AddressIconGenerator.Companion.SIZE_BIG import io.novafoundation.nova.common.base.BaseViewModel import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.utils.castOrNull import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions @@ -14,6 +15,7 @@ import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.pro import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.model.StakingProxyGroupRvItem import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.model.StakingProxyRvItem +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.ConfirmRemoveStakingProxyPayload import io.novafoundation.nova.runtime.ext.addressOf import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState import io.novafoundation.nova.runtime.state.chain @@ -62,7 +64,9 @@ class StakingProxyListViewModel( } } - fun rewokeAccess(payload: ExternalActions.Payload) { + fun rewokeAccess(externalActionPayload: ExternalActions.Payload) { + val payload = ConfirmRemoveStakingProxyPayload(externalActionPayload.requireAddress()) + stakingRouter.openConfirmRemoveStakingProxy(payload) } private suspend fun mapToProxyList(proxies: List): List { @@ -84,4 +88,6 @@ class StakingProxyListViewModel( addAll(proxyRvItems) } } + + private fun ExternalActions.Payload.requireAddress() = type.castOrNull()!!.address!! } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyFragment.kt new file mode 100644 index 0000000000..130a87cd8e --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyFragment.kt @@ -0,0 +1,82 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import io.novafoundation.nova.common.base.BaseFragment +import io.novafoundation.nova.common.di.FeatureUtils +import io.novafoundation.nova.common.mixin.impl.observeValidations +import io.novafoundation.nova.common.utils.applyStatusBarInsets +import io.novafoundation.nova.common.view.setProgress +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.showWallet +import io.novafoundation.nova.feature_account_api.presenatation.actions.setupExternalActions +import io.novafoundation.nova.feature_account_api.view.showAddress +import io.novafoundation.nova.feature_account_api.view.showChain +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_wallet_api.presentation.mixin.fee.setupFeeLoading +import kotlinx.android.synthetic.main.fragment_confirm_revoke_staking_proxy.confirmRemoveStakingProxyButton +import kotlinx.android.synthetic.main.fragment_confirm_revoke_staking_proxy.confirmRemoveStakingProxyDelegationAccount +import kotlinx.android.synthetic.main.fragment_confirm_revoke_staking_proxy.confirmRemoveStakingProxyNetwork +import kotlinx.android.synthetic.main.fragment_confirm_revoke_staking_proxy.confirmRemoveStakingProxyNetworkFee +import kotlinx.android.synthetic.main.fragment_confirm_revoke_staking_proxy.confirmRemoveStakingProxyProxiedAccount +import kotlinx.android.synthetic.main.fragment_confirm_revoke_staking_proxy.confirmRemoveStakingProxyToolbar +import kotlinx.android.synthetic.main.fragment_confirm_revoke_staking_proxy.confirmRemoveStakingProxyWallet + +class ConfirmRemoveStakingProxyFragment : BaseFragment() { + companion object { + + private const val PAYLOAD_KEY = "PAYLOAD_KEY" + + fun getBundle(payload: ConfirmRemoveStakingProxyPayload) = Bundle().apply { + putParcelable(PAYLOAD_KEY, payload) + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_confirm_revoke_staking_proxy, container, false) + } + + override fun initViews() { + confirmRemoveStakingProxyToolbar.applyStatusBarInsets() + + confirmRemoveStakingProxyToolbar.setHomeButtonListener { viewModel.backClicked() } + + confirmRemoveStakingProxyButton.setOnClickListener { viewModel.confirmClicked() } + confirmRemoveStakingProxyButton.prepareForProgress(viewLifecycleOwner) + + confirmRemoveStakingProxyProxiedAccount.setOnClickListener { viewModel.proxiedAccountClicked() } + confirmRemoveStakingProxyDelegationAccount.setOnClickListener { viewModel.proxyAccountClicked() } + } + + override fun inject() { + val payload = argument(PAYLOAD_KEY) + + FeatureUtils.getFeature( + requireContext(), + StakingFeatureApi::class.java + ) + .confirmRevokeStakingProxyFactory() + .create(this, payload) + .inject(this) + } + + override fun subscribe(viewModel: ConfirmRemoveStakingProxyViewModel) { + observeValidations(viewModel) + setupExternalActions(viewModel) + setupFeeLoading(viewModel.feeMixin, confirmRemoveStakingProxyNetworkFee) + + viewModel.chainModel.observe { confirmRemoveStakingProxyNetwork.showChain(it) } + viewModel.walletUiFlow.observe { confirmRemoveStakingProxyWallet.showWallet(it) } + viewModel.proxiedAccountModel.observe { confirmRemoveStakingProxyProxiedAccount.showAddress(it) } + viewModel.proxyAccountModel.observe { confirmRemoveStakingProxyDelegationAccount.showAddress(it) } + + viewModel.validationProgressFlow.observe(confirmRemoveStakingProxyButton::setProgress) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyPayload.kt new file mode 100644 index 0000000000..3fd2f84143 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyPayload.kt @@ -0,0 +1,9 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +class ConfirmRemoveStakingProxyPayload( + val proxyAddress: String +) : Parcelable diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt new file mode 100644 index 0000000000..3f60f2779f --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt @@ -0,0 +1,161 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke + +import io.novafoundation.nova.common.address.AddressIconGenerator +import io.novafoundation.nova.common.base.BaseViewModel +import io.novafoundation.nova.common.mixin.api.Validatable +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.common.validation.progressConsumer +import io.novafoundation.nova.feature_account_api.data.mappers.mapChainToUi +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_account_api.domain.model.requireAddressIn +import io.novafoundation.nova.feature_account_api.presenatation.account.icon.createAccountAddressModel +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.remove.RemoveStakingProxyInteractor +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.remove.RemoveStakingProxyValidationPayload +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.remove.RemoveStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapRemoveStakingProxyValidationFailureToUi +import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.awaitDecimalFee +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.create +import io.novafoundation.nova.runtime.ext.accountIdOf +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState +import io.novafoundation.nova.runtime.state.chain +import io.novafoundation.nova.runtime.state.selectedAssetFlow +import io.novafoundation.nova.runtime.state.selectedChainFlow +import jp.co.soramitsu.fearless_utils.runtime.AccountId +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch + +class ConfirmRemoveStakingProxyViewModel( + private val router: StakingRouter, + private val addressIconGenerator: AddressIconGenerator, + private val payload: ConfirmRemoveStakingProxyPayload, + private val accountRepository: AccountRepository, + private val resourceManager: ResourceManager, + private val externalActions: ExternalActions.Presentation, + private val validationExecutor: ValidationExecutor, + private val selectedAssetState: AnySelectedAssetOptionSharedState, + private val assetUseCase: ArbitraryAssetUseCase, + private val removeStakingProxyValidationSystem: RemoveStakingProxyValidationSystem, + private val walletUiUseCase: WalletUiUseCase, + private val removeStakingProxyInteractor: RemoveStakingProxyInteractor, + private val feeLoaderMixinFactory: FeeLoaderMixin.Factory +) : BaseViewModel(), + Validatable by validationExecutor, + ExternalActions by externalActions { + + private val selectedMetaAccountFlow = accountRepository.selectedMetaAccountFlow() + .shareInBackground() + + private val chainFlow = selectedAssetState.selectedChainFlow() + .shareInBackground() + + @OptIn(ExperimentalCoroutinesApi::class) + private val assetFlow = selectedAssetState.selectedAssetFlow() + .flatMapLatest { assetUseCase.assetFlow(it) } + .shareInBackground() + + val feeMixin: FeeLoaderMixin.Presentation = feeLoaderMixinFactory.create(assetFlow) + + val chainModel = chainFlow.map { chain -> + mapChainToUi(chain) + } + + val walletUiFlow = selectedMetaAccountFlow.map { walletUiUseCase.walletUiFor(it) } + + val proxiedAccountModel = combine(selectedMetaAccountFlow, chainFlow) { metaAccount, chain -> + val address = metaAccount.requireAddressIn(chain) + + generateAccountAddressModel(chain, address) + } + + val proxyAccountModel = chainFlow.map { chain -> + generateAccountAddressModel(chain, payload.proxyAddress) + } + + val validationProgressFlow = MutableStateFlow(false) + + init { + loadFee() + } + + private fun loadFee() { + launch { + val metaAccount = selectedMetaAccountFlow.first() + val chain = selectedAssetState.chain() + val proxiedAccountId = metaAccount.requireAccountIdIn(chain) + + feeMixin.loadFee( + this, + chain.id, + feeConstructor = { removeStakingProxyInteractor.estimateFee(chain, proxiedAccountId) }, + onRetryCancelled = ::backClicked + ) + } + } + + fun backClicked() { + router.back() + } + + fun confirmClicked() = launch { + val metaAccount = accountRepository.getSelectedMetaAccount() + val chain = selectedAssetState.chain() + val validationPayload = RemoveStakingProxyValidationPayload( + chain = chain, + asset = assetFlow.first(), + proxyAddress = payload.proxyAddress, + proxiedAccountId = metaAccount.requireAccountIdIn(chain), + fee = feeMixin.awaitDecimalFee() + ) + + validationExecutor.requireValid( + validationSystem = removeStakingProxyValidationSystem, + payload = validationPayload, + validationFailureTransformer = { mapRemoveStakingProxyValidationFailureToUi(resourceManager, it) }, + progressConsumer = validationProgressFlow.progressConsumer() + ) { + sendTransaction(it.chain, it.proxiedAccountId, it.chain.accountIdOf(it.proxyAddress)) + } + } + + private fun sendTransaction(chain: Chain, proxiedAccount: AccountId, proxyAccount: AccountId) = launch { + val result = removeStakingProxyInteractor.removeProxy(chain, proxiedAccount, proxyAccount) + + validationProgressFlow.value = false + + if (result.isSuccess) { + router.returnToStakingMain() + } + } + + private suspend fun generateAccountAddressModel(chain: Chain, address: String) = addressIconGenerator.createAccountAddressModel( + chain = chain, + address = address, + ) + + fun proxiedAccountClicked() { + launch { + showExternalActions(proxiedAccountModel.first().address) + } + } + + fun proxyAccountClicked() { + showExternalActions(payload.proxyAddress) + } + + private fun showExternalActions(address: String) = launch { + externalActions.showExternalActions(ExternalActions.Type.Address(address), selectedAssetState.chain()) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/di/ConfirmRemoveStakingProxyComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/di/ConfirmRemoveStakingProxyComponent.kt new file mode 100644 index 0000000000..d4a5aab73a --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/di/ConfirmRemoveStakingProxyComponent.kt @@ -0,0 +1,27 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.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.staking.delegation.proxy.revoke.ConfirmRemoveStakingProxyFragment +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.ConfirmRemoveStakingProxyPayload + +@Subcomponent( + modules = [ + ConfirmRemoveStakingProxyModule::class + ] +) +@ScreenScope +interface ConfirmRemoveStakingProxyComponent { + + @Subcomponent.Factory + interface Factory { + fun create( + @BindsInstance fragment: Fragment, + @BindsInstance payload: ConfirmRemoveStakingProxyPayload, + ): ConfirmRemoveStakingProxyComponent + } + + fun inject(fragment: ConfirmRemoveStakingProxyFragment) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/di/ConfirmRemoveStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/di/ConfirmRemoveStakingProxyModule.kt new file mode 100644 index 0000000000..a5fc0ce73b --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/di/ConfirmRemoveStakingProxyModule.kt @@ -0,0 +1,70 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.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.viewmodel.ViewModelKey +import io.novafoundation.nova.common.di.viewmodel.ViewModelModule +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.validation.ValidationExecutor +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase +import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.remove.RemoveStakingProxyInteractor +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.remove.RemoveStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.ConfirmRemoveStakingProxyPayload +import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.revoke.ConfirmRemoveStakingProxyViewModel +import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase +import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin +import io.novafoundation.nova.runtime.state.AnySelectedAssetOptionSharedState + +@Module(includes = [ViewModelModule::class]) +class ConfirmRemoveStakingProxyModule { + @Provides + @IntoMap + @ViewModelKey(ConfirmRemoveStakingProxyViewModel::class) + fun provideViewModule( + router: StakingRouter, + addressIconGenerator: AddressIconGenerator, + payload: ConfirmRemoveStakingProxyPayload, + accountRepository: AccountRepository, + resourceManager: ResourceManager, + externalActions: ExternalActions.Presentation, + validationExecutor: ValidationExecutor, + selectedAssetState: AnySelectedAssetOptionSharedState, + assetUseCase: ArbitraryAssetUseCase, + walletUiUseCase: WalletUiUseCase, + removeStakingProxyInteractor: RemoveStakingProxyInteractor, + removeStakingProxyValidationSystem: RemoveStakingProxyValidationSystem, + feeLoaderMixinFactory: FeeLoaderMixin.Factory + ): ViewModel { + return ConfirmRemoveStakingProxyViewModel( + router = router, + addressIconGenerator = addressIconGenerator, + payload = payload, + accountRepository = accountRepository, + resourceManager = resourceManager, + externalActions = externalActions, + validationExecutor = validationExecutor, + selectedAssetState = selectedAssetState, + assetUseCase = assetUseCase, + walletUiUseCase = walletUiUseCase, + removeStakingProxyInteractor = removeStakingProxyInteractor, + removeStakingProxyValidationSystem = removeStakingProxyValidationSystem, + feeLoaderMixinFactory = feeLoaderMixinFactory + ) + } + + @Provides + fun provideViewModelCreator( + fragment: Fragment, + viewModelFactory: ViewModelProvider.Factory + ): ConfirmRemoveStakingProxyViewModel { + return ViewModelProvider(fragment, viewModelFactory).get(ConfirmRemoveStakingProxyViewModel::class.java) + } +} diff --git a/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml new file mode 100644 index 0000000000..df0cb51ff1 --- /dev/null +++ b/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 8cbca84199712e07cd083a2550be22ce1980c0ed Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 12 Jan 2024 08:53:53 +0100 Subject: [PATCH 16/55] Clean code --- .../ConfirmRemoveStakingProxyViewModel.kt | 46 +++++++++---------- .../fragment_confirm_add_staking_proxy.xml | 1 - .../fragment_confirm_revoke_staking_proxy.xml | 1 - 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt index 3f60f2779f..eb6ac505eb 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt @@ -90,23 +90,18 @@ class ConfirmRemoveStakingProxyViewModel( loadFee() } - private fun loadFee() { - launch { - val metaAccount = selectedMetaAccountFlow.first() - val chain = selectedAssetState.chain() - val proxiedAccountId = metaAccount.requireAccountIdIn(chain) + fun backClicked() { + router.back() + } - feeMixin.loadFee( - this, - chain.id, - feeConstructor = { removeStakingProxyInteractor.estimateFee(chain, proxiedAccountId) }, - onRetryCancelled = ::backClicked - ) + fun proxiedAccountClicked() { + launch { + showExternalActions(proxiedAccountModel.first().address) } } - fun backClicked() { - router.back() + fun proxyAccountClicked() { + showExternalActions(payload.proxyAddress) } fun confirmClicked() = launch { @@ -130,6 +125,21 @@ class ConfirmRemoveStakingProxyViewModel( } } + private fun loadFee() { + launch { + val metaAccount = selectedMetaAccountFlow.first() + val chain = selectedAssetState.chain() + val proxiedAccountId = metaAccount.requireAccountIdIn(chain) + + feeMixin.loadFee( + this, + chain.id, + feeConstructor = { removeStakingProxyInteractor.estimateFee(chain, proxiedAccountId) }, + onRetryCancelled = ::backClicked + ) + } + } + private fun sendTransaction(chain: Chain, proxiedAccount: AccountId, proxyAccount: AccountId) = launch { val result = removeStakingProxyInteractor.removeProxy(chain, proxiedAccount, proxyAccount) @@ -145,16 +155,6 @@ class ConfirmRemoveStakingProxyViewModel( address = address, ) - fun proxiedAccountClicked() { - launch { - showExternalActions(proxiedAccountModel.first().address) - } - } - - fun proxyAccountClicked() { - showExternalActions(payload.proxyAddress) - } - private fun showExternalActions(address: String) = launch { externalActions.showExternalActions(ExternalActions.Type.Address(address), selectedAssetState.chain()) } diff --git a/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml index fc4cadd307..8b07847b0b 100644 --- a/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml +++ b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml @@ -16,7 +16,6 @@ app:titleText="@string/staking_add_proxy_confirmation_title" /> Date: Fri, 12 Jan 2024 08:56:18 +0100 Subject: [PATCH 17/55] Fixed text --- common/src/main/res/values/strings.xml | 1 + .../src/main/res/layout/fragment_confirm_add_staking_proxy.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 1ee47bd036..95bfc0ca7f 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,6 +1,7 @@ + Revoke for Revoke access diff --git a/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml index 8b07847b0b..bfc3d37d80 100644 --- a/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml +++ b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml @@ -93,7 +93,7 @@ android:layout_height="wrap_content" app:dividerVisible="false" app:primaryValueEndIcon="@drawable/ic_info" - app:title="@string/add_proxy_confirmation_delegate_to" /> + app:title="@string/remove_proxy_confirmation_revoke_for" /> From eb6aee9925477e7bfb5db08bc2f838afb8e19d08 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 12 Jan 2024 08:59:10 +0100 Subject: [PATCH 18/55] Fixed text (again) --- common/src/main/res/values/strings.xml | 1 + .../src/main/res/layout/fragment_confirm_add_staking_proxy.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 95bfc0ca7f..7a637cbe36 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,6 +1,7 @@ + Revoke access type Revoke for Revoke access diff --git a/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml index bfc3d37d80..013dbac560 100644 --- a/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml +++ b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml @@ -85,7 +85,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:primaryValue="@string/proxy_access_type_staking_operations" - app:title="@string/add_proxy_confirmation_grant_access_type" /> + app:title="@string/remove_proxy_confirmation_revoke_access_type" /> Date: Fri, 12 Jan 2024 09:07:24 +0100 Subject: [PATCH 19/55] Fixed text (again) --- .../main/res/layout/fragment_confirm_add_staking_proxy.xml | 4 ++-- .../main/res/layout/fragment_confirm_revoke_staking_proxy.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml index 013dbac560..8b07847b0b 100644 --- a/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml +++ b/feature-staking-impl/src/main/res/layout/fragment_confirm_add_staking_proxy.xml @@ -85,7 +85,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:primaryValue="@string/proxy_access_type_staking_operations" - app:title="@string/remove_proxy_confirmation_revoke_access_type" /> + app:title="@string/add_proxy_confirmation_grant_access_type" /> + app:title="@string/add_proxy_confirmation_delegate_to" /> diff --git a/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml index 3168868798..efa48484a1 100644 --- a/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml +++ b/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml @@ -76,7 +76,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:primaryValue="@string/proxy_access_type_staking_operations" - app:title="@string/add_proxy_confirmation_grant_access_type" /> + app:title="@string/remove_proxy_confirmation_revoke_access_type" /> + app:title="@string/remove_proxy_confirmation_revoke_for" /> From 2411a94bd36a19687b08f36ea63cb77b104fa776 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 15 Jan 2024 02:10:13 +0100 Subject: [PATCH 20/55] Fixed pr notes --- .../app/navigation/AccountNavigationModule.kt | 2 +- .../account/SelectAddressCommunicatorImpl.kt | 6 +- .../nova/common/utils/Filters.kt | 2 +- common/src/main/res/values/strings.xml | 6 +- .../di/AccountFeatureApi.kt | 3 + .../domain/filter/MetaAccountFilter.kt | 4 +- .../SelectAddressCommunicator.kt | 4 +- .../mixin/selectAddress/SelectAddressMixin.kt | 34 +++++++++ .../SelectAddressRequestMappingExt.kt | 18 +++++ .../di/AccountFeatureComponent.kt | 2 +- .../di/AccountFeatureHolder.kt | 2 +- .../di/AccountFeatureModule.kt | 15 ++++ .../selectAddress/SelectAddressFragment.kt | 2 +- .../selectAddress/SelectAddressViewModel.kt | 18 ++--- .../di/SelectAddressComponent.kt | 2 +- .../selectAddress/di/SelectAddressModule.kt | 4 +- .../account/mixin/SelectAddressMixin.kt | 72 +++++++++++++++++++ .../di/AssetsFeatureComponent.kt | 2 +- .../di/AssetsFeatureDependencies.kt | 3 + .../feature_assets/di/AssetsFeatureHolder.kt | 2 +- .../send/amount/SelectSendFragment.kt | 7 +- .../send/amount/SelectSendViewModel.kt | 63 +++++++--------- .../send/amount/di/SelectSendModule.kt | 11 +-- .../data/common/ProxyDepositCalculator.kt | 2 +- ...EnoughAmountToPayProxyDepositValidation.kt | 10 ++- .../data/common/RealProxyDepositCalculator.kt | 2 +- .../di/StakingFeatureComponent.kt | 2 +- .../di/StakingFeatureDependencies.kt | 3 + .../di/StakingFeatureHolder.kt | 2 +- .../di/StakingFeatureModule.kt | 8 +-- .../proxy/AddStakingProxyInteractor.kt | 4 +- .../proxy/RealAddStakingProxyInteractor.kt} | 9 ++- .../delegation/proxy/Declarations.kt | 5 +- .../AddProxyValidationFailureHandling.kt | 4 +- .../proxy/set/AddStakingProxyFragment.kt | 6 +- .../proxy/set/AddStakingProxyViewModel.kt | 50 +++++++------ .../proxy/set/di/AddStakingProxyModule.kt | 19 +++-- .../ParachainStakeActionsComponent.kt | 6 -- 38 files changed, 275 insertions(+), 141 deletions(-) rename {feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api => feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api}/domain/filter/MetaAccountFilter.kt (70%) rename feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/{account/wallet/list => mixin/selectAddress}/SelectAddressCommunicator.kt (94%) create mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt create mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt create mode 100644 feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt rename feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt => feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt (84%) rename feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/{data/proxy/RealAddStakingProxyRepository.kt => domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt} (90%) diff --git a/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/AccountNavigationModule.kt b/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/AccountNavigationModule.kt index 3440ff71f3..85c98c2b3e 100644 --- a/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/AccountNavigationModule.kt +++ b/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/AccountNavigationModule.kt @@ -10,7 +10,7 @@ import io.novafoundation.nova.app.root.navigation.account.SelectWalletCommunicat import io.novafoundation.nova.app.root.navigation.pincode.PinCodeTwoFactorVerificationCommunicatorImpl import io.novafoundation.nova.common.di.scope.ApplicationScope import io.novafoundation.nova.common.sequrity.verification.PinCodeTwoFactorVerificationCommunicator -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectWallet.SelectWalletCommunicator import io.novafoundation.nova.feature_account_impl.data.signer.paritySigner.PolkadotVaultVariantSignCommunicator import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/account/SelectAddressCommunicatorImpl.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/account/SelectAddressCommunicatorImpl.kt index b6477ef293..c74f095764 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/account/SelectAddressCommunicatorImpl.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/account/SelectAddressCommunicatorImpl.kt @@ -2,9 +2,9 @@ package io.novafoundation.nova.app.root.navigation.account import io.novafoundation.nova.app.root.navigation.NavStackInterScreenCommunicator import io.novafoundation.nova.app.root.navigation.NavigationHolder -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressResponder +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressResponder import io.novafoundation.nova.feature_account_impl.presentation.account.list.selectAddress.SelectAddressFragment import io.novafoundation.nova.feature_assets.presentation.AssetsRouter diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/Filters.kt b/common/src/main/java/io/novafoundation/nova/common/utils/Filters.kt index 747a8ed664..5eb8661cae 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/Filters.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/Filters.kt @@ -26,7 +26,7 @@ interface OptionsFilter : Filter { val options: List } -class EmptyFilter : Filter { +class EverythingFilter : Filter { override fun shouldInclude(model: T) = true } diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index d6e2f1f682..634b4f6d9c 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,15 +1,15 @@ + Invalid proxy address + Proxy address should be a valid %s address + Proxy deposit The deposit stays reserved on your account until the proxy is removed. Maximum number of proxies has been reached You have reached the limit of %s added proxies in %s. Remove proxies to add new ones. - Invalid address - An address must be a valid for %s - Not enough tokens You don’t have enough balance for proxy deposit of %s. Available balance: %s diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt index 72ca04deb9..2dbd1ee1a7 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/di/AccountFeatureApi.kt @@ -28,6 +28,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.language.Languag import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_account_api.presenatation.mixin.identity.IdentityMixin import io.novafoundation.nova.feature_account_api.presenatation.mixin.importType.ImportTypeChooserMixin +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectWallet.SelectWalletMixin import jp.co.soramitsu.fearless_utils.runtime.extrinsic.signer.SignerPayloadExtrinsic @@ -90,4 +91,6 @@ interface AccountFeatureApi { val selectWalletMixinFactory: SelectWalletMixin.Factory val polkadotVaultVariantConfigProvider: PolkadotVaultVariantConfigProvider + + val selectAddressMixinFactory: SelectAddressMixin.Factory } diff --git a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/filter/MetaAccountFilter.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/MetaAccountFilter.kt similarity index 70% rename from feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/filter/MetaAccountFilter.kt rename to feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/MetaAccountFilter.kt index 5354501f8f..66ae2b888e 100644 --- a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/filter/MetaAccountFilter.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/MetaAccountFilter.kt @@ -1,9 +1,9 @@ -package io.novafoundation.nova.feature_wallet_api.domain.filter +package io.novafoundation.nova.feature_account_api.domain.filter import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -class MetaAccountFilter(private val mode: Mode, private val metaIds: List) : Filter { +class MetaAccountFilter(val mode: Mode, val metaIds: List) : Filter { enum class Mode { INCLUDE, diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/wallet/list/SelectAddressCommunicator.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressCommunicator.kt similarity index 94% rename from feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/wallet/list/SelectAddressCommunicator.kt rename to feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressCommunicator.kt index 410e6bd3b5..87d3357935 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/account/wallet/list/SelectAddressCommunicator.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressCommunicator.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list +package io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress import android.os.Parcelable import io.novafoundation.nova.common.navigation.InterScreenRequester @@ -17,7 +17,7 @@ interface SelectAddressRequester : InterScreenRequester) : Filter diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt new file mode 100644 index 0000000000..c61ccae841 --- /dev/null +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt @@ -0,0 +1,34 @@ +package io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress + +import androidx.core.view.isInvisible +import io.novafoundation.nova.common.base.BaseFragment +import io.novafoundation.nova.common.utils.Filter +import io.novafoundation.nova.common.view.YourWalletsView +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow + +interface SelectAddressMixin { + + class Payload(val chain: Chain, val filter: Filter) + + interface Factory { + + fun create( + coroutineScope: CoroutineScope, + payloadFlow: Flow, + onAddressSelect: (String) -> Unit + ): SelectAddressMixin + } + + val isSelectAddressAvailableFlow: Flow + + suspend fun openSelectAddress(selectedAddress: String?) +} + +fun BaseFragment<*>.setupYourWalletsBtn(view: YourWalletsView, selectAddressMixin: SelectAddressMixin) { + selectAddressMixin.isSelectAddressAvailableFlow.observe { + view.isInvisible = !it + } +} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt new file mode 100644 index 0000000000..37f8ee325c --- /dev/null +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt @@ -0,0 +1,18 @@ +package io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress + +import io.novafoundation.nova.common.utils.EverythingFilter +import io.novafoundation.nova.common.utils.Filter +import io.novafoundation.nova.feature_account_api.domain.filter.MetaAccountFilter +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester + +fun SelectAddressRequester.Request.Filter.toMetaAccountsFilter(): Filter { + return when (this) { + is SelectAddressRequester.Request.Filter.Everything -> EverythingFilter() + + is SelectAddressRequester.Request.Filter.ExcludeMetaIds -> MetaAccountFilter( + MetaAccountFilter.Mode.EXCLUDE, + this.metaIds + ) + } +} diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureComponent.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureComponent.kt index fb2a99047c..5b9bb6a53d 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureComponent.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureComponent.kt @@ -7,7 +7,7 @@ import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.common.sequrity.verification.PinCodeTwoFactorVerificationCommunicator import io.novafoundation.nova.core_db.di.DbApi import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectWallet.SelectWalletCommunicator import io.novafoundation.nova.feature_account_api.presenatation.sign.LedgerSignCommunicator import io.novafoundation.nova.feature_account_impl.data.signer.paritySigner.PolkadotVaultVariantSignCommunicator diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureHolder.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureHolder.kt index 1ad2bf2063..fa69dc6961 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureHolder.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureHolder.kt @@ -5,7 +5,7 @@ import io.novafoundation.nova.common.di.FeatureContainer import io.novafoundation.nova.common.di.scope.ApplicationScope import io.novafoundation.nova.common.sequrity.verification.PinCodeTwoFactorVerificationCommunicator import io.novafoundation.nova.core_db.di.DbApi -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectWallet.SelectWalletCommunicator import io.novafoundation.nova.feature_account_api.presenatation.sign.LedgerSignCommunicator import io.novafoundation.nova.feature_account_impl.data.signer.paritySigner.PolkadotVaultVariantSignCommunicator diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt index 51ced342a1..0178b1d6c5 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt @@ -73,6 +73,8 @@ import io.novafoundation.nova.feature_account_impl.domain.account.advancedEncryp import io.novafoundation.nova.feature_account_api.domain.account.common.EncryptionDefaults import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.account.identity.OnChainIdentity +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin import io.novafoundation.nova.feature_account_impl.data.proxy.RealMetaAccountsUpdatesRegistry import io.novafoundation.nova.feature_account_impl.data.proxy.RealProxySyncService import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.JsonAddAccountRepository @@ -85,6 +87,7 @@ import io.novafoundation.nova.feature_account_impl.presentation.account.common.l import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountTypePresentationMapper import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountWithBalanceListingMixinFactory import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.ProxyFormatter +import io.novafoundation.nova.feature_account_impl.presentation.account.mixin.SelectAddressMixinFactory import io.novafoundation.nova.feature_account_impl.presentation.account.wallet.WalletUiUseCaseImpl import io.novafoundation.nova.feature_account_impl.presentation.common.mixin.addAccountChooser.AddAccountLauncherMixin import io.novafoundation.nova.feature_account_impl.presentation.common.mixin.addAccountChooser.AddAccountLauncherProvider @@ -498,4 +501,16 @@ class AccountFeatureModule { proxiedAddAccountRepository, rootScope ) + + @Provides + @FeatureScope + fun provideSelectAddressMixinFactory( + selectAddressCommunicator: SelectAddressCommunicator, + metaAccountGroupingInteractor: MetaAccountGroupingInteractor, + ): SelectAddressMixin.Factory { + return SelectAddressMixinFactory( + selectAddressCommunicator, + metaAccountGroupingInteractor + ) + } } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressFragment.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressFragment.kt index 1894942e89..c229745fed 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressFragment.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressFragment.kt @@ -3,7 +3,7 @@ package io.novafoundation.nova.feature_account_impl.presentation.account.list.se import android.os.Bundle import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester import io.novafoundation.nova.feature_account_impl.R import io.novafoundation.nova.feature_account_impl.di.AccountFeatureComponent import io.novafoundation.nova.feature_account_impl.presentation.account.list.WalletListFragment diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressViewModel.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressViewModel.kt index 39f2882644..5ae194fd6d 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressViewModel.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/SelectAddressViewModel.kt @@ -1,17 +1,14 @@ package io.novafoundation.nova.feature_account_impl.presentation.account.list.selectAddress -import io.novafoundation.nova.common.utils.EmptyFilter -import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInteractor -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.presenatation.account.listing.items.AccountUi import io.novafoundation.nova.feature_account_api.presenatation.account.listing.holders.AccountHolder -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester.Request -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressResponder +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester.Request +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressResponder import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountValidForTransactionListingMixinFactory import io.novafoundation.nova.feature_account_impl.presentation.account.list.WalletListViewModel -import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.toMetaAccountsFilter import kotlinx.coroutines.launch class SelectAddressViewModel( @@ -26,7 +23,7 @@ class SelectAddressViewModel( this, request.chainId, request.selectedAddress, - mapFilter(request.filter) + request.filter.toMetaAccountsFilter() ) override val mode: AccountHolder.Mode = AccountHolder.Mode.SWITCH @@ -40,11 +37,4 @@ class SelectAddressViewModel( } } } - - private fun mapFilter(filter: Request.Filter): Filter { - return when (filter) { - Request.Filter.Empty -> EmptyFilter() - is Request.Filter.ExcludeMetaIds -> MetaAccountFilter(MetaAccountFilter.Mode.EXCLUDE, filter.metaIds) - } - } } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressComponent.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressComponent.kt index 7bb85348b1..9a5d5521ff 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressComponent.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressComponent.kt @@ -4,7 +4,7 @@ import androidx.fragment.app.Fragment import dagger.BindsInstance import dagger.Subcomponent import io.novafoundation.nova.common.di.scope.ScreenScope -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester import io.novafoundation.nova.feature_account_impl.presentation.account.list.selectAddress.SelectAddressFragment @Subcomponent( diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressModule.kt index 5d1aa851e8..a016f1c55f 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/list/selectAddress/di/SelectAddressModule.kt @@ -12,8 +12,8 @@ import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountTypePresentationMapper import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.MetaAccountValidForTransactionListingMixinFactory diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt new file mode 100644 index 0000000000..c9c4ffe48e --- /dev/null +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt @@ -0,0 +1,72 @@ +package io.novafoundation.nova.feature_account_impl.presentation.account.mixin + +import io.novafoundation.nova.common.address.intoKey +import io.novafoundation.nova.common.utils.Filter +import io.novafoundation.nova.feature_account_api.domain.filter.MetaAccountFilter +import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount +import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach + +class SelectAddressMixinFactory( + private val selectAddressRequester: SelectAddressRequester, + private val metaAccountGroupingInteractor: MetaAccountGroupingInteractor, +) : SelectAddressMixin.Factory { + + override fun create( + coroutineScope: CoroutineScope, + payloadFlow: Flow, + onAddressSelect: (String) -> Unit + ): SelectAddressMixin { + return RealSelectAddressMixin( + coroutineScope, + selectAddressRequester, + payloadFlow, + metaAccountGroupingInteractor, + onAddressSelect + ) + } +} + +class RealSelectAddressMixin( + private val coroutineScope: CoroutineScope, + private val selectAddressRequester: SelectAddressRequester, + private val payloadFlow: Flow, + private val metaAccountGroupingInteractor: MetaAccountGroupingInteractor, + private val onAddressSelect: (String) -> Unit +) : SelectAddressMixin { + + init { + selectAddressRequester.responseFlow + .onEach { onAddressSelect(it.selectedAddress) } + .launchIn(coroutineScope) + } + + override val isSelectAddressAvailableFlow: Flow = payloadFlow.map { payload -> + metaAccountGroupingInteractor.hasAvailableMetaAccountsForChain(payload.chain.id, payload.filter) + } + + override suspend fun openSelectAddress(selectedAddress: String?) { + val payload = payloadFlow.first() + val metaAccountFilter = getMetaAccountsFilterPayload(payload.filter) + val request = SelectAddressRequester.Request(payload.chain.id, selectedAddress, metaAccountFilter) + selectAddressRequester.openRequest(request) + } + + private suspend fun getMetaAccountsFilterPayload(filter: Filter): SelectAddressRequester.Request.Filter { + return if (filter is MetaAccountFilter && filter.mode == MetaAccountFilter.Mode.EXCLUDE) { + SelectAddressRequester.Request.Filter.ExcludeMetaIds(filter.metaIds) + } else { + SelectAddressRequester.Request.Filter.Everything + } + } +} diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureComponent.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureComponent.kt index 76932584b2..a401b17e45 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureComponent.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureComponent.kt @@ -6,7 +6,7 @@ import io.novafoundation.nova.common.di.CommonApi import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.core_db.di.DbApi import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_assets.presentation.AssetsRouter import io.novafoundation.nova.feature_assets.presentation.balance.detail.di.BalanceDetailComponent import io.novafoundation.nova.feature_assets.presentation.balance.filters.di.AssetFiltersComponent diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureDependencies.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureDependencies.kt index b056cc67c5..cdaf025959 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureDependencies.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureDependencies.kt @@ -33,6 +33,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.W import io.novafoundation.nova.feature_account_api.presenatation.account.watchOnly.WatchOnlyMissingKeysPresenter import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin import io.novafoundation.nova.feature_buy_api.presentation.mixin.BuyMixin import io.novafoundation.nova.feature_buy_api.presentation.mixin.BuyMixinUi import io.novafoundation.nova.feature_crowdloan_api.data.repository.ContributionsRepository @@ -235,4 +236,6 @@ interface AssetsFeatureDependencies { val swapRateFormatter: SwapRateFormatter val bottomSheetLauncher: DescriptionBottomSheetLauncher + + val selectAddressMixinFactory: SelectAddressMixin.Factory } diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureHolder.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureHolder.kt index 79e375ab78..d5cef28fc6 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureHolder.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/di/AssetsFeatureHolder.kt @@ -5,7 +5,7 @@ import io.novafoundation.nova.common.di.FeatureContainer import io.novafoundation.nova.common.di.scope.ApplicationScope import io.novafoundation.nova.core_db.di.DbApi import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_assets.presentation.AssetsRouter import io.novafoundation.nova.feature_buy_api.di.BuyFeatureApi import io.novafoundation.nova.feature_crowdloan_api.di.CrowdloanFeatureApi diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendFragment.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendFragment.kt index 6138ef9bb3..506710e212 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendFragment.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendFragment.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.os.bundleOf -import androidx.core.view.isInvisible import io.novafoundation.nova.common.base.BaseFragment import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.common.mixin.impl.observeValidations @@ -16,6 +15,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInp import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.removeInputKeyboardCallback import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.setupAddressInput import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.setupExternalAccounts +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.setupYourWalletsBtn import io.novafoundation.nova.feature_assets.R import io.novafoundation.nova.feature_assets.di.AssetsFeatureApi import io.novafoundation.nova.feature_assets.di.AssetsFeatureComponent @@ -91,6 +91,7 @@ class SelectSendFragment : BaseFragment() { setupAmountChooser(viewModel.amountChooserMixin, selectSendAmount) setupAddressInput(viewModel.addressInputMixin, selectSendRecipient) setupExternalAccounts(viewModel.addressInputMixin, selectSendRecipient) + setupYourWalletsBtn(selectWallet, viewModel.selectAddressMixin) viewModel.chooseDestinationChain.awaitableActionLiveData.observeEvent { removeInputKeyboardCallback(selectSendRecipient) @@ -104,10 +105,6 @@ class SelectSendFragment : BaseFragment() { crossChainDestinationBottomSheet.show() } - viewModel.isSelectAddressAvailable.observe { - selectWallet.isInvisible = !it - } - viewModel.transferDirectionModel.observe { selectSendOriginChain.setModel(it.originChip) selectSendFromTitle.text = it.originChainLabel diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt index 4fd485a389..d0b1890898 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt @@ -7,7 +7,7 @@ import io.novafoundation.nova.common.list.headers.TextHeader import io.novafoundation.nova.common.mixin.actionAwaitable.ActionAwaitableMixin import io.novafoundation.nova.common.mixin.api.Validatable import io.novafoundation.nova.common.resources.ResourceManager -import io.novafoundation.nova.common.utils.EmptyFilter +import io.novafoundation.nova.common.utils.EverythingFilter import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.common.utils.inBackground import io.novafoundation.nova.common.utils.mapList @@ -17,15 +17,18 @@ import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.ButtonState import io.novafoundation.nova.feature_account_api.data.mappers.mapChainToUi import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_account_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.toMetaAccountsFilter import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin import io.novafoundation.nova.feature_account_api.view.ChainChipModel import io.novafoundation.nova.feature_assets.R import io.novafoundation.nova.feature_assets.domain.WalletInteractor @@ -41,7 +44,6 @@ import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.t import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.AssetTransferPayload import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.BaseAssetTransfer import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.assets.tranfers.WeightedAssetTransfer -import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_wallet_api.domain.interfaces.CrossChainTransfersUseCase import io.novafoundation.nova.feature_wallet_api.domain.model.Asset import io.novafoundation.nova.feature_wallet_api.domain.model.Token @@ -82,7 +84,6 @@ class SelectSendViewModel( private val initialRecipientAddress: String?, private val validationExecutor: ValidationExecutor, private val resourceManager: ResourceManager, - private val selectAddressRequester: SelectAddressRequester, private val externalActions: ExternalActions.Presentation, private val crossChainTransfersUseCase: CrossChainTransfersUseCase, private val accountRepository: AccountRepository, @@ -91,6 +92,7 @@ class SelectSendViewModel( selectedAccountUseCase: SelectedAccountUseCase, addressInputMixinFactory: AddressInputMixinFactory, amountChooserMixinFactory: AmountChooserMixin.Factory, + selectAddressMixinFactory: SelectAddressMixin.Factory ) : BaseViewModel(), Validatable by validationExecutor, ExternalActions by externalActions { @@ -104,6 +106,18 @@ class SelectSendViewModel( private val destinationAsset = destinationChainWithAsset.map { it.asset } private val destinationChain = destinationChainWithAsset.map { it.chain } + private val selectAddressPayloadFlow = combine( + originChain, + destinationChain + ) { origin, destination -> + SelectAddressMixin.Payload( + chain = destination, + filter = getMetaAccountsFilter(origin, destination) + ) + } + + val selectAddressMixin = selectAddressMixinFactory.create(this, selectAddressPayloadFlow, ::onAddressSelect) + val addressInputMixin = with(addressInputMixinFactory) { val destinationChain = destinationChainWithAsset.map { it.chain } val inputSpec = singleChainInputSpec(destinationChain) @@ -126,12 +140,6 @@ class SelectSendViewModel( .onStart { emit(emptyList()) } .shareInBackground() - val isSelectAddressAvailable = combine(originChain, destinationChain) { originChain, destinationChain -> - val metaAccountFilter = getMetaAccountsFilter(originChain, destinationChain) - metaAccountGroupingInteractor.hasAvailableMetaAccountsForChain(destinationChain.id, metaAccountFilter) - } - .shareInBackground() - val transferDirectionModel = combine( availableCrossChainDestinations, originChainWithAsset, @@ -177,8 +185,6 @@ class SelectSendViewModel( init { subscribeOnChangeDestination() - subscribeOnSelectAddress() - setInitialState() setupFees() @@ -249,11 +255,7 @@ class SelectSendViewModel( fun selectRecipientWallet() { launch { val selectedAddress = addressInputMixin.inputFlow.value - val originChain = originChain.first() - val destinationChain = destinationChain.first() - val filter = getMetaAccountsFilterPayload(originChain, destinationChain) - val request = SelectAddressRequester.Request(destinationChain.id, selectedAddress, filter) - selectAddressRequester.openRequest(request) + selectAddressMixin.openSelectAddress(selectedAddress) } } @@ -270,12 +272,8 @@ class SelectSendViewModel( .launchIn(this) } - private fun subscribeOnSelectAddress() { - selectAddressRequester.responseFlow - .onEach { - addressInputMixin.inputFlow.value = it.selectedAddress - } - .launchIn(this) + private fun onAddressSelect(address: String) { + addressInputMixin.inputFlow.value = address } private fun setInitialState() = launch { @@ -504,29 +502,20 @@ class SelectSendViewModel( } } - private suspend fun getMetaAccountsFilterPayload(origin: Chain, desination: Chain): SelectAddressRequester.Request.Filter { + private suspend fun getMetaAccountsFilter(origin: Chain, desination: Chain): Filter { val isCrossChain = origin.id != desination.id + return if (isCrossChain) { - SelectAddressRequester.Request.Filter.Empty + EverythingFilter() } else { val destinationAccountId = selectedAccount.first().requireAccountIdIn(desination) val notOriginMetaAccounts = accountRepository.activeMetaAccounts() .filter { it.accountIdIn(origin)?.intoKey() == destinationAccountId.intoKey() } .map { it.id } - SelectAddressRequester.Request.Filter.ExcludeMetaIds(notOriginMetaAccounts) - } - } - - private suspend fun getMetaAccountsFilter(origin: Chain, desination: Chain): Filter { - val filterPayload = getMetaAccountsFilterPayload(origin, desination) - - return when (filterPayload) { - is SelectAddressRequester.Request.Filter.Empty -> EmptyFilter() - - is SelectAddressRequester.Request.Filter.ExcludeMetaIds -> MetaAccountFilter( + MetaAccountFilter( MetaAccountFilter.Mode.EXCLUDE, - filterPayload.metaIds + notOriginMetaAccounts ) } } diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt index 091d9ac9ad..68d5b315d7 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt @@ -14,9 +14,10 @@ import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin import io.novafoundation.nova.feature_assets.domain.WalletInteractor import io.novafoundation.nova.feature_assets.domain.send.SendInteractor import io.novafoundation.nova.feature_assets.presentation.AssetsRouter @@ -43,7 +44,6 @@ class SelectSendModule { initialRecipientAddress: String?, validationExecutor: ValidationExecutor, resourceManager: ResourceManager, - selectAddressRequester: SelectAddressCommunicator, externalActions: ExternalActions.Presentation, crossChainTransfersUseCase: CrossChainTransfersUseCase, actionAwaitableMixinFactory: ActionAwaitableMixin.Factory, @@ -51,7 +51,8 @@ class SelectSendModule { selectedAccountUseCase: SelectedAccountUseCase, addressInputMixinFactory: AddressInputMixinFactory, amountChooserMixinFactory: AmountChooserMixin.Factory, - accountRepository: AccountRepository + accountRepository: AccountRepository, + selectAddressMixinFactory: SelectAddressMixin.Factory ): ViewModel { return SelectSendViewModel( chainRegistry = chainRegistry, @@ -63,7 +64,6 @@ class SelectSendModule { initialRecipientAddress = initialRecipientAddress, validationExecutor = validationExecutor, resourceManager = resourceManager, - selectAddressRequester = selectAddressRequester, externalActions = externalActions, crossChainTransfersUseCase = crossChainTransfersUseCase, actionAwaitableMixinFactory = actionAwaitableMixinFactory, @@ -71,7 +71,8 @@ class SelectSendModule { selectedAccountUseCase = selectedAccountUseCase, addressInputMixinFactory = addressInputMixinFactory, amountChooserMixinFactory = amountChooserMixinFactory, - accountRepository = accountRepository + accountRepository = accountRepository, + selectAddressMixinFactory = selectAddressMixinFactory ) } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt index cc00a7be8b..02830fa441 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt @@ -12,5 +12,5 @@ interface ProxyDepositCalculator { suspend fun getDepositConstants(chain: Chain): DepositBaseAndFactor - fun calculateProxyDeposit(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger + fun calculateProxyDepositForQuantity(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt index a942b4f598..25582b7043 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt @@ -15,6 +15,7 @@ class EnoughAmountToPayProxyDepositValidation( private val accountId: (P) -> AccountId, private val newDeposit: (P) -> BigInteger, private val availableBalance: (P) -> BigInteger, + private val feeReceiver: (P) -> BigInteger, private val error: (P, BigInteger) -> E, private val proxyRepository: GetProxyRepository ) : Validation { @@ -24,8 +25,9 @@ class EnoughAmountToPayProxyDepositValidation( val currentDeposit = proxyRepository.getProxyDeposit(chain(value).id, accountId(value)) val deltaDeposit = (newDeposit(value) - currentDeposit).atLeastZero() + val fee = feeReceiver(value) - return validOrError(deltaDeposit <= availableBalance) { + return validOrError(deltaDeposit + fee <= availableBalance) { error(value, availableBalance) } } @@ -37,7 +39,8 @@ fun ValidationSystemBuilder.enoughBalanceToPayProxyDeposit( newDeposit: (P) -> BigInteger, availableBalance: (P) -> BigInteger, error: (P, BigInteger) -> E, - proxyRepository: GetProxyRepository + proxyRepository: GetProxyRepository, + feeReceiver: (P) -> BigInteger, ) { validate( EnoughAmountToPayProxyDepositValidation( @@ -46,7 +49,8 @@ fun ValidationSystemBuilder.enoughBalanceToPayProxyDeposit( newDeposit = newDeposit, availableBalance = availableBalance, error = error, - proxyRepository = proxyRepository + proxyRepository = proxyRepository, + feeReceiver = feeReceiver, ) ) } diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt index 275d33e15b..824b1fb246 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt @@ -22,7 +22,7 @@ class RealProxyDepositCalculator( ) } - override fun calculateProxyDeposit(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger { + override fun calculateProxyDepositForQuantity(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger { return if (proxiesCount == 0) { BigInteger.ZERO } else { 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 e3ee126a43..59bfcb3d19 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 @@ -6,7 +6,7 @@ import io.novafoundation.nova.common.di.CommonApi import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.core_db.di.DbApi import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_dapp_api.di.DAppFeatureApi import io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt index 74eee825dd..3061a92cfe 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt @@ -34,6 +34,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.W import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_account_api.presenatation.mixin.identity.IdentityMixin +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin import io.novafoundation.nova.feature_dapp_api.data.repository.DAppMetadataRepository import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository @@ -178,4 +179,6 @@ interface StakingFeatureDependencies { val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher val metaAccountGroupingInteractor: MetaAccountGroupingInteractor + + val selectAddressMixinFactory: SelectAddressMixin.Factory } 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 048ed2f867..6bcf63234e 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 @@ -5,7 +5,7 @@ import io.novafoundation.nova.common.di.FeatureContainer import io.novafoundation.nova.common.di.scope.ApplicationScope import io.novafoundation.nova.core_db.di.DbApi import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_dapp_api.di.DAppFeatureApi import io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi import io.novafoundation.nova.feature_staking_impl.presentation.NominationPoolsRouter diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt index 1d9b199487..7bd7b617ad 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt @@ -23,7 +23,7 @@ import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculat import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_staking_api.data.network.blockhain.updaters.PooledBalanceUpdaterFactory import io.novafoundation.nova.feature_staking_api.data.nominationPools.pool.PoolAccountDerivation -import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.AddStakingProxyInteractor import io.novafoundation.nova.feature_staking_api.domain.api.StakingRepository import io.novafoundation.nova.feature_staking_api.presentation.nominationPools.display.PoolDisplayUseCase import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState @@ -33,7 +33,7 @@ import io.novafoundation.nova.feature_staking_impl.data.network.subquery.SubQuer import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network.blockhain.updater.RealPooledBalanceUpdaterFactory import io.novafoundation.nova.feature_staking_impl.data.nominationPools.repository.NominationPoolStateRepository import io.novafoundation.nova.feature_staking_impl.data.parachainStaking.RoundDurationEstimator -import io.novafoundation.nova.feature_staking_impl.data.proxy.RealAddStakingProxyRepository +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.RealAddStakingProxyInteractor import io.novafoundation.nova.feature_staking_impl.data.repository.BagListRepository import io.novafoundation.nova.feature_staking_impl.data.repository.LocalBagListRepository import io.novafoundation.nova.feature_staking_impl.data.repository.ParasRepository @@ -613,8 +613,8 @@ class StakingFeatureModule { extrinsicService: ExtrinsicService, proxyDepositCalculator: ProxyDepositCalculator, getProxyRepository: GetProxyRepository - ): AddStakingProxyRepository { - return RealAddStakingProxyRepository( + ): AddStakingProxyInteractor { + return RealAddStakingProxyInteractor( extrinsicService, proxyDepositCalculator, getProxyRepository diff --git a/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt similarity index 84% rename from feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt index ac29f6ef73..32bde7ffa4 100644 --- a/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/data/proxy/AddStakingProxyRepository.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_api.data.proxy +package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.model.Fee @@ -6,7 +6,7 @@ import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQua import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId -interface AddStakingProxyRepository { +interface AddStakingProxyInteractor { suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt similarity index 90% rename from feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt rename to feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt index 2db497ab2f..2e0c1ba67c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/proxy/RealAddStakingProxyRepository.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt @@ -1,4 +1,4 @@ -package io.novafoundation.nova.feature_staking_impl.data.proxy +package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.intoOrigin import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService @@ -6,7 +6,6 @@ import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmis import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_proxy_api.data.calls.addProxyCall import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator -import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType @@ -16,11 +15,11 @@ import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -class RealAddStakingProxyRepository( +class RealAddStakingProxyInteractor( private val extrinsicService: ExtrinsicService, private val proxyDepositCalculator: ProxyDepositCalculator, private val getProxyRepository: GetProxyRepository -) : AddStakingProxyRepository { +) : AddStakingProxyInteractor { override suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee { return withContext(Dispatchers.IO) { @@ -42,7 +41,7 @@ class RealAddStakingProxyRepository( val depositConstants = proxyDepositCalculator.getDepositConstants(chain) val currentProxiesCount = getProxyRepository.getProxiesQuantity(chain.id, accountId) val newQuantity = currentProxiesCount + 1 - val deposit = proxyDepositCalculator.calculateProxyDeposit(depositConstants, newQuantity) + val deposit = proxyDepositCalculator.calculateProxyDepositForQuantity(depositConstants, newQuantity) return ProxyDepositWithQuantity(deposit, newQuantity) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt index 9ffef01ae5..0521b91ecf 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt @@ -70,7 +70,7 @@ fun AddStakingProxyValidationSystemBuilder.enoughBalanceToPayDeposit( chain = { it.chain }, accountId = { it.proxiedAccountId }, newDeposit = { it.depositWithQuantity.deposit }, - availableBalance = { it.asset.freeInPlanks }, + availableBalance = { it.asset.freeInPlanks - it.asset.frozenInPlanks }, error = { payload, maxUsable -> AddStakingProxyValidationFailure.NotEnoughBalanceToReserveDeposit( chainAsset = payload.asset.token.configuration, @@ -78,5 +78,6 @@ fun AddStakingProxyValidationSystemBuilder.enoughBalanceToPayDeposit( deposit = payload.depositWithQuantity.deposit ) }, - proxyRepository = proxyRepository + proxyRepository = proxyRepository, + feeReceiver = { it.fee.networkFee.amount } ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt index f7641f6bb2..cf4a5c2d2e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt @@ -25,8 +25,8 @@ fun mapAddStakingProxyValidationFailureToUi( failure.availableBalance.formatPlanks(failure.chainAsset) ) - is InvalidAddress -> resourceManager.getString(R.string.common_invalid_address_title) to - resourceManager.getString(R.string.common_invalid_address_message, failure.chain.name) + is InvalidAddress -> resourceManager.getString(R.string.invalid_proxy_address_title) to + resourceManager.getString(R.string.invalid_proxy_address_message, failure.chain.name) is MaximumProxiesReached -> resourceManager.getString(R.string.add_proxy_maximum_reached_error_title) to resourceManager.getString(R.string.add_proxy_maximum_reached_error_message, failure.max, failure.chain.name) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt index 134c74e30f..94dec98e5e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt @@ -14,6 +14,7 @@ import io.novafoundation.nova.common.view.setState import io.novafoundation.nova.feature_account_api.presenatation.actions.setupExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.setupAddressInput import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.setupExternalAccounts +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.setupYourWalletsBtn 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 @@ -63,15 +64,12 @@ class AddStakingProxyFragment : BaseFragment() { setupAddressInput(viewModel.addressInputMixin, setStakingProxyAddress) setupExternalAccounts(viewModel.addressInputMixin, setStakingProxyAddress) + setupYourWalletsBtn(addStakingProxySelectWallet, viewModel.selectAddressMixin) viewModel.titleFlow.observe { addStakingProxyTitle.text = it } - viewModel.isSelectAddressAvailable.observe { - addStakingProxySelectWallet.isInvisible = !it - } - viewModel.proxyDepositModel.observe { addStakingProxyDeposit.showAmount(it) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt index 55c51c6ec1..74abd29f41 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt @@ -9,22 +9,24 @@ import io.novafoundation.nova.common.utils.flowOf import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher +import io.novafoundation.nova.feature_account_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressRequester +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity -import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.AddStakingProxyInteractor import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationPayload import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase -import io.novafoundation.nova.feature_wallet_api.domain.filter.MetaAccountFilter import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.awaitDecimalFee import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.create @@ -58,12 +60,13 @@ class AddStakingProxyViewModel( private val accountRepository: AccountRepository, private val assetUseCase: ArbitraryAssetUseCase, private val resourceManager: ResourceManager, - private val selectAddressRequester: SelectAddressRequester, - private val addStakingProxyRepository: AddStakingProxyRepository, + private val addStakingProxyInteractor: AddStakingProxyInteractor, private val validationExecutor: ValidationExecutor, private val addStakingProxyValidationSystem: AddStakingProxyValidationSystem, private val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, private val metaAccountGroupingInteractor: MetaAccountGroupingInteractor, + private val stakingRouter: StakingRouter, + private val selectAddressMixinFactory: SelectAddressMixin.Factory ) : BaseViewModel(), DescriptionBottomSheetLauncher by descriptionBottomSheetLauncher, ExternalActions by externalActions, @@ -79,6 +82,15 @@ class AddStakingProxyViewModel( .flatMapLatest { assetUseCase.assetFlow(it) } .shareInBackground() + private val selectAddressPayloadFlow = flowOf { + val selectedMetaAccount = accountRepository.getSelectedMetaAccount() + val chain = selectedAssetState.chain() + val filter = metaAccountsFilter(chain, selectedMetaAccount.requireAccountIdIn(chain)) + SelectAddressMixin.Payload(chain, filter) + } + + val selectAddressMixin = selectAddressMixinFactory.create(this, selectAddressPayloadFlow, ::onAddressSelect) + val titleFlow = selectedAssetFlow.map { resourceManager.getString(R.string.fragment_set_staking_proxy_title, it.token.configuration.symbol) } @@ -113,7 +125,7 @@ class AddStakingProxyViewModel( val metaAccount = accountRepository.getSelectedMetaAccount() val chain = selectedAssetState.chain() val accountId = metaAccount.requireAccountIdIn(chain) - addStakingProxyRepository.calculateDepositForAddProxy(chain, accountId) + addStakingProxyInteractor.calculateDepositForAddProxy(chain, accountId) } .shareInBackground() @@ -141,8 +153,10 @@ class AddStakingProxyViewModel( init { runFeeUpdate() + } - subscribeOnSelectAddress() + fun backClicked() { + stakingRouter.back() } fun showProxyDepositDescription() { @@ -154,13 +168,8 @@ class AddStakingProxyViewModel( fun selectAuthorityWallet() { launch { - val metaAccount = accountRepository.getSelectedMetaAccount() - val chain = selectedAssetState.chain() - val proxiedAccountId = metaAccount.requireAccountIdIn(chain) val selectedAddress = addressInputMixin.inputFlow.value - val filter = getMetaAccountsFilterPayload(chain, proxiedAccountId) - val request = SelectAddressRequester.Request(chain.id, selectedAddress, filter) - selectAddressRequester.openRequest(request) + selectAddressMixin.openSelectAddress(selectedAddress) } } @@ -189,12 +198,8 @@ class AddStakingProxyViewModel( private fun openConfirmScreen() { } - private fun subscribeOnSelectAddress() { - selectAddressRequester.responseFlow - .onEach { - addressInputMixin.inputFlow.value = it.selectedAddress - } - .launchIn(this) + private fun onAddressSelect(address: String) { + addressInputMixin.inputFlow.value = address } private fun runFeeUpdate() { @@ -204,7 +209,7 @@ class AddStakingProxyViewModel( feeMixin.loadFee( coroutineScope = this, - feeConstructor = { addStakingProxyRepository.estimateFee(chain, metaAccount.requireAccountIdIn(chain)) }, + feeConstructor = { addStakingProxyInteractor.estimateFee(chain, metaAccount.requireAccountIdIn(chain)) }, onRetryCancelled = {} ) }.launchIn(this) @@ -228,6 +233,9 @@ class AddStakingProxyViewModel( private suspend fun metaAccountsFilter(chain: Chain, accountId: AccountId): MetaAccountFilter { val metaAccountsFilterPayload = getMetaAccountsFilterPayload(chain, accountId) - return MetaAccountFilter(MetaAccountFilter.Mode.EXCLUDE, metaAccountsFilterPayload.metaIds) + return MetaAccountFilter( + MetaAccountFilter.Mode.EXCLUDE, + metaAccountsFilterPayload.metaIds + ) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt index 3705c9c04d..7ea90ddcca 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/di/AddStakingProxyModule.kt @@ -13,12 +13,14 @@ import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor -import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.list.SelectAddressCommunicator +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory -import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.AddStakingProxyInteractor import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem +import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.set.AddStakingProxyViewModel import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin @@ -40,11 +42,13 @@ class AddStakingProxyModule { assetUseCase: ArbitraryAssetUseCase, resourceManager: ResourceManager, selectAddressCommunicator: SelectAddressCommunicator, - addStakingProxyRepository: AddStakingProxyRepository, + addStakingProxyInteractor: AddStakingProxyInteractor, validationExecutor: ValidationExecutor, addStakingProxyValidationSystem: AddStakingProxyValidationSystem, descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, - metaAccountGroupingInteractor: MetaAccountGroupingInteractor + metaAccountGroupingInteractor: MetaAccountGroupingInteractor, + stakingRouter: StakingRouter, + selectAddressMixinFactory: SelectAddressMixin.Factory ): ViewModel { return AddStakingProxyViewModel( addressInputMixinFactory = addressInputMixinFactory, @@ -55,12 +59,13 @@ class AddStakingProxyModule { accountRepository = accountRepository, assetUseCase = assetUseCase, resourceManager = resourceManager, - selectAddressRequester = selectAddressCommunicator, - addStakingProxyRepository = addStakingProxyRepository, + addStakingProxyInteractor = addStakingProxyInteractor, validationExecutor = validationExecutor, addStakingProxyValidationSystem = addStakingProxyValidationSystem, descriptionBottomSheetLauncher = descriptionBottomSheetLauncher, - metaAccountGroupingInteractor = metaAccountGroupingInteractor + metaAccountGroupingInteractor = metaAccountGroupingInteractor, + stakingRouter = stakingRouter, + selectAddressMixinFactory = selectAddressMixinFactory ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt index 794149a6b8..f5166cf889 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt @@ -98,8 +98,6 @@ internal open class ParachainStakeActionsComponent( SYSTEM_MANAGE_VALIDATORS -> router.openCurrentCollators() SYSTEM_MANAGE_STAKING_BOND_MORE -> router.openStartStaking(StartParachainStakingMode.BOND_MORE) SYSTEM_MANAGE_STAKING_UNBOND -> openUnbondIfValid() - SYSTEM_ADD_PROXY -> router.openAddStakingProxy() - SYSTEM_MANAGE_PROXIES -> TODO() } } @@ -117,10 +115,6 @@ internal open class ParachainStakeActionsComponent( val collatorsCount = delegatorState.delegations.size.format() add(ManageStakeAction.collators(resourceManager, collatorsCount)) - - if (stakingOption.chain.supportProxy) { - add(ManageStakeAction.addStakingProxy(resourceManager)) // TODO: handle case when proxy is already set - } } private fun openUnbondIfValid() = launch { From 42afefc3497c5dd1d5c8782ca06bc1f7873d631d Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 15 Jan 2024 02:22:28 +0100 Subject: [PATCH 21/55] Fixed filter mapping --- .../domain/filter/MetaAccountFilter.kt | 19 ----------------- .../SelectAddressAccountFilter.kt | 21 +++++++++++++++++++ .../mixin/selectAddress/SelectAddressMixin.kt | 3 ++- .../SelectAddressRequestMappingExt.kt | 21 ++++++++++++------- .../account/mixin/SelectAddressMixin.kt | 17 +++------------ .../send/amount/SelectSendViewModel.kt | 11 ++++------ .../send/amount/di/SelectSendModule.kt | 1 - .../proxy/set/AddStakingProxyFragment.kt | 1 - .../proxy/set/AddStakingProxyViewModel.kt | 7 +++---- .../ParachainStakeActionsComponent.kt | 4 ---- 10 files changed, 46 insertions(+), 59 deletions(-) delete mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/MetaAccountFilter.kt create mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/selectAddress/SelectAddressAccountFilter.kt diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/MetaAccountFilter.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/MetaAccountFilter.kt deleted file mode 100644 index 66ae2b888e..0000000000 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/MetaAccountFilter.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.novafoundation.nova.feature_account_api.domain.filter - -import io.novafoundation.nova.common.utils.Filter -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount - -class MetaAccountFilter(val mode: Mode, val metaIds: List) : Filter { - - enum class Mode { - INCLUDE, - EXCLUDE - } - - override fun shouldInclude(model: MetaAccount): Boolean { - return when (mode) { - Mode.INCLUDE -> metaIds.contains(model.id) - Mode.EXCLUDE -> !metaIds.contains(model.id) - } - } -} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/selectAddress/SelectAddressAccountFilter.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/selectAddress/SelectAddressAccountFilter.kt new file mode 100644 index 0000000000..b029d55f4d --- /dev/null +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/filter/selectAddress/SelectAddressAccountFilter.kt @@ -0,0 +1,21 @@ +package io.novafoundation.nova.feature_account_api.domain.filter.selectAddress + +import io.novafoundation.nova.common.utils.Filter +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount + +sealed interface SelectAddressAccountFilter : Filter { + + class Everything : SelectAddressAccountFilter { + + override fun shouldInclude(model: MetaAccount): Boolean { + return true + } + } + + class ExcludeMetaAccounts(val metaIds: List) : SelectAddressAccountFilter { + + override fun shouldInclude(model: MetaAccount): Boolean { + return !metaIds.contains(model.id) + } + } +} diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt index c61ccae841..120cfdc2e7 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt @@ -4,6 +4,7 @@ import androidx.core.view.isInvisible import io.novafoundation.nova.common.base.BaseFragment import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.common.view.YourWalletsView +import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import kotlinx.coroutines.CoroutineScope @@ -11,7 +12,7 @@ import kotlinx.coroutines.flow.Flow interface SelectAddressMixin { - class Payload(val chain: Chain, val filter: Filter) + class Payload(val chain: Chain, val filter: SelectAddressAccountFilter) interface Factory { diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt index 37f8ee325c..7d76967513 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt @@ -2,17 +2,22 @@ package io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAdd import io.novafoundation.nova.common.utils.EverythingFilter import io.novafoundation.nova.common.utils.Filter -import io.novafoundation.nova.feature_account_api.domain.filter.MetaAccountFilter +import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester.Request -fun SelectAddressRequester.Request.Filter.toMetaAccountsFilter(): Filter { +fun Request.Filter.toMetaAccountsFilter(): SelectAddressAccountFilter { return when (this) { - is SelectAddressRequester.Request.Filter.Everything -> EverythingFilter() + is Request.Filter.Everything -> SelectAddressAccountFilter.Everything() - is SelectAddressRequester.Request.Filter.ExcludeMetaIds -> MetaAccountFilter( - MetaAccountFilter.Mode.EXCLUDE, - this.metaIds - ) + is Request.Filter.ExcludeMetaIds -> SelectAddressAccountFilter.ExcludeMetaAccounts(this.metaIds) + } +} + +fun SelectAddressAccountFilter.toRequestFilter(): Request.Filter { + return when (this) { + is SelectAddressAccountFilter.Everything -> Request.Filter.Everything + + is SelectAddressAccountFilter.ExcludeMetaAccounts -> Request.Filter.ExcludeMetaIds(this.metaIds) } } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt index c9c4ffe48e..8715e2135a 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt @@ -1,15 +1,12 @@ package io.novafoundation.nova.feature_account_impl.presentation.account.mixin -import io.novafoundation.nova.common.address.intoKey import io.novafoundation.nova.common.utils.Filter -import io.novafoundation.nova.feature_account_api.domain.filter.MetaAccountFilter +import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn -import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester -import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.toRequestFilter import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first @@ -57,16 +54,8 @@ class RealSelectAddressMixin( override suspend fun openSelectAddress(selectedAddress: String?) { val payload = payloadFlow.first() - val metaAccountFilter = getMetaAccountsFilterPayload(payload.filter) + val metaAccountFilter = payload.filter.toRequestFilter() val request = SelectAddressRequester.Request(payload.chain.id, selectedAddress, metaAccountFilter) selectAddressRequester.openRequest(request) } - - private suspend fun getMetaAccountsFilterPayload(filter: Filter): SelectAddressRequester.Request.Filter { - return if (filter is MetaAccountFilter && filter.mode == MetaAccountFilter.Mode.EXCLUDE) { - SelectAddressRequester.Request.Filter.ExcludeMetaIds(filter.metaIds) - } else { - SelectAddressRequester.Request.Filter.Everything - } - } } diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt index d0b1890898..1a52a47ee5 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt @@ -17,15 +17,13 @@ import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.ButtonState import io.novafoundation.nova.feature_account_api.data.mappers.mapChainToUi import io.novafoundation.nova.feature_account_api.data.model.Fee -import io.novafoundation.nova.feature_account_api.domain.filter.MetaAccountFilter +import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn -import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester -import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.toMetaAccountsFilter import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin @@ -502,19 +500,18 @@ class SelectSendViewModel( } } - private suspend fun getMetaAccountsFilter(origin: Chain, desination: Chain): Filter { + private suspend fun getMetaAccountsFilter(origin: Chain, desination: Chain): SelectAddressAccountFilter { val isCrossChain = origin.id != desination.id return if (isCrossChain) { - EverythingFilter() + SelectAddressAccountFilter.Everything() } else { val destinationAccountId = selectedAccount.first().requireAccountIdIn(desination) val notOriginMetaAccounts = accountRepository.activeMetaAccounts() .filter { it.accountIdIn(origin)?.intoKey() == destinationAccountId.intoKey() } .map { it.id } - MetaAccountFilter( - MetaAccountFilter.Mode.EXCLUDE, + SelectAddressAccountFilter.ExcludeMetaAccounts( notOriginMetaAccounts ) } diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt index 68d5b315d7..6f5418c41d 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/di/SelectSendModule.kt @@ -14,7 +14,6 @@ import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase -import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt index 94dec98e5e..d55c8373b6 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.core.view.isInvisible import io.novafoundation.nova.common.base.BaseFragment import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.common.mixin.impl.observeValidations diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt index 74abd29f41..15850f0e3e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt @@ -9,7 +9,7 @@ import io.novafoundation.nova.common.utils.flowOf import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher -import io.novafoundation.nova.feature_account_api.domain.filter.MetaAccountFilter +import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn @@ -230,11 +230,10 @@ class AddStakingProxyViewModel( return SelectAddressRequester.Request.Filter.ExcludeMetaIds(filteredMetaAccounts) } - private suspend fun metaAccountsFilter(chain: Chain, accountId: AccountId): MetaAccountFilter { + private suspend fun metaAccountsFilter(chain: Chain, accountId: AccountId): SelectAddressAccountFilter { val metaAccountsFilterPayload = getMetaAccountsFilterPayload(chain, accountId) - return MetaAccountFilter( - MetaAccountFilter.Mode.EXCLUDE, + return SelectAddressAccountFilter.ExcludeMetaAccounts( metaAccountsFilterPayload.metaIds ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt index f5166cf889..50659af6ac 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/parachain/ParachainStakeActionsComponent.kt @@ -11,12 +11,9 @@ import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.feature_staking_api.domain.model.parachain.DelegatorState import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.data.StakingOption -import io.novafoundation.nova.feature_staking_impl.data.chain import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.DelegatorStateUseCase import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.unbond.validations.preliminary.ParachainStakingUnbondPreliminaryValidationPayload import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.unbond.validations.preliminary.ParachainStakingUnbondPreliminaryValidationSystem -import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_ADD_PROXY -import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_PROXIES import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_BOND_MORE import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_UNBOND import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_VALIDATORS @@ -31,7 +28,6 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.com import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsComponent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsEvent import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.StakeActionsState -import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.addStakingProxy import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.bondMore import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.components.stakeActions.unbond import kotlinx.coroutines.CoroutineScope From 4cb29e35df8996774888b8ed24b733edc9cc7b80 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 15 Jan 2024 02:23:02 +0100 Subject: [PATCH 22/55] Run ktlint --- .../presenatation/mixin/selectAddress/SelectAddressMixin.kt | 2 -- .../mixin/selectAddress/SelectAddressRequestMappingExt.kt | 2 -- .../presentation/account/mixin/SelectAddressMixin.kt | 3 --- .../presentation/send/amount/SelectSendViewModel.kt | 3 --- 4 files changed, 10 deletions(-) diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt index 120cfdc2e7..e307639ff0 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressMixin.kt @@ -2,10 +2,8 @@ package io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAdd import androidx.core.view.isInvisible import io.novafoundation.nova.common.base.BaseFragment -import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.common.view.YourWalletsView import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt index 7d76967513..d4449b1d7a 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/selectAddress/SelectAddressRequestMappingExt.kt @@ -1,9 +1,7 @@ package io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress -import io.novafoundation.nova.common.utils.EverythingFilter import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester.Request fun Request.Filter.toMetaAccountsFilter(): SelectAddressAccountFilter { diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt index 8715e2135a..36d8003f5c 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/presentation/account/mixin/SelectAddressMixin.kt @@ -1,9 +1,6 @@ package io.novafoundation.nova.feature_account_impl.presentation.account.mixin -import io.novafoundation.nova.common.utils.Filter -import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressRequester import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.toRequestFilter diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt index 1a52a47ee5..78e64e9f3f 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt @@ -7,8 +7,6 @@ import io.novafoundation.nova.common.list.headers.TextHeader import io.novafoundation.nova.common.mixin.actionAwaitable.ActionAwaitableMixin import io.novafoundation.nova.common.mixin.api.Validatable import io.novafoundation.nova.common.resources.ResourceManager -import io.novafoundation.nova.common.utils.EverythingFilter -import io.novafoundation.nova.common.utils.Filter import io.novafoundation.nova.common.utils.inBackground import io.novafoundation.nova.common.utils.mapList import io.novafoundation.nova.common.utils.singleReplaySharedFlow @@ -21,7 +19,6 @@ import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.Se import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions From edb057799887835b902a32f4064fe84350330b4f Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 15 Jan 2024 10:35:31 +0100 Subject: [PATCH 23/55] Add duplication validation --- common/src/main/res/values/strings.xml | 3 ++ .../ProxyIsNotDuplicationForAccount.kt | 49 +++++++++++++++++++ .../AddStakingProxyValidationsModule.kt | 3 ++ .../proxy/AddStakingProxyValidationFailure.kt | 2 + .../delegation/proxy/Declarations.kt | 14 ++++++ .../AddProxyValidationFailureHandling.kt | 3 ++ .../proxy/set/AddStakingProxyFragment.kt | 2 + 7 files changed, 76 insertions(+) create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 634b4f6d9c..f8c51eb1e3 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,6 +1,9 @@ + Delegation already exists + You are already delegating to this account + Invalid proxy address Proxy address should be a valid %s address diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt new file mode 100644 index 0000000000..430c1edc14 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt @@ -0,0 +1,49 @@ +package io.novafoundation.nova.feature_proxy_api.domain.validators + +import io.novafoundation.nova.common.validation.Validation +import io.novafoundation.nova.common.validation.ValidationStatus +import io.novafoundation.nova.common.validation.ValidationSystemBuilder +import io.novafoundation.nova.common.validation.validOrError +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +class ProxyIsNotDuplicationForAccount( + private val chain: (P) -> Chain, + private val proxiedAccountId: (P) -> AccountId, + private val proxyAccountId: (P) -> AccountId, + private val proxyType: (P) -> ProxyType, + private val error: (P) -> E, + private val proxyRepository: GetProxyRepository +) : Validation { + + override suspend fun validate(value: P): ValidationStatus { + val chain = chain(value) + val proxyTypes = proxyRepository.getDelegatedProxyTypes(chain.id, proxiedAccountId(value), proxyAccountId(value)) + + return validOrError(proxyTypes.contains(proxyType(value))) { + error(value) + } + } +} + +fun ValidationSystemBuilder.proxyIsNotDuplicationForAccount( + chain: (P) -> Chain, + proxiedAccountId: (P) -> AccountId, + proxyAccountId: (P) -> AccountId, + proxyType: (P) -> ProxyType, + error: (P) -> E, + proxyRepository: GetProxyRepository +) { + validate( + ProxyIsNotDuplicationForAccount( + chain = chain, + proxiedAccountId = proxiedAccountId, + proxyAccountId = proxyAccountId, + proxyType = proxyType, + error = error, + proxyRepository = proxyRepository + ) + ) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt index b33bfd04b4..47509e30ac 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt @@ -8,6 +8,7 @@ import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyReposito import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.enoughBalanceToPayDeposit import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.maximumProxies +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.stakingTypeIsNotDuplication import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.sufficientBalanceToPayFee import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.sufficientBalanceToStayAboveEd import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.validAddress @@ -28,6 +29,8 @@ class AddStakingProxyValidationsModule { sufficientBalanceToStayAboveEd(enoughTotalToStayAboveEDValidationFactory) + stakingTypeIsNotDuplication(getProxyRepository) + maximumProxies(getProxyRepository) enoughBalanceToPayDeposit(getProxyRepository) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt index e462f2179f..162ec95c68 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt @@ -25,4 +25,6 @@ sealed interface AddStakingProxyValidationFailure { class InvalidAddress(val chain: Chain) : AddStakingProxyValidationFailure class MaximumProxiesReached(val chain: Chain, val max: Int) : AddStakingProxyValidationFailure + + object AlreadyDelegated : AddStakingProxyValidationFailure } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt index 0521b91ecf..6e8a29a216 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt @@ -3,13 +3,16 @@ package io.novafoundation.nova.feature_staking_impl.domain.validations.delegatio import io.novafoundation.nova.common.validation.ValidationSystem import io.novafoundation.nova.common.validation.ValidationSystemBuilder import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_proxy_api.domain.validators.enoughBalanceToPayProxyDeposit import io.novafoundation.nova.feature_proxy_api.domain.validators.maximumProxiesNotReached +import io.novafoundation.nova.feature_proxy_api.domain.validators.proxyIsNotDuplicationForAccount import io.novafoundation.nova.feature_wallet_api.domain.model.balanceCountedTowardsED import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughTotalToStayAboveEDValidationFactory import io.novafoundation.nova.feature_wallet_api.domain.validation.sufficientBalance import io.novafoundation.nova.feature_wallet_api.domain.validation.validAddress import io.novafoundation.nova.feature_wallet_api.domain.validation.validate +import io.novafoundation.nova.runtime.ext.accountIdOf import io.novafoundation.nova.runtime.multiNetwork.ChainWithAsset import java.math.BigDecimal @@ -81,3 +84,14 @@ fun AddStakingProxyValidationSystemBuilder.enoughBalanceToPayDeposit( proxyRepository = proxyRepository, feeReceiver = { it.fee.networkFee.amount } ) + +fun AddStakingProxyValidationSystemBuilder.stakingTypeIsNotDuplication( + proxyRepository: GetProxyRepository +) = proxyIsNotDuplicationForAccount( + chain = { it.chain }, + proxiedAccountId = { it.proxiedAccountId }, + proxyAccountId = { it.chain.accountIdOf(it.address) }, + proxyType = { ProxyType.Staking }, + error = { AddStakingProxyValidationFailure.AlreadyDelegated }, + proxyRepository = proxyRepository +) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt index cf4a5c2d2e..f93f603769 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt @@ -34,5 +34,8 @@ fun mapAddStakingProxyValidationFailureToUi( is NotEnoughToPayFee -> handleNotEnoughFeeError(failure, resourceManager) is NotEnoughToStayAboveED -> handleInsufficientBalanceCommission(failure, resourceManager) + + AddStakingProxyValidationFailure.AlreadyDelegated -> resourceManager.getString(R.string.duplicate_proxy_type_title) to + resourceManager.getString(R.string.duplicate_proxy_type_message) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt index d55c8373b6..3e7af47be8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyFragment.kt @@ -19,6 +19,7 @@ import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.di.StakingFeatureComponent import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.setupFeeLoading import io.novafoundation.nova.feature_wallet_api.presentation.view.showAmount +import kotlinx.android.synthetic.main.fragment_add_staking_proxy.addProxyToolbar import kotlinx.android.synthetic.main.fragment_add_staking_proxy.setStakingProxyAddress import kotlinx.android.synthetic.main.fragment_add_staking_proxy.addStakingProxyButton import kotlinx.android.synthetic.main.fragment_add_staking_proxy.setStakingProxyContainer @@ -39,6 +40,7 @@ class AddStakingProxyFragment : BaseFragment() { override fun initViews() { setStakingProxyContainer.applyStatusBarInsets() + addProxyToolbar.setHomeButtonListener { viewModel.backClicked() } addStakingProxyButton.prepareForProgress(this) addStakingProxySelectWallet.setOnClickListener { viewModel.selectAuthorityWallet() } From 0ebb3b96323b1b3880bca783c973171f0ca34e25 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 15 Jan 2024 11:58:29 +0100 Subject: [PATCH 24/55] Added proxy sync for staking --- .../data/signer/proxy/ProxiedSigner.kt | 2 +- .../data/repository/GetProxyRepository.kt | 4 +- .../data/repository/RealGetProxyRepository.kt | 60 +++++++++++-------- .../di/ProxyFeatureModule.kt | 7 ++- .../blockhain/updaters/ProxiesUpdater.kt | 26 ++++++++ .../RelaychainStakingUpdatersModule.kt | 19 +++++- 6 files changed, 88 insertions(+), 30 deletions(-) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt index da1818efe1..1cf794070a 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt @@ -127,7 +127,7 @@ class ProxiedSigner( val proxyAccountId = proxyMetaAccount.requireAccountIdIn(chain) val proxiedAccountId = proxiedMetaAccount.requireAccountIdIn(chain) - val availableProxyTypes = getProxyRepository.getDelegatedProxyTypes( + val availableProxyTypes = getProxyRepository.getDelegatedProxyTypesRemote( chainId = payload.chainId, proxiedAccountId = proxiedAccountId, proxyAccountId = proxyAccountId diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt index 91e9dc62d9..e3cd85f28e 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt @@ -13,7 +13,9 @@ interface GetProxyRepository { suspend fun getAllProxiesForAccounts(chainId: ChainId, accountIds: Set): List - suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List + suspend fun getDelegatedProxyTypesRemote(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List + + suspend fun getDelegatedProxyTypesLocal(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt index 150fe5bb8d..da349deb85 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt @@ -24,7 +24,6 @@ import jp.co.soramitsu.fearless_utils.runtime.AccountId import jp.co.soramitsu.fearless_utils.runtime.metadata.module import jp.co.soramitsu.fearless_utils.runtime.metadata.storage import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map private class OnChainProxiedModel( @@ -40,40 +39,42 @@ private class OnChainProxyModel( class RealGetProxyRepository( private val remoteSource: StorageDataSource, + private val localSource: StorageDataSource, private val chainRegistry: ChainRegistry, ) : GetProxyRepository { override suspend fun getAllProxiesForAccounts(chainId: ChainId, accountIds: Set): List { val delegatorToProxies = receiveAllProxiesInChain(chainId) - return delegatorToProxies - .mapNotNull { (delegator, proxied) -> - val notDelayedProxies = proxied.proxies.filter { it.delay == BigInteger.ZERO } - val matchedProxies = matchProxiesToAccountsAndMap(notDelayedProxies, accountIds) + return delegatorToProxies.mapNotNull { (delegator, proxied) -> + val notDelayedProxies = proxied.proxies.filter { it.delay == BigInteger.ZERO } + val matchedProxies = matchProxiesToAccountsAndMap(notDelayedProxies, accountIds) - if (matchedProxies.isEmpty()) return@mapNotNull null + if (matchedProxies.isEmpty()) return@mapNotNull null - delegator to matchedProxies - }.flatMap { (delegator, proxies) -> - proxies.map { proxy -> mapToProxiedWithProxies(chainId, delegator, proxy) } - } + delegator to matchedProxies + }.flatMap { (delegator, proxies) -> + proxies.map { proxy -> mapToProxiedWithProxies(chainId, delegator, proxy) } + } } - override suspend fun getDelegatedProxyTypes(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List { - val proxied = getAllProxiesFor(chainId, proxiedAccountId) + override suspend fun getDelegatedProxyTypesRemote(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List { + return getDelegatedProxyTypes(remoteSource, chainId, proxiedAccountId, proxyAccountId) + } - return proxied.proxies.filter { it.accountId == proxyAccountId.intoKey() } - .map { ProxyType.fromString(it.proxyType) } + // TODO: use it for staking after merge "add staking proxy" branch + override suspend fun getDelegatedProxyTypesLocal(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List { + return getDelegatedProxyTypes(localSource, chainId, proxiedAccountId, proxyAccountId) } override suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int { - val proxied = getAllProxiesFor(chainId, proxiedAccountId) + val proxied = getAllProxiesFor(localSource, chainId, proxiedAccountId) return proxied.proxies.size } override suspend fun getProxyDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger { - val proxied = getAllProxiesFor(chainId, proxiedAccountId) + val proxied = getAllProxiesFor(localSource, chainId, proxiedAccountId) return proxied.deposit } @@ -85,7 +86,7 @@ class RealGetProxyRepository( } override fun proxiesByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow> { - return remoteSource.subscribe(chain.id) { + return localSource.subscribe(chain.id) { runtime.metadata.module(Modules.PROXY) .storage("Proxies") .observe( @@ -103,15 +104,26 @@ class RealGetProxyRepository( .map { it.size } } - private suspend fun getAllProxiesFor(chainId: ChainId, accountId: AccountId): OnChainProxiedModel { - return remoteSource.query(chainId) { + private suspend fun getDelegatedProxyTypes( + storageDataSource: StorageDataSource, + chainId: ChainId, + proxiedAccountId: AccountId, + proxyAccountId: AccountId + ): List { + val proxied = getAllProxiesFor(storageDataSource, chainId, proxiedAccountId) + + return proxied.proxies + .filter { it.accountId == proxyAccountId.intoKey() } + .map { ProxyType.fromString(it.proxyType) } + } + + private suspend fun getAllProxiesFor(storageDataSource: StorageDataSource, chainId: ChainId, accountId: AccountId): OnChainProxiedModel { + return storageDataSource.query(chainId) { runtime.metadata.module(Modules.PROXY) .storage("Proxies") .query( keyArguments = arrayOf(accountId), - binding = { result -> - bindProxyAccounts(result) - } + binding = { result -> bindProxyAccounts(result) } ) } } @@ -122,9 +134,7 @@ class RealGetProxyRepository( .storage("Proxies") .entries( keyExtractor = { (accountId: AccountId) -> AccountIdKey(accountId) }, - binding = { result, _ -> - bindProxyAccounts(result) - }, + binding = { result, _ -> bindProxyAccounts(result) }, recover = { _, _ -> // Do nothing if entry binding throws an exception } diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt index b60a4b649a..2288e1cf4a 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt @@ -7,6 +7,7 @@ import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculat import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_impl.data.common.RealProxyDepositCalculator import io.novafoundation.nova.feature_proxy_impl.data.repository.RealGetProxyRepository +import io.novafoundation.nova.runtime.di.LOCAL_STORAGE_SOURCE import io.novafoundation.nova.runtime.di.REMOTE_STORAGE_SOURCE import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.storage.source.StorageDataSource @@ -18,10 +19,12 @@ class ProxyFeatureModule { @Provides @FeatureScope fun provideProxyRepository( - @Named(REMOTE_STORAGE_SOURCE) storageDataSource: StorageDataSource, + @Named(REMOTE_STORAGE_SOURCE) remoteSource: StorageDataSource, + @Named(LOCAL_STORAGE_SOURCE) localSource: StorageDataSource, chainRegistry: ChainRegistry ): GetProxyRepository = RealGetProxyRepository( - storageDataSource, + remoteSource = remoteSource, + localSource = localSource, chainRegistry ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt new file mode 100644 index 0000000000..5dcdb3ba9a --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt @@ -0,0 +1,26 @@ +package io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters + +import io.novafoundation.nova.common.utils.proxy +import io.novafoundation.nova.core.storage.StorageCache +import io.novafoundation.nova.core_db.model.AccountStakingLocal +import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState +import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.base.StakingUpdater +import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.scope.AccountStakingScope +import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry +import io.novafoundation.nova.runtime.network.updaters.SingleStorageKeyUpdater +import jp.co.soramitsu.fearless_utils.runtime.RuntimeSnapshot +import jp.co.soramitsu.fearless_utils.runtime.metadata.storageKey +import jp.co.soramitsu.fearless_utils.runtime.metadata.storageOrNull + +class ProxiesUpdater( + scope: AccountStakingScope, + stakingSharedState: StakingSharedState, + chainRegistry: ChainRegistry, + storageCache: StorageCache +) : SingleStorageKeyUpdater(scope, stakingSharedState, chainRegistry, storageCache), StakingUpdater { + + override suspend fun storageKey(runtime: RuntimeSnapshot, scopeValue: AccountStakingLocal): String? { + val accountId = scopeValue.accountId + return runtime.metadata.proxy().storageOrNull("Proxies")?.storageKey(runtime, accountId) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/staking/relaychain/RelaychainStakingUpdatersModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/staking/relaychain/RelaychainStakingUpdatersModule.kt index 7b8aa8fe4e..bdd3f4039e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/staking/relaychain/RelaychainStakingUpdatersModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/staking/relaychain/RelaychainStakingUpdatersModule.kt @@ -23,6 +23,7 @@ import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.update import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.MaxNominatorsUpdater import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.MinBondUpdater import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.ParachainsUpdater +import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.ProxiesUpdater import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.StakingLedgerUpdater import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.StakingUpdaters import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.ValidatorExposureUpdater @@ -360,6 +361,20 @@ class RelaychainStakingUpdatersModule { chainRegistry, ) + @Provides + @FeatureScope + fun provideProxiesUpdater( + storageCache: StorageCache, + scope: AccountStakingScope, + sharedState: StakingSharedState, + chainRegistry: ChainRegistry, + ) = ProxiesUpdater( + scope, + sharedState, + chainRegistry, + storageCache, + ) + @Provides @Relaychain @FeatureScope @@ -385,6 +400,7 @@ class RelaychainStakingUpdatersModule { genesisSlotUpdater: GenesisSlotUpdater, currentSessionIndexUpdater: CurrentSessionIndexUpdater, eraStartSessionIndexUpdater: EraStartSessionIndexUpdater, + proxiesUpdater: ProxiesUpdater ) = StakingUpdaters.Group( activeEraUpdater, validatorExposureUpdater, @@ -406,6 +422,7 @@ class RelaychainStakingUpdatersModule { currentSlotUpdater, genesisSlotUpdater, currentSessionIndexUpdater, - eraStartSessionIndexUpdater + eraStartSessionIndexUpdater, + proxiesUpdater ) } From 32463364120fba4712393e3df6e10e539371f5f0 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 15 Jan 2024 14:10:33 +0100 Subject: [PATCH 25/55] Add address argument to error dialog --- common/src/main/res/values/strings.xml | 2 +- .../delegation/proxy/AddStakingProxyValidationFailure.kt | 2 +- .../domain/validations/delegation/proxy/Declarations.kt | 2 +- .../proxy/common/AddProxyValidationFailureHandling.kt | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index f8c51eb1e3..812a0b9df4 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -2,7 +2,7 @@ Delegation already exists - You are already delegating to this account + You are already delegating to this account: %s Invalid proxy address Proxy address should be a valid %s address diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt index 162ec95c68..e2a35c9ab9 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/AddStakingProxyValidationFailure.kt @@ -26,5 +26,5 @@ sealed interface AddStakingProxyValidationFailure { class MaximumProxiesReached(val chain: Chain, val max: Int) : AddStakingProxyValidationFailure - object AlreadyDelegated : AddStakingProxyValidationFailure + class AlreadyDelegated(val address: String) : AddStakingProxyValidationFailure } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt index 6e8a29a216..2c5549a0fd 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt @@ -92,6 +92,6 @@ fun AddStakingProxyValidationSystemBuilder.stakingTypeIsNotDuplication( proxiedAccountId = { it.proxiedAccountId }, proxyAccountId = { it.chain.accountIdOf(it.address) }, proxyType = { ProxyType.Staking }, - error = { AddStakingProxyValidationFailure.AlreadyDelegated }, + error = { payload -> AddStakingProxyValidationFailure.AlreadyDelegated(payload.address) }, proxyRepository = proxyRepository ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt index f93f603769..2f95fa39c8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt @@ -35,7 +35,7 @@ fun mapAddStakingProxyValidationFailureToUi( is NotEnoughToStayAboveED -> handleInsufficientBalanceCommission(failure, resourceManager) - AddStakingProxyValidationFailure.AlreadyDelegated -> resourceManager.getString(R.string.duplicate_proxy_type_title) to - resourceManager.getString(R.string.duplicate_proxy_type_message) + is AddStakingProxyValidationFailure.AlreadyDelegated -> resourceManager.getString(R.string.duplicate_proxy_type_title) to + resourceManager.getString(R.string.duplicate_proxy_type_message, failure.address) } } From 6be6c41174a5c2f0eeb393e0ae81ca24c5e50235 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 19 Jan 2024 06:28:24 +0100 Subject: [PATCH 26/55] Nested proxies --- .../nova/core_db/dao/MetaAccountDao.kt | 13 +- .../proxied/ProxiedAddAccountRepository.kt | 8 +- .../data/proxy/RealProxySyncService.kt | 179 ++++++++-------- .../data/proxy/SyncServiceExt.kt | 16 ++ .../RealProxiedAddAccountRepository.kt | 20 +- .../data/signer/LeafSigner.kt | 5 + .../data/signer/proxy/ProxiedSigner.kt | 23 +- .../common/NestedProxiesGraphConstructor.kt | 50 +++++ .../data/model/ProxiedWithProxy.kt | 19 -- .../data/model/ProxyPermission.kt | 10 + .../data/repository/GetProxyRepository.kt | 7 +- .../domain/model/ProxyType.kt | 29 ++- .../RealNestedProxiesGraphConstructor.kt | 58 +++++ .../data/repository/RealGetProxyRepository.kt | 69 +++--- .../ProxyGraphConstryctorTest.kt | 199 ++++++++++++++++++ .../proxy/list/StakingProxyListInteractor.kt | 4 +- .../runtime/extrinsic/signer/NovaSigner.kt | 7 + 17 files changed, 527 insertions(+), 189 deletions(-) create mode 100644 feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/SyncServiceExt.kt create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/NestedProxiesGraphConstructor.kt delete mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxiedWithProxy.kt create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxyPermission.kt create mode 100644 feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealNestedProxiesGraphConstructor.kt create mode 100644 feature-proxy-impl/src/test/java/io/novafoundation/nova/feature_proxy_impl/ProxyGraphConstryctorTest.kt diff --git a/core-db/src/main/java/io/novafoundation/nova/core_db/dao/MetaAccountDao.kt b/core-db/src/main/java/io/novafoundation/nova/core_db/dao/MetaAccountDao.kt index 88250cdec0..d083c12fe1 100644 --- a/core-db/src/main/java/io/novafoundation/nova/core_db/dao/MetaAccountDao.kt +++ b/core-db/src/main/java/io/novafoundation/nova/core_db/dao/MetaAccountDao.kt @@ -163,7 +163,18 @@ interface MetaAccountDao { @Query("UPDATE meta_accounts SET name = :newName WHERE id = :metaId") suspend fun updateName(metaId: Long, newName: String) - @Query("DELETE FROM meta_accounts WHERE id = :metaId OR parentMetaId = :metaId") + @Query( + """ + WITH RECURSIVE accounts_to_delete AS ( + SELECT id, parentMetaId FROM meta_accounts WHERE id = :metaId + UNION ALL + SELECT m.id, m.parentMetaId + FROM meta_accounts m + JOIN accounts_to_delete r ON m.parentMetaId = r.id + ) + DELETE FROM meta_accounts WHERE id IN (SELECT id FROM accounts_to_delete) + """ + ) suspend fun delete(metaId: Long) @Query("SELECT COALESCE(MAX(position), 0) + 1 FROM meta_accounts") diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt index 6a99f79294..dbb14c7de5 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/repository/addAccount/proxied/ProxiedAddAccountRepository.kt @@ -1,13 +1,17 @@ package io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied -import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy import io.novafoundation.nova.feature_account_api.data.repository.addAccount.AddAccountRepository import io.novafoundation.nova.feature_account_api.domain.account.identity.Identity +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId +import jp.co.soramitsu.fearless_utils.runtime.AccountId interface ProxiedAddAccountRepository : AddAccountRepository { class Payload( - val proxiedWithProxy: ProxiedWithProxy, + val chainId: ChainId, + val proxiedAccountId: AccountId, + val proxyType: ProxyType, val proxyMetaId: Long, val identity: Identity? ) diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt index 7a3f515f61..d6b4ea7f80 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt @@ -3,23 +3,23 @@ package io.novafoundation.nova.feature_account_impl.data.proxy import android.util.Log import io.novafoundation.nova.common.address.AccountIdKey import io.novafoundation.nova.common.address.intoKey -import io.novafoundation.nova.common.list.GroupedList import io.novafoundation.nova.common.utils.LOG_TAG import io.novafoundation.nova.common.utils.coroutines.RootScope import io.novafoundation.nova.common.utils.mapToSet import io.novafoundation.nova.core_db.dao.MetaAccountDao import io.novafoundation.nova.core_db.model.chain.account.MetaAccountLocal import io.novafoundation.nova.core_db.model.chain.account.ProxyAccountLocal -import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy import io.novafoundation.nova.feature_account_api.data.proxy.MetaAccountsUpdatesRegistry import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.identity.Identity import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository -import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn +import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_proxy_api.data.common.NestedProxiesGraphConstructor +import io.novafoundation.nova.feature_proxy_api.data.common.getAllAccountIds import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain @@ -28,10 +28,16 @@ import io.novafoundation.nova.runtime.multiNetwork.findChains import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -class ProxiedWithProxyMetaAccount( - val proxiedWithProxy: ProxiedWithProxy, - val proxyMetaAccount: MetaAccount, -) +private class CreateMetaAccountsResult( + val addedMetaIds: MutableList = mutableListOf(), + val alreadyExistedMetaIds: MutableList = mutableListOf() +) { + + fun add(other: CreateMetaAccountsResult) { + addedMetaIds.addAll(other.addedMetaIds) + alreadyExistedMetaIds.addAll(other.alreadyExistedMetaIds) + } +} class RealProxySyncService( private val chainRegistry: ChainRegistry, @@ -63,36 +69,26 @@ class RealProxySyncService( Log.e(LOG_TAG, "Failed to sync proxy delegators", it) } - private suspend fun syncChainProxies(chain: Chain, metaAccounts: List) = runCatching { + private suspend fun syncChainProxies(chain: Chain, allMetaAccounts: List) = runCatching { Log.d(LOG_TAG, "Started syncing proxies for ${chain.name}") - val availableAccountIdsToMetaAccounts = chain.getAvailableAccountIds(metaAccounts) - val availableAccountIds = availableAccountIdsToMetaAccounts.keys + val availableAccounts = chain.getAvailableMetaAccounts(allMetaAccounts) + val availableMetaIds = availableAccounts.map { it.id } + val availableAccountIds = availableAccounts.mapToSet { it.requireAccountIdIn(chain).intoKey() } - val proxiedsWithProxies = getProxyRepository.getAllProxiesForAccounts(chain.id, availableAccountIds) - .withProxyMetaAccount(availableAccountIdsToMetaAccounts) + val nodes = getProxyRepository.findAllProxiedsForAccounts(chain.id, availableAccountIds) + val proxiedAccountIds = NestedProxiesGraphConstructor.Node.getAllAccountIds(nodes) val oldProxies = accountDao.getProxyAccounts(chain.id) + val identities = identityProvider.identitiesFor(proxiedAccountIds, chain.id) - val notAddedProxies = filterNotAddedProxieds(proxiedsWithProxies, oldProxies) - - val identitiesByChain = notAddedProxies.loadProxiedIdentities(chain.id) - val addedProxiedsMetaIds = notAddedProxies.map { - val identity = identitiesByChain[it.proxiedWithProxy.proxied.accountId.intoKey()] - - proxiedAddAccountRepository.addAccount( - ProxiedAddAccountRepository.Payload( - it.proxiedWithProxy, - it.proxyMetaAccount.id, - identity - ) - ) - } + val nestedNodes = nodes.flatMap { it.nestedNodes } + val result = recursivelyCreateMetaAccounts(chain.id, oldProxies, identities, availableMetaIds, nestedNodes) - val deactivatedMetaAccountIds = getDeactivatedMetaIds(proxiedsWithProxies, oldProxies) - accountDao.changeAccountsStatus(deactivatedMetaAccountIds, MetaAccountLocal.Status.DEACTIVATED) + val deactivatedMetaIds = result.findDeactivated(oldProxies) + accountDao.changeAccountsStatus(deactivatedMetaIds, MetaAccountLocal.Status.DEACTIVATED) - val changedMetaIds = addedProxiedsMetaIds + deactivatedMetaAccountIds + val changedMetaIds = result.addedMetaIds + deactivatedMetaIds metaAccountsUpdatesRegistry.addMetaIds(changedMetaIds) }.onFailure { Log.e(LOG_TAG, "Failed to sync proxy delegators in chain ${chain.name}", it) @@ -100,23 +96,68 @@ class RealProxySyncService( Log.d(LOG_TAG, "Finished syncing proxies for ${chain.name}") } - private fun filterNotAddedProxieds( - proxiedsWithProxies: List, - oldProxies: List - ): List { - val oldIdentifiers = oldProxies.mapToSet { it.identifier } - return proxiedsWithProxies.filter { it.toLocalIdentifier() !in oldIdentifiers } + private suspend fun recursivelyCreateMetaAccounts( + chainId: ChainId, + oldProxies: List, + identities: Map, + metaIds: List, + nestedNodes: List + ): CreateMetaAccountsResult { + val result = CreateMetaAccountsResult() + + metaIds.forEach { metaId -> + for (node in nestedNodes) { + val maybeExistedProxiedMetaId = node.getExistedProxiedMetaId(chainId, oldProxies, metaId) + + var nextMetaId = if (maybeExistedProxiedMetaId == null) { + val newMetaId = addProxiedAccount(chainId, node, metaId, identities) + result.addedMetaIds.add(newMetaId) + newMetaId + } else { + result.alreadyExistedMetaIds.add(maybeExistedProxiedMetaId) + maybeExistedProxiedMetaId + } + + if (node.nestedNodes.isNotEmpty()) { + val nestedResult = recursivelyCreateMetaAccounts(chainId, oldProxies, identities, listOf(nextMetaId), node.nestedNodes) + result.add(nestedResult) + } + } + } + + return result } - private suspend fun getDeactivatedMetaIds( - onChainProxies: List, - oldProxies: List - ): List { - val newIdentifiers = onChainProxies.mapToSet { it.toLocalIdentifier() } - val accountsToDeactivate = oldProxies.filter { it.identifier !in newIdentifiers } - .map { it.proxiedMetaId } + private suspend fun addProxiedAccount( + chainId: ChainId, + node: NestedProxiesGraphConstructor.Node, + metaId: Long, + identities: Map + ) = proxiedAddAccountRepository.addAccount( + ProxiedAddAccountRepository.Payload( + chainId = chainId, + proxiedAccountId = node.accountId.value, + proxyType = node.permissionType, + proxyMetaId = metaId, + identity = identities[node.accountId] + ) + ) + + private fun NestedProxiesGraphConstructor.Node.getExistedProxiedMetaId( + chainId: ChainId, + oldProxies: List, + proxyMetaId: Long + ): Long? { + val oldIdentifiers = oldProxies.associateBy { it.identifier } + + val identifier = ProxyAccountLocal.makeIdentifier( + proxyMetaId = proxyMetaId, + chainId = chainId, + proxiedAccountId = accountId.value, + proxyType = permissionType.name + ) - return accountsToDeactivate.takeNotYetDeactivatedMetaAccounts() + return oldIdentifiers[identifier]?.proxiedMetaId } private suspend fun getMetaAccounts(): List { @@ -124,46 +165,21 @@ class RealProxySyncService( .filter { it.isAllowedToSyncProxy() } } - private fun MetaAccount.isAllowedToSyncProxy(): Boolean { - return when (type) { - LightMetaAccount.Type.SECRETS, - LightMetaAccount.Type.PARITY_SIGNER, - LightMetaAccount.Type.LEDGER, - LightMetaAccount.Type.POLKADOT_VAULT, - LightMetaAccount.Type.WATCH_ONLY -> true - - LightMetaAccount.Type.PROXIED -> false - } - } - private suspend fun getSupportedProxyChains(): List { return chainRegistry.findChains { it.supportProxy } } - private fun Chain.getAvailableAccountIds(metaAccounts: List): GroupedList { - return metaAccounts.mapNotNull { metaAccount -> - val accountId = metaAccount.accountIdIn(chain = this) - accountId?.let { - accountId to metaAccount - } - }.groupBy( - keySelector = { it.first.intoKey() }, - valueTransform = { it.second } - ) + private fun Chain.getAvailableMetaAccounts(metaAccounts: List): List { + return metaAccounts.filter { metaAccount -> metaAccount.hasAccountIn(chain = this) } } - private fun List.withProxyMetaAccount(metaAccounts: GroupedList): List { - return flatMap { proxied -> - val proxyAccountId = proxied.proxy.accountId.intoKey() - metaAccounts.getValue(proxyAccountId) - .map { metaAccount -> ProxiedWithProxyMetaAccount(proxied, metaAccount) } - } - } + private suspend fun CreateMetaAccountsResult.findDeactivated(oldProxies: List): List { + val oldIds = oldProxies.map { it.proxiedMetaId } + val deactivated = oldIds - alreadyExistedMetaIds - private suspend fun List.loadProxiedIdentities(chainId: ChainId): Map { - val proxiedAccountIds = map { it.proxiedWithProxy.proxied.accountId } + val alreadyDeactivatedMetaIdsInCache = accountDao.getMetaAccountIdsByStatus(MetaAccountLocal.Status.DEACTIVATED) - return identityProvider.identitiesFor(proxiedAccountIds, chainId) + return deactivated - alreadyDeactivatedMetaIdsInCache.toSet() } private suspend fun List.takeNotYetDeactivatedMetaAccounts(): List { @@ -171,15 +187,4 @@ class RealProxySyncService( return this - alreadyDeactivatedMetaAccountIds.toSet() } - - private fun ProxiedWithProxyMetaAccount.toLocalIdentifier(): String { - val proxy = proxiedWithProxy.proxy - val proxied = proxiedWithProxy.proxied - return ProxyAccountLocal.makeIdentifier( - proxyMetaId = proxyMetaAccount.id, - chainId = proxied.chainId, - proxiedAccountId = proxied.accountId, - proxyType = proxy.proxyType - ) - } } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/SyncServiceExt.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/SyncServiceExt.kt new file mode 100644 index 0000000000..6fc9ff56f9 --- /dev/null +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/SyncServiceExt.kt @@ -0,0 +1,16 @@ +package io.novafoundation.nova.feature_account_impl.data.proxy + +import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount + +fun MetaAccount.isAllowedToSyncProxy(): Boolean { + return when (type) { + LightMetaAccount.Type.SECRETS, + LightMetaAccount.Type.PARITY_SIGNER, + LightMetaAccount.Type.LEDGER, + LightMetaAccount.Type.POLKADOT_VAULT, + LightMetaAccount.Type.WATCH_ONLY -> true + + LightMetaAccount.Type.PROXIED -> false + } +} diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/RealProxiedAddAccountRepository.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/RealProxiedAddAccountRepository.kt index 4287e3c0cb..0145ab81bf 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/RealProxiedAddAccountRepository.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/addAccount/proxied/RealProxiedAddAccountRepository.kt @@ -32,8 +32,7 @@ class RealProxiedAddAccountRepository( payload: Payload, position: Int ): MetaAccountLocal { - val proxied = payload.proxiedWithProxy.proxied - val chain = chainRegistry.getChain(proxied.chainId) + val chain = chainRegistry.getChain(payload.chainId) return MetaAccountLocal( substratePublicKey = null, @@ -41,7 +40,7 @@ class RealProxiedAddAccountRepository( substrateAccountId = null, ethereumPublicKey = null, ethereumAddress = null, - name = payload.identity?.name ?: chain.addressOf(proxied.accountId), + name = payload.identity?.name ?: chain.addressOf(payload.proxiedAccountId), parentMetaId = payload.proxyMetaId, isSelected = false, position = position, @@ -51,13 +50,11 @@ class RealProxiedAddAccountRepository( } private fun createChainAccount(proxiedMetaId: Long, payload: Payload): ChainAccountLocal { - val proxied = payload.proxiedWithProxy.proxied - return ChainAccountLocal( metaId = proxiedMetaId, - chainId = proxied.chainId, + chainId = payload.chainId, publicKey = null, - accountId = proxied.accountId, + accountId = payload.proxiedAccountId, cryptoType = null ) } @@ -66,15 +63,12 @@ class RealProxiedAddAccountRepository( proxiedMetaId: Long, payload: Payload ): ProxyAccountLocal { - val proxied = payload.proxiedWithProxy.proxied - val proxy = payload.proxiedWithProxy.proxy - return ProxyAccountLocal( proxiedMetaId = proxiedMetaId, proxyMetaId = payload.proxyMetaId, - chainId = proxied.chainId, - proxiedAccountId = proxied.accountId, - proxyType = proxy.proxyType + chainId = payload.chainId, + proxiedAccountId = payload.proxiedAccountId, + proxyType = payload.proxyType.name ) } } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/LeafSigner.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/LeafSigner.kt index 0cc896cc2c..334f5dff48 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/LeafSigner.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/LeafSigner.kt @@ -5,6 +5,7 @@ import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdI import io.novafoundation.nova.runtime.extrinsic.signer.NovaSigner import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId +import jp.co.soramitsu.fearless_utils.runtime.extrinsic.signer.SignerPayloadExtrinsic abstract class LeafSigner( private val metaAccount: MetaAccount, @@ -13,4 +14,8 @@ abstract class LeafSigner( override suspend fun signerAccountId(chain: Chain): AccountId { return metaAccount.requireAccountIdIn(chain) } + + override suspend fun modifyPayload(payloadExtrinsic: SignerPayloadExtrinsic): SignerPayloadExtrinsic { + return payloadExtrinsic + } } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt index 1cf794070a..f4cc427837 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt @@ -73,21 +73,30 @@ class ProxiedSigner( return delegate.signerAccountId(chain) } + override suspend fun modifyPayload(payloadExtrinsic: SignerPayloadExtrinsic): SignerPayloadExtrinsic { + val chain = chainRegistry.getChain(payloadExtrinsic.chainId) + val proxyMetaAccount = getProxyMetaAccount() + val delegate = createDelegate(proxyMetaAccount) + val payload = checkPermissionAndWrap(proxyMetaAccount, payloadExtrinsic, chain) + return delegate.modifyPayload(payload) + } + override suspend fun signExtrinsic(payloadExtrinsic: SignerPayloadExtrinsic): SignedExtrinsic { val chain = chainRegistry.getChain(payloadExtrinsic.chainId) val proxyMetaAccount = getProxyMetaAccount() - acknowledgeProxyOperation(proxyMetaAccount) + if (isRootProxied) { + acknowledgeProxyOperation(proxyMetaAccount) + } + + val payloadToSign = if (isRootProxied) modifyPayload(payloadExtrinsic) else payloadExtrinsic if (isRootProxied) { - validateExtrinsic(payloadExtrinsic, chain) + validateExtrinsic(payloadToSign, chain) } val delegate = createDelegate(proxyMetaAccount) - val modifiedPayload = modifyPayload(proxyMetaAccount, payloadExtrinsic, chain) - - val signedExtrinsic = delegate.signExtrinsic(modifiedPayload) - return signedExtrinsic + return delegate.signExtrinsic(payloadToSign) } override suspend fun signRaw(payload: SignerPayloadRaw): SignedRaw { @@ -123,7 +132,7 @@ class ProxiedSigner( } } - private suspend fun modifyPayload(proxyMetaAccount: MetaAccount, payload: SignerPayloadExtrinsic, chain: Chain): SignerPayloadExtrinsic { + private suspend fun checkPermissionAndWrap(proxyMetaAccount: MetaAccount, payload: SignerPayloadExtrinsic, chain: Chain): SignerPayloadExtrinsic { val proxyAccountId = proxyMetaAccount.requireAccountIdIn(chain) val proxiedAccountId = proxiedMetaAccount.requireAccountIdIn(chain) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/NestedProxiesGraphConstructor.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/NestedProxiesGraphConstructor.kt new file mode 100644 index 0000000000..6a1b0e32d4 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/NestedProxiesGraphConstructor.kt @@ -0,0 +1,50 @@ +package io.novafoundation.nova.feature_proxy_api.data.common + +import io.novafoundation.nova.common.address.AccountIdKey +import io.novafoundation.nova.common.utils.mapToSet +import io.novafoundation.nova.feature_proxy_api.data.common.NestedProxiesGraphConstructor.Node +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.feature_proxy_api.domain.model.min +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +interface NestedProxiesGraphConstructor { + + fun build(): List + + data class Node( + val accountId: AccountIdKey, + val permissionType: ProxyType, + val nestedNodes: MutableList, + val path: Map + ) { + fun hasInPath(otherAccountId: AccountIdKey): Boolean { + return path.contains(otherAccountId) || accountId == otherAccountId + } + + fun addNested(node: Node) { + nestedNodes.add(node) + } + + fun flatten(): List { + val result = mutableListOf() + result.add(this) + result.addAll(nestedNodes.flatMap { it.flatten() }) + return result + } + + companion object + } +} + +fun Node.Companion.getAllAccountIds(nodes: List): Set { + return flatten(nodes).mapToSet { it.accountId.value } +} + +fun Node.Companion.flatten(nodes: List): List { + return nodes.flatMap { it.flatten() } +} + +fun ProxyType.isMutuallyExclusiveWith(node: Node): Boolean { + val fullPermissionPath = node.path.values + node.permissionType + return fullPermissionPath.any { ProxyType.min(it, this) == null } +} diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxiedWithProxy.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxiedWithProxy.kt deleted file mode 100644 index c6e43fb500..0000000000 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxiedWithProxy.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.novafoundation.nova.feature_proxy_api.data.model - -import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId -import jp.co.soramitsu.fearless_utils.runtime.AccountId - -class ProxiedWithProxy( - val proxied: Proxied, - val proxy: Proxy -) { - class Proxied( - val accountId: AccountId, - val chainId: ChainId - ) - - class Proxy( - val accountId: AccountId, - val proxyType: String - ) -} diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxyPermission.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxyPermission.kt new file mode 100644 index 0000000000..87d8633c74 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/model/ProxyPermission.kt @@ -0,0 +1,10 @@ +package io.novafoundation.nova.feature_proxy_api.data.model + +import io.novafoundation.nova.common.address.AccountIdKey +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType + +data class ProxyPermission( + val proxiedAccountId: AccountIdKey, + val proxyAccountId: AccountIdKey, + val proxyType: ProxyType +) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt index e3cd85f28e..6858446a8a 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/GetProxyRepository.kt @@ -1,7 +1,8 @@ package io.novafoundation.nova.feature_proxy_api.data.repository import io.novafoundation.nova.common.address.AccountIdKey -import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy +import io.novafoundation.nova.feature_proxy_api.data.common.NestedProxiesGraphConstructor +import io.novafoundation.nova.feature_proxy_api.data.model.ProxyPermission import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId @@ -11,7 +12,7 @@ import kotlinx.coroutines.flow.Flow interface GetProxyRepository { - suspend fun getAllProxiesForAccounts(chainId: ChainId, accountIds: Set): List + suspend fun findAllProxiedsForAccounts(chainId: ChainId, accountIds: Set): List suspend fun getDelegatedProxyTypesRemote(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List @@ -23,7 +24,7 @@ interface GetProxyRepository { suspend fun maxProxiesQuantity(chain: Chain): Int - fun proxiesByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow> + fun proxiesByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow> fun proxiesQuantityByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyType.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyType.kt index cf6d12b013..3711fddb37 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyType.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyType.kt @@ -1,24 +1,24 @@ package io.novafoundation.nova.feature_proxy_api.domain.model -sealed class ProxyType(val name: String) { +sealed class ProxyType(val name: String, val controllableFrom: List) { - object Any : ProxyType("Any") + object Any : ProxyType("Any", emptyList()) - object NonTransfer : ProxyType("NonTransfer") + object NonTransfer : ProxyType("NonTransfer", listOf(Any)) - object Governance : ProxyType("Governance") + object Governance : ProxyType("Governance", listOf(Any, NonTransfer)) - object Staking : ProxyType("Staking") + object Staking : ProxyType("Staking", listOf(Any, NonTransfer)) - object IdentityJudgement : ProxyType("IdentityJudgement") + object IdentityJudgement : ProxyType("IdentityJudgement", listOf(Any, NonTransfer)) - object CancelProxy : ProxyType("CancelProxy") + object CancelProxy : ProxyType("CancelProxy", listOf(Any, NonTransfer)) - object Auction : ProxyType("Auction") + object Auction : ProxyType("Auction", listOf(Any, NonTransfer)) - object NominationPools : ProxyType("NominationPools") + object NominationPools : ProxyType("NominationPools", listOf(Any, NonTransfer, Staking)) - class Other(name: String) : ProxyType(name) + class Other(name: String) : ProxyType(name, listOf(Any)) companion object } @@ -36,3 +36,12 @@ fun ProxyType.Companion.fromString(name: String): ProxyType { else -> ProxyType.Other(name) } } + +fun ProxyType.isControllableFrom(proxyType: ProxyType): Boolean { + return name == proxyType.name || controllableFrom.contains(proxyType) +} + +fun ProxyType.Companion.min(first: ProxyType, second: ProxyType): ProxyType? { + return first.takeIf { it.isControllableFrom(second) } + ?: second.takeIf { it.isControllableFrom(first) } +} diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealNestedProxiesGraphConstructor.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealNestedProxiesGraphConstructor.kt new file mode 100644 index 0000000000..eee24b8388 --- /dev/null +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealNestedProxiesGraphConstructor.kt @@ -0,0 +1,58 @@ +package io.novafoundation.nova.feature_proxy_impl.data.common + +import io.novafoundation.nova.common.address.AccountIdKey +import io.novafoundation.nova.feature_proxy_api.data.common.NestedProxiesGraphConstructor +import io.novafoundation.nova.feature_proxy_api.data.common.NestedProxiesGraphConstructor.Node +import io.novafoundation.nova.feature_proxy_api.data.common.isMutuallyExclusiveWith +import io.novafoundation.nova.feature_proxy_api.data.model.ProxyPermission +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType + +class RealNestedProxiesGraphConstructor( + val startAccountIds: Set, + permissions: List +) : NestedProxiesGraphConstructor { + + val proxyToProxieds: Map> = permissions + .groupBy { it.proxyAccountId } + .mapValues { + it.value.map { + Node( + it.proxiedAccountId, + it.proxyType, + mutableListOf(), + mapOf() + ) + } + } + + override fun build(): List { + val startNodes = startAccountIds.map { Node(it, ProxyType.Any, mutableListOf(), emptyMap()) } + + fillNodes(startNodes) + + return startNodes + } + + fun fillNodes(nodes: List) { + for (node in nodes) { + val nestedNodes = proxyToProxieds[node.accountId] ?: continue + + for (proxiedNode in nestedNodes) { + // If we have an account in full node path we skip it to avoid cycles + if (node.hasInPath(proxiedNode.accountId)) continue + + // Check that proxy type is not matually exclusive by full path + val matuallyExclusive = proxiedNode.permissionType.isMutuallyExclusiveWith(node) + if (matuallyExclusive) continue + + val nestedNodePath = node.path + mapOf(node.accountId to node.permissionType) + val nestedNode = proxiedNode.copy(path = nestedNodePath) + node.addNested(nestedNode) + } + + if (node.nestedNodes.isNotEmpty()) { + fillNodes(node.nestedNodes) + } + } + } +} diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt index da349deb85..99a89d6b48 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealGetProxyRepository.kt @@ -10,10 +10,12 @@ import io.novafoundation.nova.common.data.network.runtime.binding.getTyped import io.novafoundation.nova.common.utils.Modules import io.novafoundation.nova.common.utils.numberConstant import io.novafoundation.nova.common.utils.proxy -import io.novafoundation.nova.feature_proxy_api.data.model.ProxiedWithProxy +import io.novafoundation.nova.feature_proxy_api.data.common.NestedProxiesGraphConstructor +import io.novafoundation.nova.feature_proxy_api.data.model.ProxyPermission import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_proxy_api.domain.model.fromString +import io.novafoundation.nova.feature_proxy_impl.data.common.RealNestedProxiesGraphConstructor import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId @@ -43,19 +45,23 @@ class RealGetProxyRepository( private val chainRegistry: ChainRegistry, ) : GetProxyRepository { - override suspend fun getAllProxiesForAccounts(chainId: ChainId, accountIds: Set): List { + override suspend fun findAllProxiedsForAccounts(chainId: ChainId, accountIds: Set): List { val delegatorToProxies = receiveAllProxiesInChain(chainId) - - return delegatorToProxies.mapNotNull { (delegator, proxied) -> - val notDelayedProxies = proxied.proxies.filter { it.delay == BigInteger.ZERO } - val matchedProxies = matchProxiesToAccountsAndMap(notDelayedProxies, accountIds) - - if (matchedProxies.isEmpty()) return@mapNotNull null - - delegator to matchedProxies - }.flatMap { (delegator, proxies) -> - proxies.map { proxy -> mapToProxiedWithProxies(chainId, delegator, proxy) } - } + val proxyPermissions = delegatorToProxies + .flatMap { (delegator, proxied) -> + val notDelayedProxies = proxied.proxies.filter { it.delay == BigInteger.ZERO } + + notDelayedProxies.map { proxy -> + ProxyPermission( + proxiedAccountId = delegator, + proxyAccountId = proxy.accountId, + proxyType = ProxyType.fromString(proxy.proxyType) + ) + } + } + + return RealNestedProxiesGraphConstructor(accountIds, proxyPermissions) + .build() } override suspend fun getDelegatedProxyTypesRemote(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List { @@ -85,7 +91,7 @@ class RealGetProxyRepository( return constantQuery.numberConstant("MaxProxies", runtime).toInt() } - override fun proxiesByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow> { + override fun proxiesByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow> { return localSource.subscribe(chain.id) { runtime.metadata.module(Modules.PROXY) .storage("Proxies") @@ -93,9 +99,10 @@ class RealGetProxyRepository( accountId, binding = { bindProxyAccounts(it) } ) - }.map { - it.proxies.filter { it.proxyType == proxyType.name } - .map { ProxiedWithProxy.Proxy(it.accountId.value, it.proxyType) } + }.map { proxied -> + proxied.proxies + .filter { it.proxyType == proxyType.name } + .map { ProxyPermission(accountId.intoKey(), it.accountId, ProxyType.fromString(it.proxyType)) } } } @@ -163,32 +170,4 @@ class RealGetProxyRepository( deposit = root[1].cast() ) } - - private fun mapToProxiedWithProxies( - chainId: ChainId, - delegator: AccountIdKey, - proxy: ProxiedWithProxy.Proxy - ): ProxiedWithProxy { - return ProxiedWithProxy( - proxied = ProxiedWithProxy.Proxied( - accountId = delegator.value, - chainId = chainId - ), - proxy = proxy - ) - } - - private fun matchProxiesToAccountsAndMap( - proxies: List, - accountIdToMetaAccounts: Set - ): List { - return proxies.filter { - accountIdToMetaAccounts.contains(it.accountId) - }.map { onChainProxy -> - ProxiedWithProxy.Proxy( - accountId = onChainProxy.accountId.value, - proxyType = onChainProxy.proxyType - ) - } - } } diff --git a/feature-proxy-impl/src/test/java/io/novafoundation/nova/feature_proxy_impl/ProxyGraphConstryctorTest.kt b/feature-proxy-impl/src/test/java/io/novafoundation/nova/feature_proxy_impl/ProxyGraphConstryctorTest.kt new file mode 100644 index 0000000000..b992504d33 --- /dev/null +++ b/feature-proxy-impl/src/test/java/io/novafoundation/nova/feature_proxy_impl/ProxyGraphConstryctorTest.kt @@ -0,0 +1,199 @@ +package io.novafoundation.nova.feature_proxy_impl + +import io.novafoundation.nova.common.address.AccountIdKey +import io.novafoundation.nova.common.utils.mapToSet +import io.novafoundation.nova.feature_proxy_api.data.common.NestedProxiesGraphConstructor.Node +import io.novafoundation.nova.feature_proxy_api.data.model.ProxyPermission +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.feature_proxy_impl.data.common.RealNestedProxiesGraphConstructor +import org.junit.Assert.assertEquals +import org.junit.Test + +class ProxyGraphConstryctorTest { + + @Test + fun test_result_size() { + val engine = RealNestedProxiesGraphConstructor( + startAccountIds = keysOf("Account_1", "Account_2"), + permissions = listOf(makePermission(from = "Account_4", to = "Account_1", ProxyType.Any)) + ) + + val result = engine.build() + + assertEquals(result.size, 2) + } + + @Test + fun simple_nested_proxies() { + val engine = RealNestedProxiesGraphConstructor( + startAccountIds = keysOf("Account_1", "Account_2"), + permissions = listOf( + makePermission(from = "Account_4", to = "Account_3", ProxyType.Any), + makePermission(from = "Account_3", to = "Account_1", ProxyType.Any), + ) + ) + + val result = engine.build() + + assertEquals( + result, + listOf( + makeNode( + accountId = "Account_1", + nestedNodes = makeSingleNode( + accountId = "Account_3", + nestedNodes = makeSingleNode( + "Account_4", + path = pathWithAny("Account_1", "Account_3") + ), + path = pathWithAny("Account_1") + ) + ), + makeNode("Account_2") + ) + ) + } + + // Set a timeout to check that we don't have an infinite loop + @Test(timeout = 10000L) + fun cyclical_nested_proxies() { + val engine = RealNestedProxiesGraphConstructor( + startAccountIds = keysOf("Account_1"), + permissions = listOf( + makePermission(from = "Account_3", to = "Account_2", ProxyType.Any), + makePermission(from = "Account_2", to = "Account_1", ProxyType.Any), + makePermission(from = "Account_1", to = "Account_3", ProxyType.Any), + ) + ) + + val result = engine.build() + + assertEquals( + result, + makeSingleNode( + accountId = "Account_1", + nestedNodes = makeSingleNode( + accountId = "Account_2", + nestedNodes = makeSingleNode( + accountId = "Account_3", + path = pathWithAny("Account_1", "Account_2") + ), + path = pathWithAny("Account_1") + ) + ) + ) + } + + @Test + fun mutually_exclusive_path_doesnt_build() { + val engine = RealNestedProxiesGraphConstructor( + startAccountIds = keysOf("Account_1"), + permissions = listOf( + // Staking is not controllable from Governance and should be skipped + makePermission(from = "Account_4", to = "Account_3", ProxyType.Staking), + makePermission(from = "Account_3", to = "Account_2", ProxyType.Any), + makePermission(from = "Account_2", to = "Account_1", ProxyType.Governance) + ) + ) + + val result = engine.build() + + assertEquals( + result, + makeSingleNode( + accountId = "Account_1", + nestedNodes = makeSingleNode( + accountId = "Account_2", + permissionType = ProxyType.Governance, + nestedNodes = makeSingleNode( + accountId = "Account_3", + path = path("Account_1" to ProxyType.Any, "Account_2" to ProxyType.Governance) + ), + path = pathWithAny("Account_1") + ) + ) + ) + } + + @Test + fun two_accounts_in_permission_chain() { + val engine = RealNestedProxiesGraphConstructor( + startAccountIds = keysOf("Account_1", "Account_2"), + permissions = listOf( + makePermission(from = "Account_3", to = "Account_2", ProxyType.Any), + makePermission(from = "Account_2", to = "Account_1", ProxyType.Any) + ) + ) + + val result = engine.build() + + assertEquals( + result, + listOf( + makeNode( + accountId = "Account_1", + nestedNodes = makeSingleNode( + accountId = "Account_2", + nestedNodes = makeSingleNode( + accountId = "Account_3", + path = pathWithAny("Account_1", "Account_2") + ), + path = pathWithAny("Account_1") + ) + ), + makeNode( + accountId = "Account_2", + nestedNodes = makeSingleNode( + accountId = "Account_3", + path = pathWithAny("Account_2") + ) + ) + ) + ) + } + + private fun keysOf(vararg values: String): Set { + return values.toList() + .mapToSet { it.intoKey() } + } + + private fun String.intoKey(): AccountIdKey { + return AccountIdKey(this.toByteArray()) + } + + private fun makePermission(from: String, to: String, type: ProxyType): ProxyPermission { + return ProxyPermission(from.intoKey(), to.intoKey(), type) + } + + private fun makeSingleNode( + accountId: String, + permissionType: ProxyType = ProxyType.Any, + nestedNodes: MutableList = mutableListOf(), + path: Map = mapOf() + ): MutableList { + return mutableListOf(makeNode(accountId, permissionType, nestedNodes, path)) + } + + private fun makeNode( + accountId: String, + permissionType: ProxyType = ProxyType.Any, + nestedNodes: MutableList = mutableListOf(), + path: Map = mapOf() + ): Node { + return Node(accountId.intoKey(), permissionType, nestedNodes, path) + } + + private fun pathWithAny( + vararg path: String + ): Map { + return path.associateBy { it.intoKey() } + .mapValues { ProxyType.Any } + } + + private fun path( + vararg path: Pair + ): Map { + return path.toMap() + .mapKeys { (accountId, _) -> accountId.intoKey() } + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt index e24e991ed5..b9c9a946d3 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt @@ -31,8 +31,8 @@ class StakingProxyListInteractor( proxies.map { proxy -> val proxyAccountId = proxy.accountId StakingProxyAccount( - accountIdToMetaAccount[proxyAccountId.intoKey()], - proxyAccountId + accountIdToMetaAccount[proxyAccountId], + proxyAccountId.value ) } } diff --git a/runtime/src/main/java/io/novafoundation/nova/runtime/extrinsic/signer/NovaSigner.kt b/runtime/src/main/java/io/novafoundation/nova/runtime/extrinsic/signer/NovaSigner.kt index 23d04326ca..9068d274d6 100644 --- a/runtime/src/main/java/io/novafoundation/nova/runtime/extrinsic/signer/NovaSigner.kt +++ b/runtime/src/main/java/io/novafoundation/nova/runtime/extrinsic/signer/NovaSigner.kt @@ -3,10 +3,13 @@ package io.novafoundation.nova.runtime.extrinsic.signer import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import jp.co.soramitsu.fearless_utils.runtime.extrinsic.signer.Signer +import jp.co.soramitsu.fearless_utils.runtime.extrinsic.signer.SignerPayloadExtrinsic interface NovaSigner : Signer { suspend fun signerAccountId(chain: Chain): AccountId + + suspend fun modifyPayload(payloadExtrinsic: SignerPayloadExtrinsic): SignerPayloadExtrinsic } interface FeeSigner : NovaSigner { @@ -23,4 +26,8 @@ interface FeeSigner : NovaSigner { * It might not be equal to [actualFeeSignerId] if [Signer] modifies the payload */ suspend fun requestedFeeSignerId(chain: Chain): AccountId + + override suspend fun modifyPayload(payloadExtrinsic: SignerPayloadExtrinsic): SignerPayloadExtrinsic { + throw NotImplementedError("This method should not be called") + } } From 77bf85ee321eafe93f097f446f6469893972337e Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 19 Jan 2024 06:50:20 +0100 Subject: [PATCH 27/55] Update StakingProxyListInteractor.kt --- .../staking/delegation/proxy/list/StakingProxyListInteractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt index b9c9a946d3..75043144c8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt @@ -29,7 +29,7 @@ class StakingProxyListInteractor( } proxies.map { proxy -> - val proxyAccountId = proxy.accountId + val proxyAccountId = proxy.proxyAccountId StakingProxyAccount( accountIdToMetaAccount[proxyAccountId], proxyAccountId.value From eda2304e982268cbcf094794e8b9a49df3cc67c3 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 19 Jan 2024 08:15:53 +0100 Subject: [PATCH 28/55] Fixed issue with mutable list copy --- .../common/NestedProxiesGraphConstructor.kt | 6 +- .../RealNestedProxiesGraphConstructor.kt | 11 ++-- .../ProxyGraphConstryctorTest.kt | 55 ++++++++++++++++++- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/NestedProxiesGraphConstructor.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/NestedProxiesGraphConstructor.kt index 6a1b0e32d4..f38de14780 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/NestedProxiesGraphConstructor.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/NestedProxiesGraphConstructor.kt @@ -14,15 +14,15 @@ interface NestedProxiesGraphConstructor { data class Node( val accountId: AccountIdKey, val permissionType: ProxyType, - val nestedNodes: MutableList, + var nestedNodes: List, val path: Map ) { fun hasInPath(otherAccountId: AccountIdKey): Boolean { return path.contains(otherAccountId) || accountId == otherAccountId } - fun addNested(node: Node) { - nestedNodes.add(node) + fun setNested(nodes: List) { + nestedNodes = nodes } fun flatten(): List { diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealNestedProxiesGraphConstructor.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealNestedProxiesGraphConstructor.kt index eee24b8388..1c19350484 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealNestedProxiesGraphConstructor.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealNestedProxiesGraphConstructor.kt @@ -35,9 +35,11 @@ class RealNestedProxiesGraphConstructor( fun fillNodes(nodes: List) { for (node in nodes) { - val nestedNodes = proxyToProxieds[node.accountId] ?: continue + val onChainNestedNodes = proxyToProxieds[node.accountId] ?: continue - for (proxiedNode in nestedNodes) { + val resultNestedNodes = mutableListOf() + + for (proxiedNode in onChainNestedNodes) { // If we have an account in full node path we skip it to avoid cycles if (node.hasInPath(proxiedNode.accountId)) continue @@ -47,10 +49,11 @@ class RealNestedProxiesGraphConstructor( val nestedNodePath = node.path + mapOf(node.accountId to node.permissionType) val nestedNode = proxiedNode.copy(path = nestedNodePath) - node.addNested(nestedNode) + resultNestedNodes.add(nestedNode) } - if (node.nestedNodes.isNotEmpty()) { + if (resultNestedNodes.isNotEmpty()) { + node.setNested(resultNestedNodes) fillNodes(node.nestedNodes) } } diff --git a/feature-proxy-impl/src/test/java/io/novafoundation/nova/feature_proxy_impl/ProxyGraphConstryctorTest.kt b/feature-proxy-impl/src/test/java/io/novafoundation/nova/feature_proxy_impl/ProxyGraphConstryctorTest.kt index b992504d33..12cf70d3aa 100644 --- a/feature-proxy-impl/src/test/java/io/novafoundation/nova/feature_proxy_impl/ProxyGraphConstryctorTest.kt +++ b/feature-proxy-impl/src/test/java/io/novafoundation/nova/feature_proxy_impl/ProxyGraphConstryctorTest.kt @@ -7,6 +7,7 @@ import io.novafoundation.nova.feature_proxy_api.data.model.ProxyPermission import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_proxy_impl.data.common.RealNestedProxiesGraphConstructor import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotEquals import org.junit.Test class ProxyGraphConstryctorTest { @@ -152,6 +153,56 @@ class ProxyGraphConstryctorTest { ) } + + @Test + fun cyclical_with_two_accounts_in_permission_chain() { + val engine = RealNestedProxiesGraphConstructor( + startAccountIds = keysOf("Account_1", "Account_2"), + permissions = listOf( + makePermission(from = "Account_3", to = "Account_2", ProxyType.Any), + makePermission(from = "Account_2", to = "Account_1", ProxyType.Any), + makePermission(from = "Account_1", to = "Account_3", ProxyType.Any), + makePermission(from = "Account_3", to = "Account_1", ProxyType.Any), + ) + ) + + val result = engine.build() + + assertEquals( + result, + listOf( + makeNode( + accountId = "Account_1", + nestedNodes = mutableListOf( + makeNode( + accountId = "Account_2", + nestedNodes = makeSingleNode( + accountId = "Account_3", + path = pathWithAny("Account_1", "Account_2") + ), + path = pathWithAny("Account_1") + ), + makeNode( + accountId = "Account_3", + path = pathWithAny("Account_1") + ) + ) + ), + makeNode( + accountId = "Account_2", + nestedNodes = makeSingleNode( + accountId = "Account_3", + nestedNodes = makeSingleNode( + accountId = "Account_1", + path = pathWithAny("Account_2", "Account_3") + ), + path = pathWithAny("Account_2") + ) + ) + ) + ) + } + private fun keysOf(vararg values: String): Set { return values.toList() .mapToSet { it.intoKey() } @@ -168,7 +219,7 @@ class ProxyGraphConstryctorTest { private fun makeSingleNode( accountId: String, permissionType: ProxyType = ProxyType.Any, - nestedNodes: MutableList = mutableListOf(), + nestedNodes: List = listOf(), path: Map = mapOf() ): MutableList { return mutableListOf(makeNode(accountId, permissionType, nestedNodes, path)) @@ -177,7 +228,7 @@ class ProxyGraphConstryctorTest { private fun makeNode( accountId: String, permissionType: ProxyType = ProxyType.Any, - nestedNodes: MutableList = mutableListOf(), + nestedNodes: List = listOf(), path: Map = mapOf() ): Node { return Node(accountId.intoKey(), permissionType, nestedNodes, path) From 864a2d219ac1c91db1c8be0842f19a3f84ab082c Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 22 Jan 2024 09:24:09 +0100 Subject: [PATCH 29/55] Update AddStakingProxyViewModel.kt --- .../staking/delegation/proxy/set/AddStakingProxyViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt index 7bfdbed1af..9789984be9 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/set/AddStakingProxyViewModel.kt @@ -25,7 +25,6 @@ import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationPayload import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.launchProxyDepositDescription import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload From 82543d452094675b1a95ce8b04ea35520f0d0093 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 22 Jan 2024 10:03:37 +0100 Subject: [PATCH 30/55] Fixed conflicts --- .../proxy/confirm/ConfirmAddStakingProxyViewModel.kt | 8 ++++---- .../proxy/confirm/di/ConfirmAddStakingProxyModule.kt | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt index 3a663a3486..b8bc34e012 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/ConfirmAddStakingProxyViewModel.kt @@ -5,6 +5,7 @@ import io.novafoundation.nova.common.base.BaseViewModel import io.novafoundation.nova.common.mixin.api.Validatable import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.flowOf +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher @@ -15,8 +16,7 @@ import io.novafoundation.nova.feature_account_api.domain.model.requireAddressIn import io.novafoundation.nova.feature_account_api.presenatation.account.icon.createAccountAddressModel import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions -import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity -import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.AddStakingProxyInteractor import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationPayload import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter @@ -51,7 +51,7 @@ class ConfirmAddStakingProxyViewModel( private val selectedAssetState: AnySelectedAssetOptionSharedState, private val assetUseCase: ArbitraryAssetUseCase, private val addStakingProxyValidationSystem: AddStakingProxyValidationSystem, - private val addStakingProxyRepository: AddStakingProxyRepository, + private val addStakingProxyInteractor: AddStakingProxyInteractor, private val walletUiUseCase: WalletUiUseCase, private val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, ) : BaseViewModel(), @@ -129,7 +129,7 @@ class ConfirmAddStakingProxyViewModel( } private fun sendTransaction(chain: Chain, proxiedAccount: AccountId, proxyAccount: AccountId) = launch { - val result = addStakingProxyRepository.addProxy(chain, proxiedAccount, proxyAccount) + val result = addStakingProxyInteractor.addProxy(chain, proxiedAccount, proxyAccount) validationProgressFlow.value = false diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt index 51754b8b39..1b6da604ad 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/confirm/di/ConfirmAddStakingProxyModule.kt @@ -15,7 +15,7 @@ import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBot import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.presenatation.account.wallet.WalletUiUseCase import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions -import io.novafoundation.nova.feature_staking_api.data.proxy.AddStakingProxyRepository +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.AddStakingProxyInteractor import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.confirm.ConfirmAddStakingProxyPayload @@ -39,7 +39,7 @@ class ConfirmAddStakingProxyModule { selectedAssetState: AnySelectedAssetOptionSharedState, assetUseCase: ArbitraryAssetUseCase, addStakingProxyValidationSystem: AddStakingProxyValidationSystem, - addStakingProxyRepository: AddStakingProxyRepository, + addStakingProxyRepository: AddStakingProxyInteractor, walletUiUseCase: WalletUiUseCase, descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, ): ViewModel { @@ -54,7 +54,7 @@ class ConfirmAddStakingProxyModule { selectedAssetState = selectedAssetState, assetUseCase = assetUseCase, addStakingProxyValidationSystem = addStakingProxyValidationSystem, - addStakingProxyRepository = addStakingProxyRepository, + addStakingProxyInteractor = addStakingProxyRepository, walletUiUseCase = walletUiUseCase, descriptionBottomSheetLauncher = descriptionBottomSheetLauncher ) From 2cd53711f337c5d1eb1bbce60ed81e15c1c7103f Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 22 Jan 2024 10:24:54 +0100 Subject: [PATCH 31/55] Update Declarations.kt --- .../domain/validations/delegation/proxy/Declarations.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt index 12e5fe1cff..80c0207774 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/Declarations.kt @@ -90,8 +90,8 @@ fun AddStakingProxyValidationSystemBuilder.stakingTypeIsNotDuplication( ) = proxyIsNotDuplicationForAccount( chain = { it.chain }, proxiedAccountId = { it.proxiedAccountId }, - proxyAccountId = { it.chain.accountIdOf(it.address) }, + proxyAccountId = { it.chain.accountIdOf(it.proxyAddress) }, proxyType = { ProxyType.Staking }, - error = { payload -> AddStakingProxyValidationFailure.AlreadyDelegated(payload.address) }, + error = { payload -> AddStakingProxyValidationFailure.AlreadyDelegated(payload.proxyAddress) }, proxyRepository = proxyRepository ) From ca55e01ec940e2a6deaacd443d7b09c780015c00 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 22 Jan 2024 11:28:14 +0100 Subject: [PATCH 32/55] Fixed pr notes --- .../di/modules/IdentityProviderModule.kt | 6 ++- .../account/identity/LocalIdentityProvider.kt | 20 ++++++++- .../di/StakingFeatureDependencies.kt | 5 +++ .../di/StakingFeatureModule.kt | 13 +++--- .../list/RealStakingProxyListInteractor.kt | 42 +++++++++++++++++++ .../proxy/list/StakingProxyListInteractor.kt | 40 ------------------ .../proxy/list/model/StakingProxyAccount.kt | 2 +- .../proxy/list/StakingProxyListViewModel.kt | 3 +- .../proxy/list/di/StakingProxyListModule.kt | 1 + 9 files changed, 82 insertions(+), 50 deletions(-) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt delete mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/modules/IdentityProviderModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/modules/IdentityProviderModule.kt index 61d88e2056..f39c44dfb8 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/modules/IdentityProviderModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/modules/IdentityProviderModule.kt @@ -9,6 +9,7 @@ import io.novafoundation.nova.feature_account_api.domain.account.identity.OnChai import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_impl.domain.account.identity.LocalIdentityProvider import io.novafoundation.nova.feature_account_impl.domain.account.identity.OnChainIdentityProvider +import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry @Module class IdentityProviderModule { @@ -16,9 +17,10 @@ class IdentityProviderModule { @Provides @LocalIdentity fun provideLocalIdentityProvider( - accountRepository: AccountRepository + accountRepository: AccountRepository, + chainRegistry: ChainRegistry ): IdentityProvider { - return LocalIdentityProvider(accountRepository) + return LocalIdentityProvider(accountRepository, chainRegistry) } @Provides diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/account/identity/LocalIdentityProvider.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/account/identity/LocalIdentityProvider.kt index df37cdfd74..95ce1009d1 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/account/identity/LocalIdentityProvider.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/domain/account/identity/LocalIdentityProvider.kt @@ -1,15 +1,21 @@ package io.novafoundation.nova.feature_account_impl.domain.account.identity +import io.novafoundation.nova.common.address.AccountIdKey +import io.novafoundation.nova.common.address.intoKey import io.novafoundation.nova.feature_account_api.domain.account.identity.Identity import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext class LocalIdentityProvider( - private val accountRepository: AccountRepository + private val accountRepository: AccountRepository, + private val chainRegistry: ChainRegistry ) : IdentityProvider { override suspend fun identityFor(accountId: AccountId, chainId: ChainId): Identity? = withContext(Dispatchers.IO) { @@ -17,4 +23,16 @@ class LocalIdentityProvider( name?.let(::Identity) } + + override suspend fun identitiesFor(accountIds: Collection, chainId: ChainId): Map { + val chain = chainRegistry.getChain(chainId) + val metaAccounts = accountRepository.activeMetaAccounts() + .filter { it.hasAccountIn(chain) } + .associateBy { it.requireAccountIdIn(chain).intoKey() } + + return accountIds.associateBy { it.intoKey() } + .mapValues { (key, _) -> + metaAccounts[key]?.name?.let(::Identity) + } + } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt index 74eee825dd..e68d23defa 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt @@ -25,6 +25,8 @@ import io.novafoundation.nova.core_db.dao.StakingRewardPeriodDao import io.novafoundation.nova.core_db.dao.StakingTotalRewardDao import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository +import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider +import io.novafoundation.nova.feature_account_api.domain.account.identity.LocalIdentity import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase @@ -114,6 +116,9 @@ interface StakingFeatureDependencies { @Named(LOCAL_STORAGE_SOURCE) fun localStorageSource(): StorageDataSource + @LocalIdentity + fun localIdentity(): IdentityProvider + fun chainRegistry(): ChainRegistry fun imageLoader(): ImageLoader diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt index bc0977e5c8..b36f1ba622 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt @@ -16,6 +16,8 @@ import io.novafoundation.nova.core_db.dao.StakingRewardPeriodDao import io.novafoundation.nova.core_db.dao.StakingTotalRewardDao import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository +import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider +import io.novafoundation.nova.feature_account_api.domain.account.identity.LocalIdentity import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.updaters.AccountUpdateScope import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase @@ -79,6 +81,7 @@ import io.novafoundation.nova.feature_staking_impl.domain.rewards.RewardCalculat import io.novafoundation.nova.feature_staking_impl.domain.setup.ChangeValidatorsInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.bond.BondMoreInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.controller.ControllerInteractor +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.RealStakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.StakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.rebond.RebondInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.redeem.RedeemInteractor @@ -625,10 +628,10 @@ class StakingFeatureModule { @Provides @FeatureScope fun provideStakingProxyListInteractor( - accountRepository: AccountRepository, - getProxyRepository: GetProxyRepository - ) = StakingProxyListInteractor( - accountRepository, - getProxyRepository + getProxyRepository: GetProxyRepository, + @LocalIdentity identityProvider: IdentityProvider + ): StakingProxyListInteractor = RealStakingProxyListInteractor( + getProxyRepository, + identityProvider ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt new file mode 100644 index 0000000000..76fca5a9dc --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt @@ -0,0 +1,42 @@ +package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list + +import io.novafoundation.nova.common.address.intoKey +import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn +import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.model.StakingProxyAccount +import io.novafoundation.nova.runtime.ext.addressOf +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import jp.co.soramitsu.fearless_utils.runtime.AccountId +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map + +interface StakingProxyListInteractor { + fun stakingProxyListFlow(chain: Chain, accountId: AccountId): Flow> +} + +class RealStakingProxyListInteractor( + val getProxyRepository: GetProxyRepository, + val identityProvider: IdentityProvider +) : StakingProxyListInteractor { + + override fun stakingProxyListFlow(chain: Chain, accountId: AccountId): Flow> { + return getProxyRepository.proxiesByTypeFlow(chain, accountId, ProxyType.Staking) + .map { proxies -> + val proxiesAccountIds = proxies.map { it.accountId } + val proxyIdentities = identityProvider.identitiesFor(proxiesAccountIds, chain.id) + proxies.map { proxy -> + val proxyAccountId = proxy.accountId + val identity = proxyIdentities[proxyAccountId.intoKey()] + StakingProxyAccount( + identity?.name ?: chain.addressOf(proxyAccountId), + proxyAccountId + ) + } + } + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt deleted file mode 100644 index e24e991ed5..0000000000 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/StakingProxyListInteractor.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list - -import io.novafoundation.nova.common.address.intoKey -import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository -import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn -import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn -import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository -import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType -import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.model.StakingProxyAccount -import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain -import jp.co.soramitsu.fearless_utils.runtime.AccountId -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine - -class StakingProxyListInteractor( - val accountRepository: AccountRepository, - val getProxyRepository: GetProxyRepository -) { - - fun stakingProxyListFlow(chain: Chain, accountId: AccountId): Flow> { - return combine( - accountRepository.activeMetaAccountsFlow(), - getProxyRepository.proxiesByTypeFlow(chain, accountId, ProxyType.Staking) - ) { metaAccounts, proxies -> - val accountIdToMetaAccount = metaAccounts - .filter { it.hasAccountIn(chain) } - .associateBy { - it.requireAccountIdIn(chain).intoKey() - } - - proxies.map { proxy -> - val proxyAccountId = proxy.accountId - StakingProxyAccount( - accountIdToMetaAccount[proxyAccountId.intoKey()], - proxyAccountId - ) - } - } - } -} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt index 4c182c6cd4..f704182911 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt @@ -4,6 +4,6 @@ import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import jp.co.soramitsu.fearless_utils.runtime.AccountId class StakingProxyAccount( - val metaAccount: MetaAccount?, + val accountName: String, val proxyAccountId: AccountId ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt index bf01eeb996..4036420d28 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt @@ -9,6 +9,7 @@ import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdI import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.actions.showAddressActions import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.RealStakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.StakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.model.StakingProxyAccount import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter @@ -76,7 +77,7 @@ class StakingProxyListViewModel( StakingProxyRvItem( addressIconGenerator.createAddressIcon(stakingProxyAccount.proxyAccountId, SIZE_BIG), chain.icon, - stakingProxyAccount.metaAccount?.name ?: accountAddress, + stakingProxyAccount.accountName, accountAddress ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt index 9817146824..71477ba3f8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt @@ -12,6 +12,7 @@ import io.novafoundation.nova.common.di.viewmodel.ViewModelModule import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions +import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.RealStakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.StakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.StakingProxyListViewModel From 533f54e3db90732519f68175c26464e1f0270958 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 22 Jan 2024 11:30:08 +0100 Subject: [PATCH 33/55] Run ktlint --- .../delegation/proxy/list/RealStakingProxyListInteractor.kt | 4 ---- .../delegation/proxy/list/model/StakingProxyAccount.kt | 1 - .../delegation/proxy/list/StakingProxyListViewModel.kt | 1 - .../delegation/proxy/list/di/StakingProxyListModule.kt | 1 - 4 files changed, 7 deletions(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt index 76fca5a9dc..3569dfa541 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt @@ -2,9 +2,6 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.pr import io.novafoundation.nova.common.address.intoKey import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider -import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository -import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn -import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.model.StakingProxyAccount @@ -12,7 +9,6 @@ import io.novafoundation.nova.runtime.ext.addressOf import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map interface StakingProxyListInteractor { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt index f704182911..4361f339a4 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/model/StakingProxyAccount.kt @@ -1,6 +1,5 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.model -import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import jp.co.soramitsu.fearless_utils.runtime.AccountId class StakingProxyAccount( diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt index 4036420d28..07a0aea1fc 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/StakingProxyListViewModel.kt @@ -9,7 +9,6 @@ import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdI import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.actions.showAddressActions import io.novafoundation.nova.feature_staking_impl.R -import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.RealStakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.StakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.model.StakingProxyAccount import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt index 71477ba3f8..9817146824 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/list/di/StakingProxyListModule.kt @@ -12,7 +12,6 @@ import io.novafoundation.nova.common.di.viewmodel.ViewModelModule import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions -import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.RealStakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list.StakingProxyListInteractor import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.list.StakingProxyListViewModel From b2b4ebf2e8761b8051b191c7fdba1d7a36a45e99 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 22 Jan 2024 11:44:38 +0100 Subject: [PATCH 34/55] Update ConfirmRemoveStakingProxyViewModel.kt --- .../proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt index eb6ac505eb..60264a6088 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt @@ -145,9 +145,10 @@ class ConfirmRemoveStakingProxyViewModel( validationProgressFlow.value = false - if (result.isSuccess) { + result.onSuccess { router.returnToStakingMain() } + .onFailure(::showError) } private suspend fun generateAccountAddressModel(chain: Chain, address: String) = addressIconGenerator.createAccountAddressModel( From b19a0eaa3880e5730400709954463dd6d3a6a155 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Mon, 22 Jan 2024 16:49:38 +0100 Subject: [PATCH 35/55] Fix conflicts --- common/src/main/res/values/strings.xml | 1 - .../domain/interfaces/AccountRepository.kt | 3 +-- .../data/repository/AccountRepositoryImpl.kt | 5 +---- .../data/signer/proxy/ProxiedSigner.kt | 2 -- .../di/AccountFeatureModule.kt | 14 ++------------ 5 files changed, 4 insertions(+), 21 deletions(-) diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index b14261b820..337ff399e0 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -47,7 +47,6 @@ %1$s has not delegated %2$s - Delegated account %s doesn\'t have enough balance to pay the network fee of %s. Available balance to pay fee: %s Not enough tokens to pay the fee This account granted access to perform transactions to the following account: diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/AccountRepository.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/AccountRepository.kt index c6195385e8..bfd15480ea 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/AccountRepository.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/interfaces/AccountRepository.kt @@ -4,6 +4,7 @@ import io.novafoundation.nova.core.model.CryptoType import io.novafoundation.nova.core.model.Language import io.novafoundation.nova.core.model.Node import io.novafoundation.nova.feature_account_api.domain.model.Account +import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountAssetBalance import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountOrdering @@ -43,8 +44,6 @@ interface AccountRepository { suspend fun activeMetaAccounts(): List - suspend fun hasMetaAccounts(): Boolean - suspend fun allLightMetaAccounts(): List suspend fun hasActiveMetaAccounts(): Boolean diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/AccountRepositoryImpl.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/AccountRepositoryImpl.kt index aa9fdc181b..0d2375bed3 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/AccountRepositoryImpl.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/repository/AccountRepositoryImpl.kt @@ -18,6 +18,7 @@ import io.novafoundation.nova.feature_account_api.data.secrets.keypair import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.model.Account import io.novafoundation.nova.feature_account_api.domain.model.AuthType +import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountAssetBalance import io.novafoundation.nova.feature_account_api.domain.model.MetaAccountOrdering @@ -125,10 +126,6 @@ class AccountRepositoryImpl( return accountDataSource.activeMetaAccounts() } - override suspend fun hasMetaAccounts(): Boolean { - return accountDataSource.hasMetaAccounts() - } - override suspend fun allLightMetaAccounts(): List { return accountDataSource.allLightMetaAccounts() } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt index b4bbc3629f..a38931fefe 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt @@ -4,8 +4,6 @@ import io.novafoundation.nova.common.base.errors.SigningCancelledException import io.novafoundation.nova.common.utils.chainId import io.novafoundation.nova.common.utils.toCallInstance import io.novafoundation.nova.common.validation.ValidationStatus -import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxiedExtrinsicValidationFailure.ProxyNotEnoughFee -import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxiedExtrinsicValidationPayload import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxyExtrinsicValidationRequestBus import io.novafoundation.nova.feature_account_api.data.signer.SignerProvider import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt index 7d15c3e041..5d12bfd469 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/di/AccountFeatureModule.kt @@ -31,9 +31,6 @@ import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository import io.novafoundation.nova.feature_account_api.data.repository.addAccount.proxied.ProxiedAddAccountRepository import io.novafoundation.nova.feature_account_api.data.signer.SignerProvider -import io.novafoundation.nova.feature_account_api.domain.account.common.EncryptionDefaults -import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider -import io.novafoundation.nova.feature_account_api.domain.account.identity.OnChainIdentity import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountInteractor import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor @@ -61,8 +58,6 @@ import io.novafoundation.nova.feature_account_impl.data.proxy.RealMetaAccountsUp import io.novafoundation.nova.feature_account_impl.data.proxy.RealProxySyncService import io.novafoundation.nova.feature_account_impl.data.repository.AccountRepositoryImpl import io.novafoundation.nova.feature_account_impl.data.repository.RealOnChainIdentityRepository -import io.novafoundation.nova.feature_account_impl.data.repository.RealProxyRepository -import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.proxied.ProxiedAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.JsonAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.MnemonicAddAccountRepository import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.SeedAddAccountRepository @@ -86,12 +81,6 @@ import io.novafoundation.nova.feature_account_api.domain.account.identity.Identi import io.novafoundation.nova.feature_account_api.domain.account.identity.OnChainIdentity import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressCommunicator import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin -import io.novafoundation.nova.feature_account_impl.data.proxy.RealMetaAccountsUpdatesRegistry -import io.novafoundation.nova.feature_account_impl.data.proxy.RealProxySyncService -import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.JsonAddAccountRepository -import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.MnemonicAddAccountRepository -import io.novafoundation.nova.feature_account_impl.data.repository.addAccount.secrets.SeedAddAccountRepository -import io.novafoundation.nova.feature_account_impl.di.modules.ProxySigningModule import io.novafoundation.nova.feature_account_impl.domain.account.details.WalletDetailsInteractor import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter import io.novafoundation.nova.feature_account_impl.presentation.account.common.listing.DelegatedMetaAccountUpdatesListingMixinFactory @@ -511,7 +500,8 @@ class AccountFeatureModule { identityProvider, metaAccountsUpdatesRegistry, proxiedAddAccountRepository, - rootScope + rootScope, + shouldSyncWatchOnlyProxies = BuildConfig.DEBUG ) @Provides From e90976fcadb1fe40ef262abf76ee42b0bb8ddbc6 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 23 Jan 2024 03:47:33 +0100 Subject: [PATCH 36/55] Fix pr notes --- .../domain/validators/ProxyIsNotDuplicationForAccount.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt index 430c1edc14..f58f0a4738 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt @@ -20,7 +20,7 @@ class ProxyIsNotDuplicationForAccount( override suspend fun validate(value: P): ValidationStatus { val chain = chain(value) - val proxyTypes = proxyRepository.getDelegatedProxyTypes(chain.id, proxiedAccountId(value), proxyAccountId(value)) + val proxyTypes = proxyRepository.getDelegatedProxyTypesLocal(chain.id, proxiedAccountId(value), proxyAccountId(value)) return validOrError(proxyTypes.contains(proxyType(value))) { error(value) From 83d4130566eee3e20c82b10b249ca5e4b126767d Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 23 Jan 2024 03:57:52 +0100 Subject: [PATCH 37/55] Update AddStakingProxyValidationsModule.kt --- .../di/validations/AddStakingProxyValidationsModule.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt index 697bd585d3..49ff7ff08d 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt @@ -8,7 +8,7 @@ import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyReposito import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.enoughBalanceToPayDeposit import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.maximumProxies -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.stakingTypeIsNotDuplication +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.stakingTypeIsNotDuplication import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.sufficientBalanceToPayFee import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.sufficientBalanceToStayAboveEd import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.validAddress From 5b6a178dd349f99c112b084587479ce6545f4179 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 23 Jan 2024 04:12:17 +0100 Subject: [PATCH 38/55] Update ProxyIsNotDuplicationForAccount.kt --- .../domain/validators/ProxyIsNotDuplicationForAccount.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt index f58f0a4738..fbf78225a8 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/ProxyIsNotDuplicationForAccount.kt @@ -22,7 +22,7 @@ class ProxyIsNotDuplicationForAccount( val chain = chain(value) val proxyTypes = proxyRepository.getDelegatedProxyTypesLocal(chain.id, proxiedAccountId(value), proxyAccountId(value)) - return validOrError(proxyTypes.contains(proxyType(value))) { + return validOrError(!proxyTypes.contains(proxyType(value))) { error(value) } } From 04066a9789f48e53ac178521b995a8d29be30fb3 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 23 Jan 2024 13:09:24 +0100 Subject: [PATCH 39/55] Change proxy deposit amount view --- .../ChooseDelegationAmountValidationSystem.kt | 2 +- .../RemoveVotesValidationSystem.kt | 2 +- .../RevokeDelegationValidationSystem.kt | 2 +- .../VoteReferendumValidationSystem.kt | 2 +- .../VoteReferendumValidationSystem.kt | 2 +- .../data/common/DepositBaseAndFactor.kt | 8 +++ .../data/common/ProxyDepositCalculator.kt | 11 +--- .../repository/ProxyConstantsRepository.kt | 9 +++ .../feature_proxy_api/di/ProxyFeatureApi.kt | 3 + .../domain/model/ProxyDepositWithQuantity.kt | 8 --- ...EnoughAmountToPayProxyDepositValidation.kt | 56 ------------------- .../data/common/RealProxyDepositCalculator.kt | 24 ++++---- .../RealProxyConstantsRepository.kt | 23 ++++++++ .../di/ProxyFeatureModule.kt | 17 +++++- .../di/StakingFeatureDependencies.kt | 3 + .../di/StakingFeatureModule.kt | 7 ++- .../AddStakingProxyValidationsModule.kt | 4 +- .../validations/RebagValidationSystem.kt | 2 +- .../claimRewards/validations/Declarations.kt | 2 +- .../redeem/validations/Declarations.kt | 2 +- .../unbond/validations/Declarations.kt | 2 +- .../validations/ValidationSystem.kt | 2 +- .../proxy/AddStakingProxyInteractor.kt | 4 +- .../proxy/RealAddStakingProxyInteractor.kt | 16 +++--- .../direct/DirectStakingProperties.kt | 2 +- .../add/AddStakingProxyValidationPayload.kt | 5 +- .../delegation/proxy/add/Declarations.kt | 31 +++++----- .../delegation/proxy/remove/Declarations.kt | 2 +- .../confirm/ConfirmAddStakingProxyPayload.kt | 4 +- .../ConfirmAddStakingProxyViewModel.kt | 9 +-- .../proxy/add/set/AddStakingProxyViewModel.kt | 22 +++++--- .../proxy/add/set/di/AddStakingProxyModule.kt | 7 ++- .../feature_wallet_api/domain/model/Asset.kt | 1 + .../EnoughAmountToTransferValidation.kt | 2 +- .../assets/transfers/validations/Common.kt | 2 +- 35 files changed, 147 insertions(+), 153 deletions(-) create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/DepositBaseAndFactor.kt create mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/ProxyConstantsRepository.kt delete mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyDepositWithQuantity.kt delete mode 100644 feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt create mode 100644 feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealProxyConstantsRepository.kt diff --git a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/create/chooseAmount/validation/ChooseDelegationAmountValidationSystem.kt b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/create/chooseAmount/validation/ChooseDelegationAmountValidationSystem.kt index ee76c93548..acd7086dee 100644 --- a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/create/chooseAmount/validation/ChooseDelegationAmountValidationSystem.kt +++ b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/create/chooseAmount/validation/ChooseDelegationAmountValidationSystem.kt @@ -23,7 +23,7 @@ fun ValidationSystem.Companion.chooseDelegationAmount( error = { context -> ChooseDelegationAmountValidationFailure.NotEnoughToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/removeVotes/validations/RemoveVotesValidationSystem.kt b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/removeVotes/validations/RemoveVotesValidationSystem.kt index 076c4245dc..7b94f54a97 100644 --- a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/removeVotes/validations/RemoveVotesValidationSystem.kt +++ b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/removeVotes/validations/RemoveVotesValidationSystem.kt @@ -12,7 +12,7 @@ fun ValidationSystem.Companion.removeVotesValidationSystem(): RemoteVotesValidat error = { context -> RemoveVotesValidationFailure.NotEnoughToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/revoke/validations/RevokeDelegationValidationSystem.kt b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/revoke/validations/RevokeDelegationValidationSystem.kt index 285a4d789b..9f8ea83016 100644 --- a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/revoke/validations/RevokeDelegationValidationSystem.kt +++ b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/delegation/delegation/revoke/validations/RevokeDelegationValidationSystem.kt @@ -12,7 +12,7 @@ fun ValidationSystem.Companion.revokeDelegationValidationSystem(): RevokeDelegat error = { context -> RevokeDelegationValidationFailure.NotEnoughToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/referendum/unlock/validations/VoteReferendumValidationSystem.kt b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/referendum/unlock/validations/VoteReferendumValidationSystem.kt index 10dc1400fa..2eeb2ae956 100644 --- a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/referendum/unlock/validations/VoteReferendumValidationSystem.kt +++ b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/referendum/unlock/validations/VoteReferendumValidationSystem.kt @@ -12,7 +12,7 @@ fun ValidationSystem.Companion.unlockReferendumValidationSystem(): UnlockReferen error = { context -> UnlockGovernanceValidationFailure.NotEnoughToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/referendum/vote/validations/VoteReferendumValidationSystem.kt b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/referendum/vote/validations/VoteReferendumValidationSystem.kt index f33fd17562..a5da04c2c5 100644 --- a/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/referendum/vote/validations/VoteReferendumValidationSystem.kt +++ b/feature-governance-impl/src/main/java/io/novafoundation/nova/feature_governance_impl/domain/referendum/vote/validations/VoteReferendumValidationSystem.kt @@ -29,7 +29,7 @@ fun ValidationSystem.Companion.voteReferendumValidationSystem( error = { context -> VoteReferendumValidationFailure.NotEnoughToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/DepositBaseAndFactor.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/DepositBaseAndFactor.kt new file mode 100644 index 0000000000..55442f8855 --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/DepositBaseAndFactor.kt @@ -0,0 +1,8 @@ +package io.novafoundation.nova.feature_proxy_api.data.common + +import java.math.BigInteger + +class DepositBaseAndFactor( + val baseAmount: BigInteger, + val factorAmount: BigInteger +) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt index 02830fa441..736e184496 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/common/ProxyDepositCalculator.kt @@ -1,16 +1,11 @@ package io.novafoundation.nova.feature_proxy_api.data.common -import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import java.math.BigInteger -class DepositBaseAndFactor( - val baseAmount: BigInteger, - val factorAmount: BigInteger -) - interface ProxyDepositCalculator { - suspend fun getDepositConstants(chain: Chain): DepositBaseAndFactor - fun calculateProxyDepositForQuantity(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger + + suspend fun calculateProxyDepositForQuantity(chainId: ChainId, proxiesCount: Int): BigInteger } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/ProxyConstantsRepository.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/ProxyConstantsRepository.kt new file mode 100644 index 0000000000..010519ac0d --- /dev/null +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/data/repository/ProxyConstantsRepository.kt @@ -0,0 +1,9 @@ +package io.novafoundation.nova.feature_proxy_api.data.repository + +import io.novafoundation.nova.feature_proxy_api.data.common.DepositBaseAndFactor +import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId + +interface ProxyConstantsRepository { + + suspend fun getDepositConstants(chainId: ChainId): DepositBaseAndFactor +} diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/di/ProxyFeatureApi.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/di/ProxyFeatureApi.kt index 12ed8cdf61..cebeb79969 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/di/ProxyFeatureApi.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/di/ProxyFeatureApi.kt @@ -2,10 +2,13 @@ package io.novafoundation.nova.feature_proxy_api.di import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository interface ProxyFeatureApi { val proxyRepository: GetProxyRepository val proxyDepositCalculator: ProxyDepositCalculator + + val proxyConstantsRepository: ProxyConstantsRepository } diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyDepositWithQuantity.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyDepositWithQuantity.kt deleted file mode 100644 index c4d26b6f2d..0000000000 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/model/ProxyDepositWithQuantity.kt +++ /dev/null @@ -1,8 +0,0 @@ -package io.novafoundation.nova.feature_proxy_api.domain.model - -import java.math.BigInteger - -class ProxyDepositWithQuantity( - val deposit: BigInteger, - val quantity: Int -) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt deleted file mode 100644 index 25582b7043..0000000000 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/EnoughAmountToPayProxyDepositValidation.kt +++ /dev/null @@ -1,56 +0,0 @@ -package io.novafoundation.nova.feature_proxy_api.domain.validators - -import io.novafoundation.nova.common.utils.atLeastZero -import io.novafoundation.nova.common.validation.Validation -import io.novafoundation.nova.common.validation.ValidationStatus -import io.novafoundation.nova.common.validation.ValidationSystemBuilder -import io.novafoundation.nova.common.validation.validOrError -import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository -import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain -import java.math.BigInteger -import jp.co.soramitsu.fearless_utils.runtime.AccountId - -class EnoughAmountToPayProxyDepositValidation( - private val chain: (P) -> Chain, - private val accountId: (P) -> AccountId, - private val newDeposit: (P) -> BigInteger, - private val availableBalance: (P) -> BigInteger, - private val feeReceiver: (P) -> BigInteger, - private val error: (P, BigInteger) -> E, - private val proxyRepository: GetProxyRepository -) : Validation { - - override suspend fun validate(value: P): ValidationStatus { - val availableBalance = availableBalance(value) - val currentDeposit = proxyRepository.getProxyDeposit(chain(value).id, accountId(value)) - - val deltaDeposit = (newDeposit(value) - currentDeposit).atLeastZero() - val fee = feeReceiver(value) - - return validOrError(deltaDeposit + fee <= availableBalance) { - error(value, availableBalance) - } - } -} - -fun ValidationSystemBuilder.enoughBalanceToPayProxyDeposit( - chain: (P) -> Chain, - accountId: (P) -> AccountId, - newDeposit: (P) -> BigInteger, - availableBalance: (P) -> BigInteger, - error: (P, BigInteger) -> E, - proxyRepository: GetProxyRepository, - feeReceiver: (P) -> BigInteger, -) { - validate( - EnoughAmountToPayProxyDepositValidation( - chain = chain, - accountId = accountId, - newDeposit = newDeposit, - availableBalance = availableBalance, - error = error, - proxyRepository = proxyRepository, - feeReceiver = feeReceiver, - ) - ) -} diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt index 824b1fb246..9b81e15f2b 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/common/RealProxyDepositCalculator.kt @@ -1,27 +1,17 @@ package io.novafoundation.nova.feature_proxy_impl.data.common -import io.novafoundation.nova.common.utils.numberConstant -import io.novafoundation.nova.common.utils.proxy import io.novafoundation.nova.feature_proxy_api.data.common.DepositBaseAndFactor import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator +import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry -import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain -import io.novafoundation.nova.runtime.multiNetwork.getRuntime +import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId import java.math.BigInteger class RealProxyDepositCalculator( - private val chainRegestry: ChainRegistry + private val chainRegestry: ChainRegistry, + private val proxyConstantsRepository: ProxyConstantsRepository ) : ProxyDepositCalculator { - override suspend fun getDepositConstants(chain: Chain): DepositBaseAndFactor { - val runtime = chainRegestry.getRuntime(chain.id) - val constantQuery = runtime.metadata.proxy() - return DepositBaseAndFactor( - baseAmount = constantQuery.numberConstant("ProxyDepositBase", runtime), - factorAmount = constantQuery.numberConstant("ProxyDepositFactor", runtime) - ) - } - override fun calculateProxyDepositForQuantity(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger { return if (proxiesCount == 0) { BigInteger.ZERO @@ -29,4 +19,10 @@ class RealProxyDepositCalculator( baseAndFactor.baseAmount + baseAndFactor.factorAmount * proxiesCount.toBigInteger() } } + + override suspend fun calculateProxyDepositForQuantity(chainId: ChainId, proxiesCount: Int): BigInteger { + val depositAndFactor = proxyConstantsRepository.getDepositConstants(chainId) + + return calculateProxyDepositForQuantity(depositAndFactor, proxiesCount) + } } diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealProxyConstantsRepository.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealProxyConstantsRepository.kt new file mode 100644 index 0000000000..c0209740d6 --- /dev/null +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/data/repository/RealProxyConstantsRepository.kt @@ -0,0 +1,23 @@ +package io.novafoundation.nova.feature_proxy_impl.data.repository + +import io.novafoundation.nova.common.utils.numberConstant +import io.novafoundation.nova.common.utils.proxy +import io.novafoundation.nova.feature_proxy_api.data.common.DepositBaseAndFactor +import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository +import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry +import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId +import io.novafoundation.nova.runtime.multiNetwork.getRuntime + +class RealProxyConstantsRepository( + private val chainRegestry: ChainRegistry +) : ProxyConstantsRepository { + + override suspend fun getDepositConstants(chainId: ChainId): DepositBaseAndFactor { + val runtime = chainRegestry.getRuntime(chainId) + val constantQuery = runtime.metadata.proxy() + return DepositBaseAndFactor( + baseAmount = constantQuery.numberConstant("ProxyDepositBase", runtime), + factorAmount = constantQuery.numberConstant("ProxyDepositFactor", runtime) + ) + } +} diff --git a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt index 2288e1cf4a..a73d53db6d 100644 --- a/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt +++ b/feature-proxy-impl/src/main/java/io/novafoundation/nova/feature_proxy_impl/di/ProxyFeatureModule.kt @@ -5,8 +5,10 @@ import dagger.Provides import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository import io.novafoundation.nova.feature_proxy_impl.data.common.RealProxyDepositCalculator import io.novafoundation.nova.feature_proxy_impl.data.repository.RealGetProxyRepository +import io.novafoundation.nova.feature_proxy_impl.data.repository.RealProxyConstantsRepository import io.novafoundation.nova.runtime.di.LOCAL_STORAGE_SOURCE import io.novafoundation.nova.runtime.di.REMOTE_STORAGE_SOURCE import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry @@ -30,7 +32,18 @@ class ProxyFeatureModule { @Provides @FeatureScope - fun provideProxyDepositCalculator(chainRegistry: ChainRegistry): ProxyDepositCalculator { - return RealProxyDepositCalculator(chainRegistry) + fun provideProxyConstantsRepository( + chainRegistry: ChainRegistry + ): ProxyConstantsRepository = RealProxyConstantsRepository( + chainRegistry + ) + + @Provides + @FeatureScope + fun provideProxyDepositCalculator( + chainRegistry: ChainRegistry, + proxyConstantsRepository: ProxyConstantsRepository + ): ProxyDepositCalculator { + return RealProxyDepositCalculator(chainRegistry, proxyConstantsRepository) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt index 99aa5ec0eb..30a1e4b889 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt @@ -40,6 +40,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddr import io.novafoundation.nova.feature_dapp_api.data.repository.DAppMetadataRepository import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository import io.novafoundation.nova.feature_wallet_api.data.cache.AssetCache import io.novafoundation.nova.feature_wallet_api.data.repository.BalanceLocksRepository import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase @@ -186,4 +187,6 @@ interface StakingFeatureDependencies { val metaAccountGroupingInteractor: MetaAccountGroupingInteractor val selectAddressMixinFactory: SelectAddressMixin.Factory + + val proxyConstantsRepository: ProxyConstantsRepository } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt index f0dadf8e26..be8765d9ba 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt @@ -23,6 +23,7 @@ import io.novafoundation.nova.feature_account_api.domain.updaters.AccountUpdateS import io.novafoundation.nova.feature_account_api.presenatation.account.AddressDisplayUseCase import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository +import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository import io.novafoundation.nova.feature_staking_api.data.network.blockhain.updaters.PooledBalanceUpdaterFactory import io.novafoundation.nova.feature_staking_api.data.nominationPools.pool.PoolAccountDerivation import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.AddStakingProxyInteractor @@ -618,12 +619,14 @@ class StakingFeatureModule { fun provideAddProxyRepository( extrinsicService: ExtrinsicService, proxyDepositCalculator: ProxyDepositCalculator, - getProxyRepository: GetProxyRepository + getProxyRepository: GetProxyRepository, + proxyConstantsRepository: ProxyConstantsRepository ): AddStakingProxyInteractor { return RealAddStakingProxyInteractor( extrinsicService, proxyDepositCalculator, - getProxyRepository + getProxyRepository, + proxyConstantsRepository ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt index 49ff7ff08d..d247ae152e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt @@ -6,7 +6,7 @@ import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.common.validation.ValidationSystem import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.AddStakingProxyValidationSystem -import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.enoughBalanceToPayDeposit +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.enoughBalanceToPayDepositAndFee import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.maximumProxies import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.stakingTypeIsNotDuplication import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.sufficientBalanceToPayFee @@ -33,6 +33,6 @@ class AddStakingProxyValidationsModule { maximumProxies(getProxyRepository) - enoughBalanceToPayDeposit(getProxyRepository) + enoughBalanceToPayDepositAndFee() } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/bagList/rebag/validations/RebagValidationSystem.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/bagList/rebag/validations/RebagValidationSystem.kt index d871e1a84d..6c165a438a 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/bagList/rebag/validations/RebagValidationSystem.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/bagList/rebag/validations/RebagValidationSystem.kt @@ -12,7 +12,7 @@ fun ValidationSystem.Companion.rebagValidationSystem(): RebagValidationSystem = error = { context -> RebagValidationFailure.NotEnoughToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/claimRewards/validations/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/claimRewards/validations/Declarations.kt index d38c4dd878..4337303a81 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/claimRewards/validations/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/claimRewards/validations/Declarations.kt @@ -44,7 +44,7 @@ private fun NominationPoolsClaimRewardsValidationSystemBuilder.enoughToPayFees() error = { context -> NominationPoolsClaimRewardsValidationFailure.NotEnoughBalanceToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/redeem/validations/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/redeem/validations/Declarations.kt index 122a82aa81..9ff505d945 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/redeem/validations/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/redeem/validations/Declarations.kt @@ -26,7 +26,7 @@ private fun NominationPoolsRedeemValidationSystemBuilder.enoughToPayFees() { error = { context -> NominationPoolsRedeemValidationFailure.NotEnoughBalanceToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/unbond/validations/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/unbond/validations/Declarations.kt index 2da505dcf3..c866a640da 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/unbond/validations/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/unbond/validations/Declarations.kt @@ -43,7 +43,7 @@ private fun NominationPoolsUnbondValidationSystemBuilder.enoughToPayFees() { error = { context -> NominationPoolsUnbondValidationFailure.NotEnoughBalanceToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/parachainStaking/yieldBoost/validations/ValidationSystem.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/parachainStaking/yieldBoost/validations/ValidationSystem.kt index 19c494f6de..951755dded 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/parachainStaking/yieldBoost/validations/ValidationSystem.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/parachainStaking/yieldBoost/validations/ValidationSystem.kt @@ -19,7 +19,7 @@ fun ValidationSystem.Companion.yieldBoost( error = { context -> YieldBoostValidationFailure.NotEnoughToPayToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt index 32bde7ffa4..5fb2d99b51 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt @@ -2,7 +2,7 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.pr import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.model.Fee -import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity +import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId @@ -12,5 +12,5 @@ interface AddStakingProxyInteractor { suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result - suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): ProxyDepositWithQuantity + suspend fun calculateDeltaDepositForAddProxy(chain: Chain, accountId: AccountId): Balance } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt index 2e0c1ba67c..06e303d9fa 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt @@ -7,8 +7,9 @@ import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_proxy_api.data.calls.addProxyCall import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository -import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity +import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType +import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.runtime.ext.emptyAccountId import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId @@ -18,7 +19,8 @@ import kotlinx.coroutines.withContext class RealAddStakingProxyInteractor( private val extrinsicService: ExtrinsicService, private val proxyDepositCalculator: ProxyDepositCalculator, - private val getProxyRepository: GetProxyRepository + private val getProxyRepository: GetProxyRepository, + private val proxyConstantsRepository: ProxyConstantsRepository ) : AddStakingProxyInteractor { override suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee { @@ -37,11 +39,11 @@ class RealAddStakingProxyInteractor( } } - override suspend fun calculateDepositForAddProxy(chain: Chain, accountId: AccountId): ProxyDepositWithQuantity { - val depositConstants = proxyDepositCalculator.getDepositConstants(chain) + override suspend fun calculateDeltaDepositForAddProxy(chain: Chain, accountId: AccountId): Balance { + val depositConstants = proxyConstantsRepository.getDepositConstants(chain.id) val currentProxiesCount = getProxyRepository.getProxiesQuantity(chain.id, accountId) - val newQuantity = currentProxiesCount + 1 - val deposit = proxyDepositCalculator.calculateProxyDepositForQuantity(depositConstants, newQuantity) - return ProxyDepositWithQuantity(deposit, newQuantity) + val oldDeposit = proxyDepositCalculator.calculateProxyDepositForQuantity(depositConstants, currentProxiesCount) + val newDeposit = proxyDepositCalculator.calculateProxyDepositForQuantity(depositConstants, currentProxiesCount + 1) + return newDeposit - oldDeposit } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/direct/DirectStakingProperties.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/direct/DirectStakingProperties.kt index 8f236cbe44..24be148225 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/direct/DirectStakingProperties.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/direct/DirectStakingProperties.kt @@ -117,7 +117,7 @@ private class DirectStakingProperties( error = { context -> StartMultiStakingValidationFailure.NotEnoughToPayFees( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationPayload.kt index 08cfeafa6a..8a4dcb6ada 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationPayload.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationPayload.kt @@ -1,6 +1,6 @@ package io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add -import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity +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.presentation.model.DecimalFee import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain @@ -12,5 +12,6 @@ class AddStakingProxyValidationPayload( val proxiedAccountId: AccountId, val proxyAddress: String, val fee: DecimalFee, - val depositWithQuantity: ProxyDepositWithQuantity + val deltaDeposit: Balance, + val currentQuantity: Int ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt index 908fcb2af8..13f60b0b4c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt @@ -4,10 +4,11 @@ import io.novafoundation.nova.common.validation.ValidationSystem import io.novafoundation.nova.common.validation.ValidationSystemBuilder import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType -import io.novafoundation.nova.feature_proxy_api.domain.validators.enoughBalanceToPayProxyDeposit import io.novafoundation.nova.feature_proxy_api.domain.validators.maximumProxiesNotReached import io.novafoundation.nova.feature_proxy_api.domain.validators.proxyIsNotDuplicationForAccount +import io.novafoundation.nova.feature_wallet_api.domain.model.amountFromPlanks import io.novafoundation.nova.feature_wallet_api.domain.model.balanceCountedTowardsED +import io.novafoundation.nova.feature_wallet_api.domain.model.planksFromAmount import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughTotalToStayAboveEDValidationFactory import io.novafoundation.nova.feature_wallet_api.domain.validation.sufficientBalance import io.novafoundation.nova.feature_wallet_api.domain.validation.validAddress @@ -46,7 +47,7 @@ fun AddStakingProxyValidationSystemBuilder.sufficientBalanceToPayFee() = error = { context -> AddStakingProxyValidationFailure.NotEnoughToPayFee( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } @@ -57,7 +58,7 @@ fun AddStakingProxyValidationSystemBuilder.maximumProxies( ) = maximumProxiesNotReached( chain = { it.chain }, accountId = { it.proxiedAccountId }, - newProxiedQuantity = { it.depositWithQuantity.quantity }, + newProxiedQuantity = { it.currentQuantity + 1 }, error = { payload, max -> AddStakingProxyValidationFailure.MaximumProxiesReached( chain = payload.chain, @@ -67,22 +68,18 @@ fun AddStakingProxyValidationSystemBuilder.maximumProxies( proxyRepository = proxyRepository ) -fun AddStakingProxyValidationSystemBuilder.enoughBalanceToPayDeposit( - proxyRepository: GetProxyRepository -) = enoughBalanceToPayProxyDeposit( - chain = { it.chain }, - accountId = { it.proxiedAccountId }, - newDeposit = { it.depositWithQuantity.deposit }, - availableBalance = { it.asset.freeInPlanks - it.asset.frozenInPlanks }, - error = { payload, maxUsable -> +fun AddStakingProxyValidationSystemBuilder.enoughBalanceToPayDepositAndFee() = sufficientBalance( + fee = { it.fee }, + amount = { it.asset.token.configuration.amountFromPlanks(it.deltaDeposit) }, + available = { it.asset.free - it.asset.frozen }, + error = { + val chainAsset = it.payload.asset.token.configuration AddStakingProxyValidationFailure.NotEnoughBalanceToReserveDeposit( - chainAsset = payload.asset.token.configuration, - availableBalance = maxUsable, - deposit = payload.depositWithQuantity.deposit + chainAsset = chainAsset, + availableBalance = chainAsset.planksFromAmount(it.maxUsable), + deposit = it.payload.deltaDeposit ) - }, - proxyRepository = proxyRepository, - feeReceiver = { it.fee.networkFee.amount } + } ) fun AddStakingProxyValidationSystemBuilder.stakingTypeIsNotDuplication( diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt index 8e255829a2..0a2baa4fd3 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt @@ -33,7 +33,7 @@ fun RemoveStakingProxyValidationSystemBuilder.sufficientBalanceToPayFee() { error = { context -> RemoveStakingProxyValidationFailure.NotEnoughToPayFee( chainAsset = context.payload.asset.token.configuration, - maxUsable = context.availableToPayFees, + maxUsable = context.maxUsable, fee = context.fee ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyPayload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyPayload.kt index a656b52a34..fc31648a8e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyPayload.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyPayload.kt @@ -9,6 +9,6 @@ import kotlinx.android.parcel.Parcelize class ConfirmAddStakingProxyPayload( val fee: FeeParcelModel, val proxyAddress: String, - val newProxyDeposit: Balance, - val newProxyQuantity: Int + val deltaDeposit: Balance, + val currentQuantity: Int ) : Parcelable diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt index e78e07d5de..2cc8565a87 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt @@ -5,7 +5,6 @@ import io.novafoundation.nova.common.base.BaseViewModel import io.novafoundation.nova.common.mixin.api.Validatable import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.flowOf -import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.bottomSheet.description.DescriptionBottomSheetLauncher @@ -86,7 +85,7 @@ class ConfirmAddStakingProxyViewModel( } val proxyDeposit = assetFlow.map { asset -> - mapAmountToAmountModel(payload.newProxyDeposit, asset) + mapAmountToAmountModel(payload.deltaDeposit, asset) } val feeModelFlow = combine(assetFlow, decimalFeeFlow) { asset, decimalFee -> @@ -112,10 +111,8 @@ class ConfirmAddStakingProxyViewModel( proxyAddress = payload.proxyAddress, proxiedAccountId = metaAccount.requireAccountIdIn(chain), fee = decimalFeeFlow.first(), - depositWithQuantity = ProxyDepositWithQuantity( - deposit = payload.newProxyDeposit, - quantity = payload.newProxyQuantity - ) + deltaDeposit = payload.deltaDeposit, + currentQuantity = payload.currentQuantity ) validationExecutor.requireValid( diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt index 015fad1167..1e2a13127a 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt @@ -18,7 +18,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddr import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin -import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyDepositWithQuantity +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.AddStakingProxyInteractor import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor @@ -28,6 +28,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.launchProxyDepositDescription import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.common.mapAddStakingProxyValidationFailureToUi import io.novafoundation.nova.feature_staking_impl.presentation.staking.delegation.proxy.add.confirm.ConfirmAddStakingProxyPayload +import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.feature_wallet_api.domain.ArbitraryAssetUseCase import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.awaitDecimalFee @@ -69,7 +70,8 @@ class AddStakingProxyViewModel( private val descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, private val metaAccountGroupingInteractor: MetaAccountGroupingInteractor, private val stakingRouter: StakingRouter, - private val selectAddressMixinFactory: SelectAddressMixin.Factory + private val selectAddressMixinFactory: SelectAddressMixin.Factory, + private val getProxyRepository: GetProxyRepository ) : BaseViewModel(), DescriptionBottomSheetLauncher by descriptionBottomSheetLauncher, ExternalActions by externalActions, @@ -124,16 +126,16 @@ class AddStakingProxyViewModel( } .shareInBackground() - private val proxyDeposit: Flow = flowOf { + private val proxyDepositDelta: Flow = flowOf { val metaAccount = accountRepository.getSelectedMetaAccount() val chain = selectedAssetState.chain() val accountId = metaAccount.requireAccountIdIn(chain) - addStakingProxyInteractor.calculateDepositForAddProxy(chain, accountId) + addStakingProxyInteractor.calculateDeltaDepositForAddProxy(chain, accountId) } .shareInBackground() - val proxyDepositModel: Flow = combine(proxyDeposit, selectedAssetFlow) { depositwithQuantity, asset -> - mapAmountToAmountModel(depositwithQuantity.deposit, asset) + val proxyDepositModel: Flow = combine(proxyDepositDelta, selectedAssetFlow) { depositDelta, asset -> + mapAmountToAmountModel(depositDelta, asset) } .shareInBackground() @@ -176,13 +178,15 @@ class AddStakingProxyViewModel( fun onConfirmClick() = launch { val metaAccount = accountRepository.getSelectedMetaAccount() val chain = selectedAssetState.chain() + val proxiedAccountId = metaAccount.requireAccountIdIn(chain) val validationPayload = AddStakingProxyValidationPayload( chain = chain, asset = selectedAssetFlow.first(), proxyAddress = addressInputMixin.inputFlow.value, proxiedAccountId = metaAccount.requireAccountIdIn(chain), fee = feeMixin.awaitDecimalFee(), - depositWithQuantity = proxyDeposit.first() + deltaDeposit = proxyDepositDelta.first(), + currentQuantity = getProxyRepository.getProxiesQuantity(chain.id, proxiedAccountId) ) validationExecutor.requireValid( @@ -200,8 +204,8 @@ class AddStakingProxyViewModel( ConfirmAddStakingProxyPayload( fee = mapFeeToParcel(validationPayload.fee), proxyAddress = proxyAddress, - newProxyDeposit = depositWithQuantity.deposit, - newProxyQuantity = depositWithQuantity.quantity + deltaDeposit = deltaDeposit, + currentQuantity = currentQuantity ) } stakingRouter.openConfirmAddStakingProxy(screenPayload) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyModule.kt index 4c0fc6a81b..d4edb104b1 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/di/AddStakingProxyModule.kt @@ -17,6 +17,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddr import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_account_api.presenatation.mixin.addressInput.AddressInputMixinFactory import io.novafoundation.nova.feature_account_api.presenatation.mixin.selectAddress.SelectAddressMixin +import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.AddStakingProxyInteractor import io.novafoundation.nova.feature_staking_impl.domain.StakingInteractor import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.AddStakingProxyValidationSystem @@ -48,7 +49,8 @@ class AddStakingProxyModule { descriptionBottomSheetLauncher: DescriptionBottomSheetLauncher, metaAccountGroupingInteractor: MetaAccountGroupingInteractor, stakingRouter: StakingRouter, - selectAddressMixinFactory: SelectAddressMixin.Factory + selectAddressMixinFactory: SelectAddressMixin.Factory, + getProxyRepository: GetProxyRepository ): ViewModel { return AddStakingProxyViewModel( addressInputMixinFactory = addressInputMixinFactory, @@ -65,7 +67,8 @@ class AddStakingProxyModule { descriptionBottomSheetLauncher = descriptionBottomSheetLauncher, metaAccountGroupingInteractor = metaAccountGroupingInteractor, stakingRouter = stakingRouter, - selectAddressMixinFactory = selectAddressMixinFactory + selectAddressMixinFactory = selectAddressMixinFactory, + getProxyRepository = getProxyRepository ) } diff --git a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt index 173959ed0c..85ba305c25 100644 --- a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt +++ b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt @@ -98,6 +98,7 @@ data class Asset( val transferable = token.amountFromPlanks(transferableInPlanks) val free = token.amountFromPlanks(freeInPlanks) + val frozen = token.amountFromPlanks(frozenInPlanks) // TODO move to runtime storage val bonded = token.amountFromPlanks(bondedInPlanks) diff --git a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/validation/EnoughAmountToTransferValidation.kt b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/validation/EnoughAmountToTransferValidation.kt index 11d334e60a..ce543075ae 100644 --- a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/validation/EnoughAmountToTransferValidation.kt +++ b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/validation/EnoughAmountToTransferValidation.kt @@ -34,7 +34,7 @@ class EnoughAmountToTransferValidationGeneric( val payload: P, - val availableToPayFees: BigDecimal, + val maxUsable: BigDecimal, val fee: BigDecimal, ) diff --git a/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt b/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt index 674c352673..8286ce1648 100644 --- a/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt +++ b/feature-wallet-impl/src/main/java/io/novafoundation/nova/feature_wallet_impl/data/network/blockchain/assets/transfers/validations/Common.kt @@ -91,7 +91,7 @@ fun AssetTransfersValidationSystemBuilder.sufficientTransferableBalanceToPayOrig AssetTransferValidationFailure.NotEnoughFunds.InCommissionAsset( chainAsset = context.payload.transfer.originChain.commissionAsset, fee = context.fee, - maxUsable = context.availableToPayFees + maxUsable = context.maxUsable ) } ) From 8610dc0d4dcbc0a8fbb8a24dacf5f476b0a5ac68 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Thu, 25 Jan 2024 17:03:29 +0100 Subject: [PATCH 40/55] Don't allow self delegation --- .../validation/NotSelfAccountValidation.kt | 39 +++++++++++++++++++ .../AddStakingProxyValidationsModule.kt | 5 +++ .../add/AddStakingProxyValidationFailure.kt | 2 + .../delegation/proxy/add/Declarations.kt | 11 ++++++ .../AddProxyValidationFailureHandling.kt | 3 ++ 5 files changed, 60 insertions(+) create mode 100644 feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/validation/NotSelfAccountValidation.kt diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/validation/NotSelfAccountValidation.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/validation/NotSelfAccountValidation.kt new file mode 100644 index 0000000000..bc70fea56a --- /dev/null +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/validation/NotSelfAccountValidation.kt @@ -0,0 +1,39 @@ +package io.novafoundation.nova.feature_account_api.domain.validation + +import io.novafoundation.nova.common.validation.Validation +import io.novafoundation.nova.common.validation.ValidationStatus +import io.novafoundation.nova.common.validation.ValidationSystemBuilder +import io.novafoundation.nova.common.validation.validOrError +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.accountIdIn +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import jp.co.soramitsu.fearless_utils.runtime.AccountId + +class NotSelfAccountValidation( + private val chainProvider: (P) -> Chain, + private val accountIdProvider: (P) -> AccountId, + private val failure: (P) -> F, + private val accountRepository: AccountRepository, +) : Validation { + + override suspend fun validate(value: P): ValidationStatus { + val chain = chainProvider(value) + val accountId = accountIdProvider(value) + val selfAccountId = accountRepository.getSelectedMetaAccount() + .accountIdIn(chain) + + val isDifferentAccounts = !accountId.contentEquals(selfAccountId) + return validOrError(isDifferentAccounts) { + failure(value) + } + } +} + +fun ValidationSystemBuilder.notSelfAccount( + chainProvider: (P) -> Chain, + accountIdProvider: (P) -> AccountId, + failure: (P) -> F, + accountRepository: AccountRepository, +) { + validate(NotSelfAccountValidation(chainProvider, accountIdProvider, failure, accountRepository)) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt index d247ae152e..6e15dd850f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/AddStakingProxyValidationsModule.kt @@ -4,10 +4,12 @@ import dagger.Module import dagger.Provides import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.common.validation.ValidationSystem +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.AddStakingProxyValidationSystem import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.enoughBalanceToPayDepositAndFee import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.maximumProxies +import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.notSelfAccount import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.stakingTypeIsNotDuplication import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.sufficientBalanceToPayFee import io.novafoundation.nova.feature_staking_impl.domain.validations.delegation.proxy.add.sufficientBalanceToStayAboveEd @@ -21,10 +23,13 @@ class AddStakingProxyValidationsModule { @Provides fun provideAddStakingProxyValidationSystem( getProxyRepository: GetProxyRepository, + accountRepository: AccountRepository, enoughTotalToStayAboveEDValidationFactory: EnoughTotalToStayAboveEDValidationFactory ): AddStakingProxyValidationSystem = ValidationSystem { validAddress() + notSelfAccount(accountRepository) + sufficientBalanceToPayFee() sufficientBalanceToStayAboveEd(enoughTotalToStayAboveEDValidationFactory) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt index e6737b58be..f92e850fa0 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt @@ -24,6 +24,8 @@ sealed interface AddStakingProxyValidationFailure { class InvalidAddress(val chain: Chain) : AddStakingProxyValidationFailure + object SelfDelegation : AddStakingProxyValidationFailure + class MaximumProxiesReached(val chain: Chain, val max: Int) : AddStakingProxyValidationFailure class AlreadyDelegated(val address: String) : AddStakingProxyValidationFailure diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt index 13f60b0b4c..0ecbaf1622 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt @@ -2,6 +2,8 @@ package io.novafoundation.nova.feature_staking_impl.domain.validations.delegatio import io.novafoundation.nova.common.validation.ValidationSystem import io.novafoundation.nova.common.validation.ValidationSystemBuilder +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.validation.notSelfAccount import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_proxy_api.domain.validators.maximumProxiesNotReached @@ -92,3 +94,12 @@ fun AddStakingProxyValidationSystemBuilder.stakingTypeIsNotDuplication( error = { payload -> AddStakingProxyValidationFailure.AlreadyDelegated(payload.proxyAddress) }, proxyRepository = proxyRepository ) + +fun AddStakingProxyValidationSystemBuilder.notSelfAccount( + accountRepository: AccountRepository +) = notSelfAccount( + chainProvider = { it.chain }, + accountIdProvider = { it.chain.accountIdOf(it.proxyAddress) }, + failure = { AddStakingProxyValidationFailure.SelfDelegation }, + accountRepository = accountRepository +) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt index 55e134a698..9442a58431 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt @@ -28,6 +28,9 @@ fun mapAddStakingProxyValidationFailureToUi( is InvalidAddress -> resourceManager.getString(R.string.invalid_proxy_address_title) to resourceManager.getString(R.string.invalid_proxy_address_message, failure.chain.name) + AddStakingProxyValidationFailure.SelfDelegation -> resourceManager.getString(R.string.delegation_error_self_delegate_title) to + resourceManager.getString(R.string.delegation_error_self_delegate_message) + is MaximumProxiesReached -> resourceManager.getString(R.string.add_proxy_maximum_reached_error_title) to resourceManager.getString(R.string.add_proxy_maximum_reached_error_message, failure.max, failure.chain.name) From 47c8feaef9c8ac2604b22876016a03ead043c514 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 26 Jan 2024 12:24:34 +0100 Subject: [PATCH 41/55] Sync proxies after add/remove proxy --- .../di/StakingFeatureDependencies.kt | 3 +++ .../di/StakingFeatureModule.kt | 15 ++++++++--- .../proxy/AddStakingProxyInteractor.kt | 4 ++- .../proxy/RealAddStakingProxyInteractor.kt | 19 +++++++++++--- .../remove/RemoveStakingProxyInteractor.kt | 25 +++++++++++++++---- .../proxy/add/set/AddStakingProxyViewModel.kt | 1 + 6 files changed, 53 insertions(+), 14 deletions(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt index 30a1e4b889..e2c51faccc 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureDependencies.kt @@ -24,6 +24,7 @@ import io.novafoundation.nova.core_db.dao.StakingDashboardDao import io.novafoundation.nova.core_db.dao.StakingRewardPeriodDao import io.novafoundation.nova.core_db.dao.StakingTotalRewardDao import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.account.identity.LocalIdentity @@ -189,4 +190,6 @@ interface StakingFeatureDependencies { val selectAddressMixinFactory: SelectAddressMixin.Factory val proxyConstantsRepository: ProxyConstantsRepository + + val proxySyncService: ProxySyncService } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt index be8765d9ba..00330dc08f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureModule.kt @@ -15,6 +15,7 @@ import io.novafoundation.nova.core_db.dao.ExternalBalanceDao import io.novafoundation.nova.core_db.dao.StakingRewardPeriodDao import io.novafoundation.nova.core_db.dao.StakingTotalRewardDao import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.data.repository.OnChainIdentityRepository import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.account.identity.LocalIdentity @@ -620,13 +621,15 @@ class StakingFeatureModule { extrinsicService: ExtrinsicService, proxyDepositCalculator: ProxyDepositCalculator, getProxyRepository: GetProxyRepository, - proxyConstantsRepository: ProxyConstantsRepository + proxyConstantsRepository: ProxyConstantsRepository, + proxySyncService: ProxySyncService ): AddStakingProxyInteractor { return RealAddStakingProxyInteractor( extrinsicService, proxyDepositCalculator, getProxyRepository, - proxyConstantsRepository + proxyConstantsRepository, + proxySyncService ) } @@ -643,6 +646,10 @@ class StakingFeatureModule { @Provides @FeatureScope fun removeStakingProxyInteractor( - extrinsicService: ExtrinsicService - ): RemoveStakingProxyInteractor = RealRemoveStakingProxyInteractor(extrinsicService) + extrinsicService: ExtrinsicService, + proxySyncService: ProxySyncService + ): RemoveStakingProxyInteractor = RealRemoveStakingProxyInteractor( + extrinsicService, + proxySyncService + ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt index 5fb2d99b51..8704d7f611 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt @@ -3,14 +3,16 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.pr import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance +import io.novafoundation.nova.runtime.extrinsic.ExtrinsicStatus import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId +import kotlinx.coroutines.flow.Flow interface AddStakingProxyInteractor { suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee - suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result + suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result> suspend fun calculateDeltaDepositForAddProxy(chain: Chain, accountId: AccountId): Balance } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt index 06e303d9fa..b5dee1e0bf 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt @@ -3,7 +3,9 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.pr import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.intoOrigin import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission +import io.novafoundation.nova.feature_account_api.data.extrinsic.awaitInBlock import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_proxy_api.data.calls.addProxyCall import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository @@ -11,16 +13,20 @@ import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRe import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.runtime.ext.emptyAccountId +import io.novafoundation.nova.runtime.extrinsic.ExtrinsicStatus import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext class RealAddStakingProxyInteractor( private val extrinsicService: ExtrinsicService, private val proxyDepositCalculator: ProxyDepositCalculator, private val getProxyRepository: GetProxyRepository, - private val proxyConstantsRepository: ProxyConstantsRepository + private val proxyConstantsRepository: ProxyConstantsRepository, + private val proxySyncService: ProxySyncService ) : AddStakingProxyInteractor { override suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee { @@ -31,12 +37,17 @@ class RealAddStakingProxyInteractor( } } - override suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { - return withContext(Dispatchers.IO) { - extrinsicService.submitExtrinsic(chain, proxiedAccountId.intoOrigin()) { + override suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result> { + val result = withContext(Dispatchers.IO) { + extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { addProxyCall(proxyAccountId, ProxyType.Staking) } } + + result.awaitInBlock() + proxySyncService.startSyncing() + + return result } override suspend fun calculateDeltaDepositForAddProxy(chain: Chain, accountId: AccountId): Balance { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt index 3b418d63e8..277b111179 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt @@ -1,26 +1,36 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.remove +import io.novafoundation.nova.common.utils.mapFailure import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.intoOrigin import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission +import io.novafoundation.nova.feature_account_api.data.extrinsic.awaitInBlock import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_proxy_api.data.calls.removeProxyCall import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType import io.novafoundation.nova.runtime.ext.emptyAccountId +import io.novafoundation.nova.runtime.extrinsic.ExtrinsicStatus import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.withContext interface RemoveStakingProxyInteractor { suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee - suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result + suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result> } class RealRemoveStakingProxyInteractor( - private val extrinsicService: ExtrinsicService + private val extrinsicService: ExtrinsicService, + private val proxySyncService: ProxySyncService ) : RemoveStakingProxyInteractor { override suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee { @@ -31,11 +41,16 @@ class RealRemoveStakingProxyInteractor( } } - override suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { - return withContext(Dispatchers.IO) { - extrinsicService.submitExtrinsic(chain, proxiedAccountId.intoOrigin()) { + override suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result> { + val result = withContext(Dispatchers.IO) { + extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { removeProxyCall(proxyAccountId, ProxyType.Staking) } } + + result.awaitInBlock() + proxySyncService.startSyncing() + + return result } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt index 1e2a13127a..969a6ee619 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt @@ -196,6 +196,7 @@ class AddStakingProxyViewModel( progressConsumer = _validationProgressFlow.progressConsumer() ) { openConfirmScreen(it) + _validationProgressFlow.value = false } } From 9db8eeb817c468c35bf0961645b0e933fa896c12 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 26 Jan 2024 14:02:36 +0100 Subject: [PATCH 42/55] Fixed crash on staking for not supported proxy chains --- .../nova/common/utils/FearlessLibExt.kt | 2 ++ .../network/blockhain/updaters/ProxiesUpdater.kt | 3 ++- .../RelaychainStakeActionsComponent.kt | 16 +++++++++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/FearlessLibExt.kt b/common/src/main/java/io/novafoundation/nova/common/utils/FearlessLibExt.kt index fdf5dca621..ce1823f63a 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/FearlessLibExt.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/FearlessLibExt.kt @@ -235,6 +235,8 @@ fun RuntimeMetadata.assetConversionOrNull() = moduleOrNull(Modules.ASSET_CONVERS fun RuntimeMetadata.assetConversion() = module(Modules.ASSET_CONVERSION) +fun RuntimeMetadata.proxyOrNull() = moduleOrNull(Modules.PROXY) + fun RuntimeMetadata.proxy() = module(Modules.PROXY) fun RuntimeMetadata.firstExistingModuleName(vararg options: String): String { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt index 5dcdb3ba9a..cbc898e62c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt @@ -1,6 +1,7 @@ package io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters import io.novafoundation.nova.common.utils.proxy +import io.novafoundation.nova.common.utils.proxyOrNull import io.novafoundation.nova.core.storage.StorageCache import io.novafoundation.nova.core_db.model.AccountStakingLocal import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState @@ -21,6 +22,6 @@ class ProxiesUpdater( override suspend fun storageKey(runtime: RuntimeSnapshot, scopeValue: AccountStakingLocal): String? { val accountId = scopeValue.accountId - return runtime.metadata.proxy().storageOrNull("Proxies")?.storageKey(runtime, accountId) + return runtime.metadata.proxyOrNull()?.storageOrNull("Proxies")?.storageKey(runtime, accountId) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt index cadd611022..0f18ad79fd 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt @@ -5,6 +5,7 @@ import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.Event import io.novafoundation.nova.common.utils.WithCoroutineScopeExtensions import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType @@ -40,10 +41,13 @@ import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.com import io.novafoundation.nova.feature_staking_impl.presentation.staking.main.mainStakingValidationFailure import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combineTransform +import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.launch class RelaychainStakeActionsComponentFactory( @@ -88,9 +92,7 @@ private class RelaychainStakeActionsComponent( @OptIn(ExperimentalCoroutinesApi::class) private val stakingProxiesQuantity = accountRepository.selectedMetaAccountFlow() .flatMapLatest { metaAccount -> - val chain = stakingOption.assetWithChain.chain - val accountId = metaAccount.requireAccountIdIn(chain) - getProxyRepository.proxiesQuantityByTypeFlow(chain, accountId, ProxyType.Staking) + getProxiesQuantity(metaAccount) } private val selectedAccountStakingStateFlow = stakingSharedComputation.selectedAccountStakingStateFlow( @@ -116,6 +118,14 @@ private class RelaychainStakeActionsComponent( } } + private suspend fun getProxiesQuantity(metaAccount: MetaAccount): Flow { + val chain = stakingOption.assetWithChain.chain + if (chain.supportProxy.not()) return flowOf(0) + + val accountId = metaAccount.requireAccountIdIn(chain) + return getProxyRepository.proxiesQuantityByTypeFlow(chain, accountId, ProxyType.Staking) + } + private fun manageStakeActionChosen(manageStakeAction: ManageStakeAction) { val validationSystem = stakeActionsValidations[manageStakeAction.id] From 7a27803ec86f5655de423afa42c3f3dd8ec4109e Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Fri, 26 Jan 2024 14:03:24 +0100 Subject: [PATCH 43/55] Run ktlint --- .../data/network/blockhain/updaters/ProxiesUpdater.kt | 1 - .../staking/delegation/proxy/AddStakingProxyInteractor.kt | 1 - .../delegation/proxy/RealAddStakingProxyInteractor.kt | 4 +--- .../delegation/proxy/remove/RemoveStakingProxyInteractor.kt | 6 ------ .../relaychain/RelaychainStakeActionsComponent.kt | 1 - 5 files changed, 1 insertion(+), 12 deletions(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt index cbc898e62c..993fb4fa05 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/network/blockhain/updaters/ProxiesUpdater.kt @@ -1,6 +1,5 @@ package io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters -import io.novafoundation.nova.common.utils.proxy import io.novafoundation.nova.common.utils.proxyOrNull import io.novafoundation.nova.core.storage.StorageCache import io.novafoundation.nova.core_db.model.AccountStakingLocal diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt index 8704d7f611..cfc9c0499c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt @@ -1,6 +1,5 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy -import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.runtime.extrinsic.ExtrinsicStatus diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt index b5dee1e0bf..bae33d5e82 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt @@ -2,7 +2,6 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.pr import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.intoOrigin import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService -import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.extrinsic.awaitInBlock import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService @@ -18,7 +17,6 @@ import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext class RealAddStakingProxyInteractor( @@ -46,7 +44,7 @@ class RealAddStakingProxyInteractor( result.awaitInBlock() proxySyncService.startSyncing() - + return result } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt index 277b111179..71887a7a24 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt @@ -1,9 +1,7 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.remove -import io.novafoundation.nova.common.utils.mapFailure import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.intoOrigin import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService -import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSubmission import io.novafoundation.nova.feature_account_api.data.extrinsic.awaitInBlock import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService @@ -15,10 +13,6 @@ import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.withContext interface RemoveStakingProxyInteractor { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt index 0f18ad79fd..719af99b56 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/components/stakeActions/relaychain/RelaychainStakeActionsComponent.kt @@ -43,7 +43,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combineTransform -import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest From 5f35e319734a192e4915139192227bd634277dea Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 30 Jan 2024 15:02:18 +0100 Subject: [PATCH 44/55] Fixed proxied accounts duplication --- .../data/proxy/RealProxySyncService.kt | 59 ++++++++++++------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt index d6b4ea7f80..b9ba496cbb 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt @@ -73,7 +73,6 @@ class RealProxySyncService( Log.d(LOG_TAG, "Started syncing proxies for ${chain.name}") val availableAccounts = chain.getAvailableMetaAccounts(allMetaAccounts) - val availableMetaIds = availableAccounts.map { it.id } val availableAccountIds = availableAccounts.mapToSet { it.requireAccountIdIn(chain).intoKey() } val nodes = getProxyRepository.findAllProxiedsForAccounts(chain.id, availableAccountIds) @@ -82,8 +81,7 @@ class RealProxySyncService( val oldProxies = accountDao.getProxyAccounts(chain.id) val identities = identityProvider.identitiesFor(proxiedAccountIds, chain.id) - val nestedNodes = nodes.flatMap { it.nestedNodes } - val result = recursivelyCreateMetaAccounts(chain.id, oldProxies, identities, availableMetaIds, nestedNodes) + val result = createMetaAccounts(chain, oldProxies, identities, availableAccounts, nodes) val deactivatedMetaIds = result.findDeactivated(oldProxies) accountDao.changeAccountsStatus(deactivatedMetaIds, MetaAccountLocal.Status.DEACTIVATED) @@ -96,32 +94,51 @@ class RealProxySyncService( Log.d(LOG_TAG, "Finished syncing proxies for ${chain.name}") } + private suspend fun createMetaAccounts( + chain: Chain, + oldProxies: List, + identities: Map, + maybeProxyMetaAccounts: List, + startNodes: List + ): CreateMetaAccountsResult { + val result = CreateMetaAccountsResult() + + val accountIdToNode = startNodes.associateBy { it.accountId } + for (metaAccount in maybeProxyMetaAccounts) { + val proxyAccountId = metaAccount.requireAccountIdIn(chain).intoKey() + val startNode = accountIdToNode[proxyAccountId] ?: continue // skip adding proxieds for metaAccount if it's not in the tree + + val nestedResult = recursivelyCreateMetaAccounts(chain.id, oldProxies, identities, metaAccount.id, startNode.nestedNodes) + result.add(nestedResult) + } + + return result + } + private suspend fun recursivelyCreateMetaAccounts( chainId: ChainId, oldProxies: List, identities: Map, - metaIds: List, + proxyMetaId: Long, nestedNodes: List ): CreateMetaAccountsResult { val result = CreateMetaAccountsResult() - metaIds.forEach { metaId -> - for (node in nestedNodes) { - val maybeExistedProxiedMetaId = node.getExistedProxiedMetaId(chainId, oldProxies, metaId) - - var nextMetaId = if (maybeExistedProxiedMetaId == null) { - val newMetaId = addProxiedAccount(chainId, node, metaId, identities) - result.addedMetaIds.add(newMetaId) - newMetaId - } else { - result.alreadyExistedMetaIds.add(maybeExistedProxiedMetaId) - maybeExistedProxiedMetaId - } - - if (node.nestedNodes.isNotEmpty()) { - val nestedResult = recursivelyCreateMetaAccounts(chainId, oldProxies, identities, listOf(nextMetaId), node.nestedNodes) - result.add(nestedResult) - } + for (node in nestedNodes) { + val maybeExistedProxiedMetaId = node.getExistedProxiedMetaId(chainId, oldProxies, proxyMetaId) + + var nextMetaId = if (maybeExistedProxiedMetaId == null) { + val newMetaId = addProxiedAccount(chainId, node, proxyMetaId, identities) + result.addedMetaIds.add(newMetaId) + newMetaId + } else { + result.alreadyExistedMetaIds.add(maybeExistedProxiedMetaId) + maybeExistedProxiedMetaId + } + + if (node.nestedNodes.isNotEmpty()) { + val nestedResult = recursivelyCreateMetaAccounts(chainId, oldProxies, identities, nextMetaId, node.nestedNodes) + result.add(nestedResult) } } From 3e95f506d22e3440066ebbd9e18839a595ebbd2a Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 30 Jan 2024 15:37:20 +0100 Subject: [PATCH 45/55] Fixed pr --- .../data/proxy/RealProxySyncService.kt | 15 +-------------- .../data/proxy/SyncServiceExt.kt | 7 ++++--- .../data/signer/proxy/ProxiedSigner.kt | 5 ----- .../proxy/list/RealStakingProxyListInteractor.kt | 11 +++++------ 4 files changed, 10 insertions(+), 28 deletions(-) diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt index e9717389bb..dbe58161b2 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt @@ -197,20 +197,7 @@ class RealProxySyncService( private suspend fun getMetaAccounts(): List { return accountRepository.getActiveMetaAccounts() - .filter { it.isAllowedToSyncProxy() } - } - - private fun MetaAccount.isAllowedToSyncProxy(): Boolean { - return when (type) { - LightMetaAccount.Type.SECRETS, - LightMetaAccount.Type.PARITY_SIGNER, - LightMetaAccount.Type.LEDGER, - LightMetaAccount.Type.POLKADOT_VAULT -> true - - LightMetaAccount.Type.WATCH_ONLY -> shouldSyncWatchOnlyProxies - - LightMetaAccount.Type.PROXIED -> false - } + .filter { it.isAllowedToSyncProxy(shouldSyncWatchOnlyProxies) } } private suspend fun getSupportedProxyChains(): List { diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/SyncServiceExt.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/SyncServiceExt.kt index 6fc9ff56f9..07d04c07d0 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/SyncServiceExt.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/SyncServiceExt.kt @@ -3,13 +3,14 @@ package io.novafoundation.nova.feature_account_impl.data.proxy import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount -fun MetaAccount.isAllowedToSyncProxy(): Boolean { +fun MetaAccount.isAllowedToSyncProxy(shouldSyncWatchOnly: Boolean): Boolean { return when (type) { LightMetaAccount.Type.SECRETS, LightMetaAccount.Type.PARITY_SIGNER, LightMetaAccount.Type.LEDGER, - LightMetaAccount.Type.POLKADOT_VAULT, - LightMetaAccount.Type.WATCH_ONLY -> true + LightMetaAccount.Type.POLKADOT_VAULT -> true + + LightMetaAccount.Type.WATCH_ONLY -> shouldSyncWatchOnly LightMetaAccount.Type.PROXIED -> false } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt index 409e5a3636..f4cc427837 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/signer/proxy/ProxiedSigner.kt @@ -89,11 +89,6 @@ class ProxiedSigner( acknowledgeProxyOperation(proxyMetaAccount) } - // TODO this wont use the actual payload for fee validation when multiple nested proxies are used - // We need to design a universal solution - // We actually can use `signedExtrinsic.payload` to access actual payload but in this case validation will happen only after signing - // which will have bad UX with Vault and Ledger. - // As an option we could separate signing and wrapping step specifically for such nested signers and use only the wrapping step before fee validation val payloadToSign = if (isRootProxied) modifyPayload(payloadExtrinsic) else payloadExtrinsic if (isRootProxied) { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt index 3569dfa541..8a13aa97c4 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/list/RealStakingProxyListInteractor.kt @@ -1,6 +1,5 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.delegation.proxy.list -import io.novafoundation.nova.common.address.intoKey import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType @@ -23,14 +22,14 @@ class RealStakingProxyListInteractor( override fun stakingProxyListFlow(chain: Chain, accountId: AccountId): Flow> { return getProxyRepository.proxiesByTypeFlow(chain, accountId, ProxyType.Staking) .map { proxies -> - val proxiesAccountIds = proxies.map { it.accountId } + val proxiesAccountIds = proxies.map { it.proxyAccountId.value } val proxyIdentities = identityProvider.identitiesFor(proxiesAccountIds, chain.id) proxies.map { proxy -> - val proxyAccountId = proxy.accountId - val identity = proxyIdentities[proxyAccountId.intoKey()] + val proxyAccountId = proxy.proxyAccountId + val identity = proxyIdentities[proxyAccountId] StakingProxyAccount( - identity?.name ?: chain.addressOf(proxyAccountId), - proxyAccountId + identity?.name ?: chain.addressOf(proxyAccountId.value), + proxyAccountId.value ) } } From c5101825f47dfd66e8f6f415bf98271296dd018d Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Wed, 31 Jan 2024 08:23:57 +0100 Subject: [PATCH 46/55] Fixed pr notes --- .../validators/MaximumProxiesNotReachedValidation.kt | 8 ++++---- .../delegation/proxy/AddStakingProxyInteractor.kt | 3 +-- .../proxy/RealAddStakingProxyInteractor.kt | 10 ++++------ .../proxy/remove/RemoveStakingProxyInteractor.kt | 12 +++++------- .../validations/delegation/proxy/add/Declarations.kt | 5 +++-- .../nova/feature_wallet_api/domain/model/Asset.kt | 4 ++++ 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt index 55082f9c47..9ab2c8f7ba 100644 --- a/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt +++ b/feature-proxy-api/src/main/java/io/novafoundation/nova/feature_proxy_api/domain/validators/MaximumProxiesNotReachedValidation.kt @@ -11,13 +11,13 @@ import jp.co.soramitsu.fearless_utils.runtime.AccountId class MaximumProxiesNotReachedValidation( private val chain: (P) -> Chain, private val accountId: (P) -> AccountId, - private val newProxiedQuantity: (P) -> Int, + private val proxiesQuantity: (P) -> Int, private val error: (P, Int) -> E, private val proxyRepository: GetProxyRepository ) : Validation { override suspend fun validate(value: P): ValidationStatus { - val newProxiesQuantity = newProxiedQuantity(value) + val newProxiesQuantity = proxiesQuantity(value) val maximumProxiesQuantiy = proxyRepository.maxProxiesQuantity(chain(value)) return validOrError(newProxiesQuantity <= maximumProxiesQuantiy) { @@ -29,7 +29,7 @@ class MaximumProxiesNotReachedValidation( fun ValidationSystemBuilder.maximumProxiesNotReached( chain: (P) -> Chain, accountId: (P) -> AccountId, - newProxiedQuantity: (P) -> Int, + proxiesQuantity: (P) -> Int, error: (P, Int) -> E, proxyRepository: GetProxyRepository ) { @@ -37,7 +37,7 @@ fun ValidationSystemBuilder.maximumProxiesNotReached( MaximumProxiesNotReachedValidation( chain = chain, accountId = accountId, - newProxiedQuantity = newProxiedQuantity, + proxiesQuantity = proxiesQuantity, error = error, proxyRepository = proxyRepository ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt index cfc9c0499c..3bce3f08da 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/AddStakingProxyInteractor.kt @@ -5,13 +5,12 @@ import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Ba import io.novafoundation.nova.runtime.extrinsic.ExtrinsicStatus import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId -import kotlinx.coroutines.flow.Flow interface AddStakingProxyInteractor { suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee - suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result> + suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result suspend fun calculateDeltaDepositForAddProxy(chain: Chain, accountId: AccountId): Balance } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt index bae33d5e82..509ce0259f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt @@ -16,7 +16,6 @@ import io.novafoundation.nova.runtime.extrinsic.ExtrinsicStatus import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.withContext class RealAddStakingProxyInteractor( @@ -35,17 +34,16 @@ class RealAddStakingProxyInteractor( } } - override suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result> { + override suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { val result = withContext(Dispatchers.IO) { extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { addProxyCall(proxyAccountId, ProxyType.Staking) } } - result.awaitInBlock() - proxySyncService.startSyncing() - - return result + return result.awaitInBlock().also { + proxySyncService.startSyncing() + } } override suspend fun calculateDeltaDepositForAddProxy(chain: Chain, accountId: AccountId): Balance { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt index 71887a7a24..0603ab3681 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt @@ -12,14 +12,13 @@ import io.novafoundation.nova.runtime.extrinsic.ExtrinsicStatus import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import jp.co.soramitsu.fearless_utils.runtime.AccountId import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.withContext interface RemoveStakingProxyInteractor { suspend fun estimateFee(chain: Chain, proxiedAccountId: AccountId): Fee - suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result> + suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result } class RealRemoveStakingProxyInteractor( @@ -35,16 +34,15 @@ class RealRemoveStakingProxyInteractor( } } - override suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result> { + override suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { val result = withContext(Dispatchers.IO) { extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { removeProxyCall(proxyAccountId, ProxyType.Staking) } } - result.awaitInBlock() - proxySyncService.startSyncing() - - return result + return result.awaitInBlock().also { + proxySyncService.startSyncing() + } } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt index 0ecbaf1622..c4b64f81ea 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt @@ -11,6 +11,7 @@ import io.novafoundation.nova.feature_proxy_api.domain.validators.proxyIsNotDupl import io.novafoundation.nova.feature_wallet_api.domain.model.amountFromPlanks import io.novafoundation.nova.feature_wallet_api.domain.model.balanceCountedTowardsED import io.novafoundation.nova.feature_wallet_api.domain.model.planksFromAmount +import io.novafoundation.nova.feature_wallet_api.domain.model.regulatTransferableBalance import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughTotalToStayAboveEDValidationFactory import io.novafoundation.nova.feature_wallet_api.domain.validation.sufficientBalance import io.novafoundation.nova.feature_wallet_api.domain.validation.validAddress @@ -60,7 +61,7 @@ fun AddStakingProxyValidationSystemBuilder.maximumProxies( ) = maximumProxiesNotReached( chain = { it.chain }, accountId = { it.proxiedAccountId }, - newProxiedQuantity = { it.currentQuantity + 1 }, + proxiesQuantity = { it.currentQuantity + 1 }, error = { payload, max -> AddStakingProxyValidationFailure.MaximumProxiesReached( chain = payload.chain, @@ -73,7 +74,7 @@ fun AddStakingProxyValidationSystemBuilder.maximumProxies( fun AddStakingProxyValidationSystemBuilder.enoughBalanceToPayDepositAndFee() = sufficientBalance( fee = { it.fee }, amount = { it.asset.token.configuration.amountFromPlanks(it.deltaDeposit) }, - available = { it.asset.free - it.asset.frozen }, + available = { it.asset.token.amountFromPlanks(it.asset.regulatTransferableBalance()) }, error = { val chainAsset = it.payload.asset.token.configuration AddStakingProxyValidationFailure.NotEnoughBalanceToReserveDeposit( diff --git a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt index 85ba305c25..50519a191c 100644 --- a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt +++ b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt @@ -113,3 +113,7 @@ fun Asset.balanceCountedTowardsED(): BigDecimal { fun Asset.transferableReplacingFrozen(newFrozen: Balance): Balance { return transferableMode.calculateTransferable(freeInPlanks, newFrozen, reservedInPlanks) } + +fun Asset.regulatTransferableBalance(): Balance { + return Asset.TransferableMode.REGULAR.calculateTransferable(freeInPlanks, frozenInPlanks, reservedInPlanks) +} From 6e8656c742233df84b4672d180017080f43e0b58 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Wed, 31 Jan 2024 11:56:39 +0100 Subject: [PATCH 47/55] Staking proxy fixes - fixed free balance to transferable in validation - fixed crash on invalid transaction in add/remove proxy interactors - add "stash required" alert on manage proxy click using controller account - add "network not supported" dialog when we try to open unsupported chains in staking --- common/src/main/res/values/strings.xml | 5 ++ .../validation/HasChainAccountValidation.kt | 13 ++++ .../domain/model/relaychain/StakingState.kt | 4 +- .../StakeActionsValidationModule.kt | 75 +++++++++++++++---- .../proxy/RealAddStakingProxyInteractor.kt | 6 +- .../remove/RemoveStakingProxyInteractor.kt | 6 +- .../StashOnlyIsAllowedValidation.kt | 32 ++++++++ .../delegation/proxy/add/Declarations.kt | 2 +- .../delegation/proxy/remove/Declarations.kt | 2 +- .../domain/validations/main/Reused.kt | 7 +- .../main/StakeActionsValidationFailure.kt | 4 + .../controller/set/SetControllerViewModel.kt | 4 +- .../staking/main/ValidationFailure.kt | 6 ++ 13 files changed, 139 insertions(+), 27 deletions(-) create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/StashOnlyIsAllowedValidation.kt diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index d73802dd74..85f1fa83ae 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,6 +1,11 @@ + Select stash account to setup proxy + Please switch your wallet to %s to setup a proxy + + %s not supported + Revoke access type Revoke for Revoke access diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/validation/HasChainAccountValidation.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/validation/HasChainAccountValidation.kt index bd14636758..2471d52faa 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/validation/HasChainAccountValidation.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/domain/validation/HasChainAccountValidation.kt @@ -11,6 +11,7 @@ import io.novafoundation.nova.common.validation.ValidationSystemBuilder import io.novafoundation.nova.common.validation.validationError import io.novafoundation.nova.feature_account_api.R import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount.Type.LEDGER +import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount.Type.PROXIED import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.PolkadotVaultVariant import io.novafoundation.nova.feature_account_api.domain.model.asPolkadotVaultVariantOrNull @@ -32,6 +33,8 @@ interface NoChainAccountFoundError { object LedgerNotSupported : AddAccountState() class PolkadotVaultNotSupported(val variant: PolkadotVaultVariant) : AddAccountState() + + object ProxyAccountNotSupported : AddAccountState() } } @@ -53,6 +56,10 @@ class HasChainAccountValidation( errorProducer(chain, account, AddAccountState.LedgerNotSupported).validationError() } + account.type == PROXIED -> { + errorProducer(chain, account, AddAccountState.ProxyAccountNotSupported).validationError() + } + polkadotVaultVariant != null && chain.isEthereumBased -> { errorProducer(chain, account, AddAccountState.PolkadotVaultNotSupported(polkadotVaultVariant)).validationError() } @@ -91,9 +98,11 @@ fun handleChainAccountNotFound( customStyle = R.style.AccentNegativeAlertDialogTheme ) ) + AddAccountState.LedgerNotSupported -> TransformedFailure.Default( resourceManager.getString(R.string.ledger_chain_not_supported, chainName) to null ) + is AddAccountState.PolkadotVaultNotSupported -> { val vaultLabel = resourceManager.polkadotVaultLabelFor(state.variant) @@ -101,5 +110,9 @@ fun handleChainAccountNotFound( resourceManager.getString(R.string.account_parity_signer_chain_not_supported, vaultLabel, chainName) to null ) } + + AddAccountState.ProxyAccountNotSupported -> TransformedFailure.Default( + resourceManager.getString(R.string.common_network_not_supported, chainName) to null + ) } } diff --git a/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/domain/model/relaychain/StakingState.kt b/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/domain/model/relaychain/StakingState.kt index 2a89071eb4..c36f1943ac 100644 --- a/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/domain/model/relaychain/StakingState.kt +++ b/feature-staking-api/src/main/java/io/novafoundation/nova/feature_staking_api/domain/model/relaychain/StakingState.kt @@ -19,7 +19,7 @@ sealed class StakingState( chainAsset: Chain.Asset, val accountId: AccountId, val controllerId: AccountId, - val stashId: AccountId, + val stashId: AccountId ) : StakingState(chain, chainAsset) { val accountAddress: String = chain.addressOf(accountId) @@ -58,3 +58,5 @@ sealed class StakingState( fun StakingState.Stash.stashTransactionOrigin(): TransactionOrigin = TransactionOrigin.WalletWithAccount(stashId) fun StakingState.Stash.controllerTransactionOrigin(): TransactionOrigin = TransactionOrigin.WalletWithAccount(controllerId) + +fun StakingState.Stash.accountIsStash(): Boolean = accountId.contentEquals(stashId) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/StakeActionsValidationModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/StakeActionsValidationModule.kt index 65bc197a0e..0ef5a5cd07 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/StakeActionsValidationModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/validations/StakeActionsValidationModule.kt @@ -11,10 +11,14 @@ import io.novafoundation.nova.common.validation.ValidationSystem import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_staking_api.domain.api.StakingRepository import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.BALANCE_CONTROLLER_IS_NOT_ALLOWED import io.novafoundation.nova.feature_staking_impl.domain.validations.main.BALANCE_REQUIRED_CONTROLLER -import io.novafoundation.nova.feature_staking_impl.domain.validations.main.BALANCE_REQUIRED_STASH -import io.novafoundation.nova.feature_staking_impl.domain.validations.main.MainStakingAccountRequiredValidation +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.BALANCE_REQUIRED_STASH_META_ACCOUNT +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.ControllerAccountIsNotAllowedValidation +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.MainStakingMetaAccountRequiredValidation import io.novafoundation.nova.feature_staking_impl.domain.validations.main.MainStakingUnlockingLimitValidation +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_ADD_PROXY +import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_PROXIES import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_REWARD_DESTINATION import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_BOND_MORE import io.novafoundation.nova.feature_staking_impl.domain.validations.main.SYSTEM_MANAGE_STAKING_REBAG @@ -40,7 +44,7 @@ class StakeActionsValidationsModule { fun provideControllerValidation( stakingSharedState: StakingSharedState, accountRepository: AccountRepository - ) = MainStakingAccountRequiredValidation( + ) = MainStakingMetaAccountRequiredValidation( accountRepository, accountAddressExtractor = { it.stashState.controllerAddress }, errorProducer = StakeActionsValidationFailure::ControllerRequired, @@ -48,18 +52,31 @@ class StakeActionsValidationsModule { ) @FeatureScope - @Named(BALANCE_REQUIRED_STASH) + @Named(BALANCE_REQUIRED_STASH_META_ACCOUNT) @Provides fun provideStashValidation( stakingSharedState: StakingSharedState, accountRepository: AccountRepository - ) = MainStakingAccountRequiredValidation( + ) = MainStakingMetaAccountRequiredValidation( accountRepository, accountAddressExtractor = { it.stashState.stashAddress }, errorProducer = StakeActionsValidationFailure::StashRequired, sharedState = stakingSharedState ) + @FeatureScope + @Named(BALANCE_CONTROLLER_IS_NOT_ALLOWED) + @Provides + fun provideControllerNotAllowedValidation( + stakingSharedState: StakingSharedState, + accountRepository: AccountRepository + ) = ControllerAccountIsNotAllowedValidation( + accountRepository, + stakingState = { it.stashState }, + errorProducer = StakeActionsValidationFailure::StashRequiredToManageProxies, + sharedState = stakingSharedState + ) + @FeatureScope @Provides fun provideUnbondingLimitValidation( @@ -77,7 +94,7 @@ class StakeActionsValidationsModule { @Provides fun provideRedeemValidationSystem( @Named(BALANCE_REQUIRED_CONTROLLER) - controllerRequiredValidation: MainStakingAccountRequiredValidation, + controllerRequiredValidation: MainStakingMetaAccountRequiredValidation, ) = StakeActionsValidationSystem( CompositeValidation( validations = listOf( @@ -86,12 +103,28 @@ class StakeActionsValidationsModule { ) ) + @FeatureScope + @Named(SYSTEM_MANAGE_PROXIES) + @Provides + fun provideManageProxiesValidationSystem( + @Named(BALANCE_CONTROLLER_IS_NOT_ALLOWED) + controllerAccountIsNotAllowedValidation: ControllerAccountIsNotAllowedValidation, + ) = StakeActionsValidationSystem(controllerAccountIsNotAllowedValidation) + + @FeatureScope + @Named(SYSTEM_ADD_PROXY) + @Provides + fun provideAddProxiesValidationSystem( + @Named(BALANCE_CONTROLLER_IS_NOT_ALLOWED) + controllerAccountIsNotAllowedValidation: ControllerAccountIsNotAllowedValidation, + ) = StakeActionsValidationSystem(controllerAccountIsNotAllowedValidation) + @FeatureScope @Named(SYSTEM_MANAGE_STAKING_BOND_MORE) @Provides fun provideBondMoreValidationSystem( - @Named(BALANCE_REQUIRED_STASH) - stashRequiredValidation: MainStakingAccountRequiredValidation, + @Named(BALANCE_REQUIRED_STASH_META_ACCOUNT) + stashRequiredValidation: MainStakingMetaAccountRequiredValidation, ) = StakeActionsValidationSystem( CompositeValidation( validations = listOf( @@ -105,7 +138,7 @@ class StakeActionsValidationsModule { @Provides fun provideUnbondValidationSystem( @Named(BALANCE_REQUIRED_CONTROLLER) - controllerRequiredValidation: MainStakingAccountRequiredValidation, + controllerRequiredValidation: MainStakingMetaAccountRequiredValidation, balanceUnlockingLimitValidation: MainStakingUnlockingLimitValidation ) = StakeActionsValidationSystem( CompositeValidation( @@ -121,7 +154,7 @@ class StakeActionsValidationsModule { @Provides fun provideRebondValidationSystem( @Named(BALANCE_REQUIRED_CONTROLLER) - controllerRequiredValidation: MainStakingAccountRequiredValidation + controllerRequiredValidation: MainStakingMetaAccountRequiredValidation ) = StakeActionsValidationSystem( CompositeValidation( validations = listOf( @@ -134,8 +167,8 @@ class StakeActionsValidationsModule { @Named(SYSTEM_MANAGE_STAKING_REBAG) @Provides fun provideRebagValidationSystem( - @Named(BALANCE_REQUIRED_STASH) - stashRequiredValidation: MainStakingAccountRequiredValidation + @Named(BALANCE_REQUIRED_STASH_META_ACCOUNT) + stashRequiredValidation: MainStakingMetaAccountRequiredValidation ): StakeActionsValidationSystem = ValidationSystem { validate(stashRequiredValidation) } @@ -145,7 +178,7 @@ class StakeActionsValidationsModule { @Provides fun provideRewardDestinationValidationSystemToMap( @Named(BALANCE_REQUIRED_CONTROLLER) - controllerRequiredValidation: MainStakingAccountRequiredValidation, + controllerRequiredValidation: MainStakingMetaAccountRequiredValidation, ): StakeActionsValidationSystem = StakeActionsValidationSystem(controllerRequiredValidation) } @@ -175,4 +208,20 @@ interface StakeActionsValidationModule { fun provideUnbondValidationSystemToMap( @Named(SYSTEM_MANAGE_STAKING_UNBOND) system: StakeActionsValidationSystem, ): StakeActionsValidationSystem + + @FeatureScope + @StakeActionsValidationKey(SYSTEM_MANAGE_PROXIES) + @IntoMap + @Binds + fun provideManageProxyValidationSystemToMap( + @Named(SYSTEM_MANAGE_PROXIES) system: StakeActionsValidationSystem, + ): StakeActionsValidationSystem + + @FeatureScope + @StakeActionsValidationKey(SYSTEM_ADD_PROXY) + @IntoMap + @Binds + fun provideAddProxyValidationSystemToMap( + @Named(SYSTEM_ADD_PROXY) system: StakeActionsValidationSystem, + ): StakeActionsValidationSystem } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt index 509ce0259f..f256d26bd3 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt @@ -35,10 +35,8 @@ class RealAddStakingProxyInteractor( } override suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { - val result = withContext(Dispatchers.IO) { - extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { - addProxyCall(proxyAccountId, ProxyType.Staking) - } + val result = extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { + addProxyCall(proxyAccountId, ProxyType.Staking) } return result.awaitInBlock().also { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt index 0603ab3681..5a2a380b71 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt @@ -35,10 +35,8 @@ class RealRemoveStakingProxyInteractor( } override suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { - val result = withContext(Dispatchers.IO) { - extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { - removeProxyCall(proxyAccountId, ProxyType.Staking) - } + val result = extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { + removeProxyCall(proxyAccountId, ProxyType.Staking) } return result.awaitInBlock().also { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/StashOnlyIsAllowedValidation.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/StashOnlyIsAllowedValidation.kt new file mode 100644 index 0000000000..5e80aa29c9 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/StashOnlyIsAllowedValidation.kt @@ -0,0 +1,32 @@ +package io.novafoundation.nova.feature_staking_impl.domain.validations + +import io.novafoundation.nova.common.validation.DefaultFailureLevel +import io.novafoundation.nova.common.validation.Validation +import io.novafoundation.nova.common.validation.ValidationStatus +import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount +import io.novafoundation.nova.feature_staking_api.domain.model.relaychain.StakingState +import io.novafoundation.nova.feature_staking_api.domain.model.relaychain.accountIsStash +import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState +import io.novafoundation.nova.runtime.state.chain + +class StashOnlyIsAllowedValidation( + val accountRepository: AccountRepository, + val stakingState: (P) -> StakingState, + val sharedState: StakingSharedState, + val errorProducer: (stashAddress: String, stashAccount: MetaAccount?) -> E +) : Validation { + + override suspend fun validate(value: P): ValidationStatus { + val stakingState = stakingState(value) + if (stakingState !is StakingState.Stash) return ValidationStatus.Valid() + + return if (stakingState.accountIsStash()) { + ValidationStatus.Valid() + } else { + val chain = sharedState.chain() + val stashMetaAccount = accountRepository.findMetaAccount(stakingState.stashId, chain.id) + ValidationStatus.NotValid(DefaultFailureLevel.ERROR, errorProducer(stakingState.stashAddress, stashMetaAccount)) + } + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt index c4b64f81ea..d3e3bee3e9 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt @@ -44,7 +44,7 @@ fun AddStakingProxyValidationSystemBuilder.sufficientBalanceToStayAboveEd( fun AddStakingProxyValidationSystemBuilder.sufficientBalanceToPayFee() = sufficientBalance( - available = { it.asset.free }, + available = { it.asset.transferable }, amount = { BigDecimal.ZERO }, fee = { it.fee }, error = { context -> diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt index 0a2baa4fd3..7da3fac0d2 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/remove/Declarations.kt @@ -27,7 +27,7 @@ fun RemoveStakingProxyValidationSystemBuilder.sufficientBalanceToStayAboveEd( fun RemoveStakingProxyValidationSystemBuilder.sufficientBalanceToPayFee() { return sufficientBalance( - available = { it.asset.free }, + available = { it.asset.transferable }, amount = { BigDecimal.ZERO }, fee = { it.fee }, error = { context -> diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/Reused.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/Reused.kt index 4646c0311d..28fbea3e7b 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/Reused.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/Reused.kt @@ -1,10 +1,13 @@ package io.novafoundation.nova.feature_staking_impl.domain.validations.main import io.novafoundation.nova.feature_staking_impl.domain.validations.AccountRequiredValidation +import io.novafoundation.nova.feature_staking_impl.domain.validations.StashOnlyIsAllowedValidation import io.novafoundation.nova.feature_staking_impl.domain.validations.UnbondingRequestsLimitValidation -const val BALANCE_REQUIRED_STASH = "MainStakingAccountRequiredValidation.Stash" +const val BALANCE_CONTROLLER_IS_NOT_ALLOWED = "ControllerAccountIsNotAllowedValidation" +const val BALANCE_REQUIRED_STASH_META_ACCOUNT = "MainStakingAccountRequiredValidation.Stash" const val BALANCE_REQUIRED_CONTROLLER = "MainStakingAccountRequiredValidation.Controller" -typealias MainStakingAccountRequiredValidation = AccountRequiredValidation +typealias ControllerAccountIsNotAllowedValidation = StashOnlyIsAllowedValidation +typealias MainStakingMetaAccountRequiredValidation = AccountRequiredValidation typealias MainStakingUnlockingLimitValidation = UnbondingRequestsLimitValidation diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/StakeActionsValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/StakeActionsValidationFailure.kt index 990baaac19..aec7cd171c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/StakeActionsValidationFailure.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/main/StakeActionsValidationFailure.kt @@ -1,5 +1,7 @@ package io.novafoundation.nova.feature_staking_impl.domain.validations.main +import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount + sealed class StakeActionsValidationFailure { class UnbondingRequestLimitReached(val limit: Int) : StakeActionsValidationFailure() @@ -7,4 +9,6 @@ sealed class StakeActionsValidationFailure { class ControllerRequired(val controllerAddress: String) : StakeActionsValidationFailure() class StashRequired(val stashAddress: String) : StakeActionsValidationFailure() + + class StashRequiredToManageProxies(val stashAddress: String, val stashMetaAccount: MetaAccount?) : StakeActionsValidationFailure() } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerViewModel.kt index ca5746e1a9..d8d64f4e1a 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/controller/set/SetControllerViewModel.kt @@ -24,6 +24,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.account.icon.cre import io.novafoundation.nova.feature_account_api.presenatation.actions.ExternalActions import io.novafoundation.nova.feature_staking_api.domain.model.StakingAccount import io.novafoundation.nova.feature_staking_api.domain.model.relaychain.StakingState +import io.novafoundation.nova.feature_staking_api.domain.model.relaychain.accountIsStash import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.data.repository.ControllersDeprecationStage import io.novafoundation.nova.feature_staking_impl.data.repository.ControllersDeprecationStage.DEPRECATED @@ -252,7 +253,7 @@ class SetControllerViewModel( } private fun StakingState.Stash.isUsingCorrectAccountToChangeController(): Boolean { - return accountId.contentEquals(stashId) + return accountIsStash() } private fun StakingState.Stash.isUsingWrongAccountToChangeController(): Boolean { @@ -271,6 +272,7 @@ class SetControllerViewModel( imageRes = R.drawable.shield, bannerBackgroundRes = R.drawable.ic_banner_grey_gradient ) + DEPRECATED -> AdvertisementCardModel( title = resourceManager.getString(R.string.staking_set_controller_deprecated_title), subtitle = resourceManager.getString(R.string.staking_set_controller_deprecated_subtitle), diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/ValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/ValidationFailure.kt index 4e31295ec8..0a87047bfe 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/ValidationFailure.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/main/ValidationFailure.kt @@ -19,9 +19,15 @@ fun mainStakingValidationFailure( getString(R.string.staking_unbonding_limit_reached_title) to getString(R.string.staking_unbonding_limit_reached_message, reason.limit) } + is StakeActionsValidationFailure.StashRequired -> { getString(R.string.common_error_general_title) to getString(R.string.staking_stash_missing_message, reason.stashAddress) } + + is StakeActionsValidationFailure.StashRequiredToManageProxies -> { + getString(R.string.staking_manage_proxy_requires_stash_title) to + getString(R.string.staking_manage_proxy_requires_stash_message, reason.stashMetaAccount?.name ?: reason.stashAddress) + } } } From 13931b3b8da34b24aeaf0fd424d5facaef165799 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Wed, 31 Jan 2024 12:22:04 +0100 Subject: [PATCH 48/55] Fixed w3n on add staking proxy --- .../novafoundation/nova/common/utils/keyboard/KeyboardExt.kt | 3 +++ .../presenatation/mixin/addressInput/AddressInputMixinUi.kt | 3 +++ .../proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt | 5 ++--- .../delegation/proxy/add/set/AddStakingProxyFragment.kt | 2 +- .../delegation/proxy/add/set/AddStakingProxyViewModel.kt | 4 ++-- .../proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt | 4 +--- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/keyboard/KeyboardExt.kt b/common/src/main/java/io/novafoundation/nova/common/utils/keyboard/KeyboardExt.kt index d808719f51..362f125a31 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/keyboard/KeyboardExt.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/keyboard/KeyboardExt.kt @@ -27,6 +27,9 @@ fun View.showSoftKeyboard() { inputMethodManager.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT) } +/** + * Make sure that the insets are not consumed by the layer above for this method to work correctly + */ fun Lifecycle.setKeyboardVisibilityListener(view: View, callback: KeyboardVisibilityCallback?) { if (callback == null) { ViewCompat.setOnApplyWindowInsetsListener(view, null) diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/addressInput/AddressInputMixinUi.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/addressInput/AddressInputMixinUi.kt index bcd1eb7082..81e6b34509 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/addressInput/AddressInputMixinUi.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/presenatation/mixin/addressInput/AddressInputMixinUi.kt @@ -27,6 +27,9 @@ fun BaseFragment<*>.setupAddressInput( mixin.state.observe(::setState) } +/** + * Make sure that the insets are not consumed by the layer above for this method to work correctly + */ fun BaseFragment<*>.setupExternalAccounts( mixin: AddressInputMixin, inputField: AddressInputField diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt index 2cc8565a87..99359b1b76 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/confirm/ConfirmAddStakingProxyViewModel.kt @@ -130,9 +130,8 @@ class ConfirmAddStakingProxyViewModel( validationProgressFlow.value = false - if (result.isSuccess) { - router.returnToStakingMain() - } + result.onSuccess { router.returnToStakingMain() } + .onFailure(::showError) } private suspend fun generateAccountAddressModel(chain: Chain, address: String) = addressIconGenerator.createAccountAddressModel( diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyFragment.kt index 62f87860e3..f9b8c6c86d 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyFragment.kt @@ -39,7 +39,7 @@ class AddStakingProxyFragment : BaseFragment() { } override fun initViews() { - setStakingProxyContainer.applyStatusBarInsets() + setStakingProxyContainer.applyStatusBarInsets(consume = false) addProxyToolbar.setHomeButtonListener { viewModel.backClicked() } addStakingProxyButton.prepareForProgress(this) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt index 969a6ee619..5d6bb08f55 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/add/set/AddStakingProxyViewModel.kt @@ -170,7 +170,7 @@ class AddStakingProxyViewModel( fun selectAuthorityWallet() { launch { - val selectedAddress = addressInputMixin.inputFlow.value + val selectedAddress = addressInputMixin.getAddress() selectAddressMixin.openSelectAddress(selectedAddress) } } @@ -182,7 +182,7 @@ class AddStakingProxyViewModel( val validationPayload = AddStakingProxyValidationPayload( chain = chain, asset = selectedAssetFlow.first(), - proxyAddress = addressInputMixin.inputFlow.value, + proxyAddress = addressInputMixin.getAddress(), proxiedAccountId = metaAccount.requireAccountIdIn(chain), fee = feeMixin.awaitDecimalFee(), deltaDeposit = proxyDepositDelta.first(), diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt index 60264a6088..f781098f50 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/revoke/ConfirmRemoveStakingProxyViewModel.kt @@ -145,9 +145,7 @@ class ConfirmRemoveStakingProxyViewModel( validationProgressFlow.value = false - result.onSuccess { - router.returnToStakingMain() - } + result.onSuccess { router.returnToStakingMain() } .onFailure(::showError) } From 76459cf859707bc4d685bdeb429785421367b00a Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Thu, 1 Feb 2024 10:10:10 +0100 Subject: [PATCH 49/55] Add staking proxy fixes - Fixed crash on submitAndWatchExtrinsic exception - Activete deactivated proxies in case when we have deactivated proxy in DB but onchain the proxy is exist --- .../data/extrinsic/ExtrinsicServiceExt.kt | 2 +- .../data/extrinsic/RealExtrinsicService.kt | 2 ++ .../data/proxy/RealProxySyncService.kt | 13 ++++++++++++- .../proxy/RealAddStakingProxyInteractor.kt | 10 +++++----- .../proxy/remove/RemoveStakingProxyInteractor.kt | 10 +++++----- .../proxy/add/AddStakingProxyValidationFailure.kt | 2 +- .../delegation/proxy/add/Declarations.kt | 6 +++--- .../common/AddProxyValidationFailureHandling.kt | 2 +- .../nova/feature_wallet_api/domain/model/Asset.kt | 2 +- 9 files changed, 31 insertions(+), 18 deletions(-) diff --git a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/extrinsic/ExtrinsicServiceExt.kt b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/extrinsic/ExtrinsicServiceExt.kt index 9a7b95da70..7cc932d323 100644 --- a/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/extrinsic/ExtrinsicServiceExt.kt +++ b/feature-account-api/src/main/java/io/novafoundation/nova/feature_account_api/data/extrinsic/ExtrinsicServiceExt.kt @@ -5,6 +5,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first -suspend fun Result>.awaitInBlock(): Result = map { +suspend fun Result>.awaitInBlock(): Result = mapCatching { it.filterIsInstance().first() } diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/extrinsic/RealExtrinsicService.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/extrinsic/RealExtrinsicService.kt index 781c97c595..ea8db504a4 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/extrinsic/RealExtrinsicService.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/extrinsic/RealExtrinsicService.kt @@ -75,6 +75,8 @@ class RealExtrinsicService( ) } + // TODO: The flow in Result may produce an exception that will be not handled since Result can't catch an exception inside a flow + // For now it's handling in awaitInBlock() extension override suspend fun submitAndWatchExtrinsic( chain: Chain, origin: TransactionOrigin, diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt index dbe58161b2..c5eca74171 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/proxy/RealProxySyncService.kt @@ -15,6 +15,7 @@ import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService import io.novafoundation.nova.feature_account_api.domain.account.identity.Identity import io.novafoundation.nova.feature_account_api.domain.account.identity.IdentityProvider import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository +import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount import io.novafoundation.nova.feature_account_api.domain.model.hasAccountIn import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdIn @@ -33,12 +34,14 @@ import kotlinx.coroutines.launch private class CreateMetaAccountsResult( val addedMetaIds: MutableList = mutableListOf(), - val alreadyExistedMetaIds: MutableList = mutableListOf() + val alreadyExistedMetaIds: MutableList = mutableListOf(), + val shouldBeActivatedMetaIds: MutableList = mutableListOf() ) { fun add(other: CreateMetaAccountsResult) { addedMetaIds.addAll(other.addedMetaIds) alreadyExistedMetaIds.addAll(other.alreadyExistedMetaIds) + shouldBeActivatedMetaIds.addAll(other.shouldBeActivatedMetaIds) } } @@ -103,6 +106,7 @@ class RealProxySyncService( val deactivatedMetaIds = result.findDeactivated(oldProxies) accountDao.changeAccountsStatus(deactivatedMetaIds, MetaAccountLocal.Status.DEACTIVATED) + accountDao.changeAccountsStatus(result.shouldBeActivatedMetaIds, MetaAccountLocal.Status.ACTIVE) val changedMetaIds = result.addedMetaIds + deactivatedMetaIds metaAccountsUpdatesRegistry.addMetaIds(changedMetaIds) @@ -150,6 +154,13 @@ class RealProxySyncService( result.addedMetaIds.add(newMetaId) newMetaId } else { + // An account may be deactivated but not deleted yet in case when we remove a proxy and then add it again + // To support this case we should track deactivated accounts and activate them again + val existedMetaAccount = accountRepository.getMetaAccount(maybeExistedProxiedMetaId) + if (existedMetaAccount.status == LightMetaAccount.Status.DEACTIVATED) { + result.shouldBeActivatedMetaIds.add(maybeExistedProxiedMetaId) + } + result.alreadyExistedMetaIds.add(maybeExistedProxiedMetaId) maybeExistedProxiedMetaId } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt index f256d26bd3..c99edce477 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/RealAddStakingProxyInteractor.kt @@ -35,12 +35,12 @@ class RealAddStakingProxyInteractor( } override suspend fun addProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { - val result = extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { - addProxyCall(proxyAccountId, ProxyType.Staking) - } + return withContext(Dispatchers.Default) { + val result = extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { + addProxyCall(proxyAccountId, ProxyType.Staking) + } - return result.awaitInBlock().also { - proxySyncService.startSyncing() + result.awaitInBlock().also { proxySyncService.startSyncing() } } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt index 5a2a380b71..a293b1bce5 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/delegation/proxy/remove/RemoveStakingProxyInteractor.kt @@ -35,12 +35,12 @@ class RealRemoveStakingProxyInteractor( } override suspend fun removeProxy(chain: Chain, proxiedAccountId: AccountId, proxyAccountId: AccountId): Result { - val result = extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { - removeProxyCall(proxyAccountId, ProxyType.Staking) - } + return withContext(Dispatchers.Default) { + val result = extrinsicService.submitAndWatchExtrinsic(chain, proxiedAccountId.intoOrigin()) { + removeProxyCall(proxyAccountId, ProxyType.Staking) + } - return result.awaitInBlock().also { - proxySyncService.startSyncing() + result.awaitInBlock().also { proxySyncService.startSyncing() } } } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt index f92e850fa0..ec7cbcc86c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/AddStakingProxyValidationFailure.kt @@ -18,7 +18,7 @@ sealed interface AddStakingProxyValidationFailure { class NotEnoughBalanceToReserveDeposit( val chainAsset: Chain.Asset, - val availableBalance: Balance, + val maxUsable: Balance, val deposit: Balance ) : AddStakingProxyValidationFailure diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt index d3e3bee3e9..f51ee4604e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/delegation/proxy/add/Declarations.kt @@ -11,7 +11,7 @@ import io.novafoundation.nova.feature_proxy_api.domain.validators.proxyIsNotDupl import io.novafoundation.nova.feature_wallet_api.domain.model.amountFromPlanks import io.novafoundation.nova.feature_wallet_api.domain.model.balanceCountedTowardsED import io.novafoundation.nova.feature_wallet_api.domain.model.planksFromAmount -import io.novafoundation.nova.feature_wallet_api.domain.model.regulatTransferableBalance +import io.novafoundation.nova.feature_wallet_api.domain.model.regularTransferableBalance import io.novafoundation.nova.feature_wallet_api.domain.validation.EnoughTotalToStayAboveEDValidationFactory import io.novafoundation.nova.feature_wallet_api.domain.validation.sufficientBalance import io.novafoundation.nova.feature_wallet_api.domain.validation.validAddress @@ -74,12 +74,12 @@ fun AddStakingProxyValidationSystemBuilder.maximumProxies( fun AddStakingProxyValidationSystemBuilder.enoughBalanceToPayDepositAndFee() = sufficientBalance( fee = { it.fee }, amount = { it.asset.token.configuration.amountFromPlanks(it.deltaDeposit) }, - available = { it.asset.token.amountFromPlanks(it.asset.regulatTransferableBalance()) }, + available = { it.asset.token.amountFromPlanks(it.asset.regularTransferableBalance()) }, error = { val chainAsset = it.payload.asset.token.configuration AddStakingProxyValidationFailure.NotEnoughBalanceToReserveDeposit( chainAsset = chainAsset, - availableBalance = chainAsset.planksFromAmount(it.maxUsable), + maxUsable = chainAsset.planksFromAmount(it.maxUsable), deposit = it.payload.deltaDeposit ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt index 9442a58431..f0b3bbd415 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/AddProxyValidationFailureHandling.kt @@ -22,7 +22,7 @@ fun mapAddStakingProxyValidationFailureToUi( resourceManager.getString( R.string.staking_not_enough_balance_to_pay_proxy_deposit_message, failure.deposit.formatPlanks(failure.chainAsset), - failure.availableBalance.formatPlanks(failure.chainAsset) + failure.maxUsable.formatPlanks(failure.chainAsset) ) is InvalidAddress -> resourceManager.getString(R.string.invalid_proxy_address_title) to diff --git a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt index 50519a191c..914a90f75f 100644 --- a/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt +++ b/feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/domain/model/Asset.kt @@ -114,6 +114,6 @@ fun Asset.transferableReplacingFrozen(newFrozen: Balance): Balance { return transferableMode.calculateTransferable(freeInPlanks, newFrozen, reservedInPlanks) } -fun Asset.regulatTransferableBalance(): Balance { +fun Asset.regularTransferableBalance(): Balance { return Asset.TransferableMode.REGULAR.calculateTransferable(freeInPlanks, frozenInPlanks, reservedInPlanks) } From bd02ca905971bab7187298c922d455e3684a7b54 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 6 Feb 2024 10:15:42 +0100 Subject: [PATCH 50/55] Fixed pr notes --- .../domain/validations/StashOnlyIsAllowedValidation.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/StashOnlyIsAllowedValidation.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/StashOnlyIsAllowedValidation.kt index 5e80aa29c9..5d53a8a41a 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/StashOnlyIsAllowedValidation.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/validations/StashOnlyIsAllowedValidation.kt @@ -19,7 +19,7 @@ class StashOnlyIsAllowedValidation( override suspend fun validate(value: P): ValidationStatus { val stakingState = stakingState(value) - if (stakingState !is StakingState.Stash) return ValidationStatus.Valid() + if (stakingState !is StakingState.Stash) throw IllegalStateException("StashOnlyIsAllowedValidation can be used only for Stash state") return if (stakingState.accountIsStash()) { ValidationStatus.Valid() From aea858fa7eaaac31412e2c8d7a9cd4342f5419d1 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 6 Feb 2024 11:53:31 +0100 Subject: [PATCH 51/55] Run ktlint --- .../presentation/send/amount/SelectSendViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt index b59d6bdae6..119975a614 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt @@ -14,7 +14,6 @@ import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.ButtonState import io.novafoundation.nova.feature_account_api.data.mappers.mapChainToUi -import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor From eddd8fdd88697125abd3c219f37f56423b473767 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 6 Feb 2024 13:11:14 +0100 Subject: [PATCH 52/55] Localization --- common/src/main/res/values-ru/strings.xml | 34 +++++++++++++++++-- common/src/main/res/values/strings.xml | 3 -- .../common/ProxyDepositDescriptionSetupExt.kt | 2 +- .../fragment_confirm_revoke_staking_proxy.xml | 2 +- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/common/src/main/res/values-ru/strings.xml b/common/src/main/res/values-ru/strings.xml index 3d098b212b..049848f496 100644 --- a/common/src/main/res/values-ru/strings.xml +++ b/common/src/main/res/values-ru/strings.xml @@ -142,6 +142,13 @@ Изменить аккаунт %s Изменить аккаунт Вы должны добавить %s аккаунт в кошелек, чтобы иметь возможность делегировать + Делегировать аккаунту + Аккаунт делегирования + Кошелек делегирования + Тип доступа + Депозит остается зарезервированным на вашем счете до тех пор, пока прокси не будет удален. + Вы достигли лимита добавленных прокси (%s) в %s . Удалите прокси, чтобы добавить новые. + Достигнуто максимальное количество прокси Введенный адрес контракта уже добавлен в Nova как токен %s. Введенный адрес контракта присутствует в Nova как токен %s. Вы уверены, что хотите изменить его? Этот токен уже добавлен @@ -198,6 +205,7 @@ Адрес аккаунта Активно Добавить + Добавить делегацию Адрес Продвинутый Все @@ -246,8 +254,10 @@ %s (и еще %s) Выберите приложение для работы с почтой Включить + Введите адрес… Введите сумму... Ошибка + Недостаточно токенов Событие EVM Адрес Ваша учетная запись будет удалена из сети после операции, так как ваш баланс опустится ниже минимального @@ -296,6 +306,7 @@ %s аккаунт отсутствует Модуль Сеть + Сеть %s не поддерживается Сети Сеть @@ -330,6 +341,8 @@ Необходимы разрешения Цена Продолжить + Прокси депозит + Отозвать доступ Подробнее Рекомендовано Обновить @@ -494,7 +507,6 @@ результаты поиска: %d Nova Wallet автоматически добавляет делегированные аккаунты (Прокси) в отдельную категорию для вас. Вы всегда можете управлять кошельками в Настройках. Обновление делегированных аккаунтов - Добавить делегацию Голоса за все время Делегат Все аккаунты @@ -534,6 +546,8 @@ Ваша делегация Ваши делегации Показывать + Вы уже делегируете полномочия этому аккаунту: %s + Делегация уже существует (BTC/ETH совместимый) ECDSA ed25519 (альтернативный) @@ -549,6 +563,7 @@ Сеть: %s\nМнемоника: %s Подождите, пока будет рассчитана комиссия Расчет комиссии в процессе + Добавить делегацию для %s стекинга Детали обмена Макс: Вы платите @@ -573,6 +588,8 @@ Ваша мнемоника недействительна Пожалуйста, убедитесь, что введенные данные содержат 64 hex символа. Сид неверный + Адрес прокси должен быть действительным адресом %s + Неверный адрес прокси Не удается декодировать QR QR код Из галереи @@ -670,6 +687,7 @@ Этот аккаунт предоставил доступ для выполнения транзакций следующему аккаунту: Более не действительны Что такое прокси? + Операции стейкинга Делегированный аккаунт %s не имеет достаточного баланса для оплаты сетевой комиссии %s. Доступный баланс для оплаты комиссии: %s Проксированные кошельки не поддерживают подпись произвольных сообщений - только транзакций %1$s не делегировал прав %2$s @@ -792,6 +810,8 @@ Вы набрали максимальное количество голосов за трек: %s Достигнуто максимальное количество голосов У вас недостаточно токенов для голосования. Доступно для голосования: %s. + Отзываемый типа доступа + Отозвать у Удалить голоса Вы ранее голосовали в референдумах в %d треке. Для того, чтобы сделать этот трек доступным для делегирования вам необходимо удалить голоса. @@ -822,6 +842,7 @@ Адрес или w3n Получатель является системным аккаунтом. Этот аккаунт не контролируется какой-либо компанией или частным лицом. \nВы уверены, что все еще хотите выполнить данный перевод? Токены будут потеряны + Выдать полномочия аккаунту Пожалуйста, убедитесь, что биометрия включена в настройках Биометрия отключена в настройках Сообщество @@ -852,11 +873,12 @@ Неподдерживаемый тип стейкинга sr25519 (рекомендованный) Schnorrkel - Добавьте учетную запись контроллера в устройство. - Нет доступа к учетной записи контроллера Выбранный аккаунт уже используется в качестве контроллера. + Делегировать полномочия (прокси) + Ваши делегации Активные делегаторы Чтобы выполнить это действие, добавьте контроллер аккаунт %s в приложение + Добавить делегацию Ваш стейк меньше минимума %s.\nСтейк меньше минимума уменьшает шансы получить вознаграждение Застейкайте ещё токенов Смените своих валидаторов. @@ -924,6 +946,8 @@ Минимальный стейк Сеть %s Застейкано + Пожалуйста, переключите свой кошелек на %s , чтобы настроить прокси. + Выберите стэш-аккаунт для настройки прокси Управление %s (макс. %s ) Достигнуто максимальное количество номинаторов. Пожалуйста, попробуйте позже @@ -931,6 +955,8 @@ Мин. стейк Вы должны добавить %s аккаунт в кошелек для того, чтобы начать стейкинг Eжемесячно + Добавьте учетную запись контроллера в устройство. + Нет доступа к учетной записи контроллера Номинировано: %s вознаграждены Один из ваших валидаторов был выбран сетью. @@ -942,6 +968,7 @@ Неактивен Ожидание следующей Эры ожидание следующей эры (%s) + У вас недостаточный баланс для прокси-депозита %s. Доступный баланс: %s Коллатор Минимальный стейк коллатора выше, чем ваша делегация. Вы не будете получать вознаграждения от этого коллатора. Информация о коллаторе @@ -1004,6 +1031,7 @@ Последний год (1Г) Ваш доступный баланс составляет %s, вам необходимо оставить %s в качестве минимального баланса и оплатить комиссию сети в размере %s. Таким образом, вы можете застейкать не более %s. + Делегированные полномочия (прокси) Текущий слот очереди Новый слот очереди Вернуть в стейк diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 85f1fa83ae..e8e749ba75 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -8,9 +8,7 @@ Revoke access type Revoke for - Revoke access - Add delegation Delegated authorities (proxy) @@ -31,7 +29,6 @@ Invalid proxy address Proxy address should be a valid %s address - Proxy deposit The deposit stays reserved on your account until the proxy is removed. Maximum number of proxies has been reached diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/ProxyDepositDescriptionSetupExt.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/ProxyDepositDescriptionSetupExt.kt index 0d17934050..6802f10e2a 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/ProxyDepositDescriptionSetupExt.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/delegation/proxy/common/ProxyDepositDescriptionSetupExt.kt @@ -5,7 +5,7 @@ import io.novafoundation.nova.feature_staking_impl.R fun DescriptionBottomSheetLauncher.launchProxyDepositDescription() { launchDescriptionBottomSheet( - titleRes = R.string.add_proxy_deposit_description_title, + titleRes = R.string.common_proxy_deposit, descriptionRes = R.string.add_proxy_deposit_description_message ) } diff --git a/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml b/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml index efa48484a1..6510d6ee33 100644 --- a/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml +++ b/feature-staking-impl/src/main/res/layout/fragment_confirm_revoke_staking_proxy.xml @@ -13,7 +13,7 @@ android:layout_height="wrap_content" app:dividerVisible="false" app:layout_constraintTop_toTopOf="parent" - app:titleText="@string/remove_proxy_title" /> + app:titleText="@string/common_proxy_rewoke_access" /> Date: Tue, 6 Feb 2024 13:14:30 +0100 Subject: [PATCH 53/55] Run ktlint --- .../presentation/send/amount/SelectSendViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt index b59d6bdae6..119975a614 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/send/amount/SelectSendViewModel.kt @@ -14,7 +14,6 @@ import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.common.view.ButtonState import io.novafoundation.nova.feature_account_api.data.mappers.mapChainToUi -import io.novafoundation.nova.feature_account_api.data.model.Fee import io.novafoundation.nova.feature_account_api.domain.filter.selectAddress.SelectAddressAccountFilter import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository import io.novafoundation.nova.feature_account_api.domain.interfaces.MetaAccountGroupingInteractor From b8162f21766625405d8fce6471a452e980a0ce8b Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 6 Feb 2024 14:15:33 +0100 Subject: [PATCH 54/55] Update build.gradle --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c89eab9c3f..01b7b74e35 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,8 @@ buildscript { ext { // App version - versionName = '7.7.5' - versionCode = 114 + versionName = '7.8.0' + versionCode = 115 applicationId = "io.novafoundation.nova" releaseApplicationSuffix = "market" From ada953d4f6694bb2085ef2d353cdaf8372a40c12 Mon Sep 17 00:00:00 2001 From: antonijzelinskij Date: Tue, 6 Feb 2024 14:46:55 +0100 Subject: [PATCH 55/55] Changed banner text for deprecated controller account --- common/src/main/res/values-ru/strings.xml | 2 +- common/src/main/res/values/strings.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common/src/main/res/values-ru/strings.xml b/common/src/main/res/values-ru/strings.xml index 049848f496..6a60331e1d 100644 --- a/common/src/main/res/values-ru/strings.xml +++ b/common/src/main/res/values-ru/strings.xml @@ -1074,7 +1074,7 @@ выбрано %d (макс. %d) Валидаторы (%d) Изменить контроллер на стэш - Сеть мигрирует в сторону замены контроллеров на прокси. Nova Wallet будет поддерживать прокси в будущих обновлениях + Используйте прокси для делегирования операций стейкинга другому аккаунту Контроллер Аккаунты Устаревают Выберите другой аккаунт в качестве контроллера, чтобы делегировать ему операции по управлению стейкингом Улучшите безопасность стейкинга diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index e8e749ba75..1f3611c872 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,6 +1,8 @@ + Use Proxies to delegate Staking operations to another account + Select stash account to setup proxy Please switch your wallet to %s to setup a proxy @@ -366,7 +368,6 @@ Polkadot Vault Controller Accounts Are Being Deprecated - Network is migrating towards replacing Controllers to Proxies feature. Nova Wallet will support Proxies in future updates Update Controller to Stash No networks or tokens with entered\nname were found