From 0c8e53f5d394df2704b2f42c583f83e64f3b6a62 Mon Sep 17 00:00:00 2001 From: Radmir Date: Thu, 23 Apr 2026 14:16:17 +0500 Subject: [PATCH 1/4] Fix Android Monad stake delegation routing Scope delegation lookup by state so multiple positions on the same validator (Active / Activating / Deactivating / AwaitingWithdrawal) open their own detail screen instead of collapsing to the first match. Also hide the orphaned "Manage" header when the actions list is empty, and keep watch wallets off the Confirm screen when tapping an AwaitingWithdrawal row. --- .../gemwallet/android/ui/navigation/routes/Stake.kt | 9 +++++---- .../data/repositories/stake/StakeRepository.kt | 5 +++-- .../transactions/TransactionBalanceService.kt | 1 + .../transactions/TransactionBalanceServiceTest.kt | 5 +++-- .../android/data/service/store/database/StakeDao.kt | 5 +++-- .../delegation/viewmodels/DelegationViewModel.kt | 12 ++++++++---- .../android/features/stake/presents/StakeScreen.kt | 3 ++- .../stake/presents/components/StakeActions.kt | 3 +++ .../features/stake/viewmodels/StakeViewModel.kt | 7 ++++--- .../transfer_amount/viewmodels/AmountViewModel.kt | 4 +++- .../main/kotlin/com/gemwallet/android/ext/Wallet.kt | 6 +++++- .../com/gemwallet/android/model/AmountParams.kt | 4 ++++ 12 files changed, 44 insertions(+), 20 deletions(-) diff --git a/android/app/src/main/kotlin/com/gemwallet/android/ui/navigation/routes/Stake.kt b/android/app/src/main/kotlin/com/gemwallet/android/ui/navigation/routes/Stake.kt index acc022013b..7ac5589a2c 100644 --- a/android/app/src/main/kotlin/com/gemwallet/android/ui/navigation/routes/Stake.kt +++ b/android/app/src/main/kotlin/com/gemwallet/android/ui/navigation/routes/Stake.kt @@ -11,26 +11,27 @@ import com.gemwallet.android.ui.models.actions.AmountTransactionAction import com.gemwallet.android.features.earn.delegation.presents.DelegationScene import com.gemwallet.android.features.stake.presents.StakeScreen import com.wallet.core.primitives.AssetId +import com.wallet.core.primitives.DelegationState import kotlinx.serialization.Serializable @Serializable data class StakeRoute(val assetId: String) @Serializable -data class DelegationRoute(val validatorId: String, val delegationId: String) +data class DelegationRoute(val validatorId: String, val delegationId: String, val state: String) fun NavController.navigateToStake(assetId: AssetId, navOptions: NavOptions? = null) { navigate(StakeRoute(assetId.toIdentifier()), navOptions ?: navOptions { launchSingleTop = true }) } -fun NavController.navigateToDelegation(validatorId: String, delegationId: String) { - navigate(DelegationRoute(validatorId, delegationId), navOptions = navOptions { launchSingleTop = true }) +fun NavController.navigateToDelegation(validatorId: String, delegationId: String, state: DelegationState) { + navigate(DelegationRoute(validatorId, delegationId, state.name), navOptions = navOptions { launchSingleTop = true }) } fun NavGraphBuilder.stake( onAmount: AmountTransactionAction, onConfirm: (ConfirmParams) -> Unit, - onDelegation: (String, String) -> Unit, + onDelegation: (String, String, DelegationState) -> Unit, onCancel: () -> Unit, ) { composable { entry -> diff --git a/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/stake/StakeRepository.kt b/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/stake/StakeRepository.kt index 8548582206..1e8e3dffd9 100644 --- a/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/stake/StakeRepository.kt +++ b/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/stake/StakeRepository.kt @@ -10,6 +10,7 @@ import com.wallet.core.primitives.AssetId import com.wallet.core.primitives.Chain import com.wallet.core.primitives.Delegation import com.wallet.core.primitives.DelegationBase +import com.wallet.core.primitives.DelegationState import com.wallet.core.primitives.DelegationValidator import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow @@ -87,8 +88,8 @@ class StakeRepository( .map { items -> items.mapNotNull { it.toModel() } } } - fun getDelegation(validatorId: String, delegationId: String = ""): Flow { - return stakeDao.getDelegation(validatorId = validatorId, delegationId = delegationId) + fun getDelegation(validatorId: String, delegationId: String, state: DelegationState): Flow { + return stakeDao.getDelegation(validatorId = validatorId, delegationId = delegationId, state = state) .map { it?.toModel() } } diff --git a/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceService.kt b/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceService.kt index de1f850799..1f23dd4017 100644 --- a/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceService.kt +++ b/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceService.kt @@ -46,6 +46,7 @@ class TransactionBalanceService @Inject constructor( val currentDelegation = stakeRepository.getDelegation( validatorId = delegation.base.validatorId, delegationId = delegation.base.delegationId, + state = delegation.base.state, ).firstOrNull() ?: delegation return TransactionBalanceContext( delegationBalance = currentDelegation.base.balance.toBigIntegerOrNull() ?: BigInteger.ZERO, diff --git a/android/data/repositories/src/test/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceServiceTest.kt b/android/data/repositories/src/test/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceServiceTest.kt index d1ec9c4b9f..ceb242b6eb 100644 --- a/android/data/repositories/src/test/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceServiceTest.kt +++ b/android/data/repositories/src/test/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceServiceTest.kt @@ -10,6 +10,7 @@ import com.gemwallet.android.testkit.mockAssetInfo import com.gemwallet.android.testkit.mockDelegation import com.gemwallet.android.testkit.mockDelegationValidator import com.gemwallet.android.testkit.mockAssetMonad +import com.wallet.core.primitives.DelegationState import com.wallet.core.primitives.TransactionType import io.mockk.coEvery import io.mockk.every @@ -75,7 +76,7 @@ class TransactionBalanceServiceTest { validatorId = "validator-1", ) every { - stakeRepository.getDelegation("validator-1", "delegation-1") + stakeRepository.getDelegation("validator-1", "delegation-1", DelegationState.Active) } returns flowOf( mockDelegation( assetId = asset.id, @@ -110,7 +111,7 @@ class TransactionBalanceServiceTest { validatorId = "validator-1", ) every { - stakeRepository.getDelegation("validator-1", "delegation-1") + stakeRepository.getDelegation("validator-1", "delegation-1", DelegationState.Active) } returns flowOf( mockDelegation( assetId = asset.id, diff --git a/android/data/services/store/src/main/kotlin/com/gemwallet/android/data/service/store/database/StakeDao.kt b/android/data/services/store/src/main/kotlin/com/gemwallet/android/data/service/store/database/StakeDao.kt index aa8f590094..ec7f7dbb9a 100644 --- a/android/data/services/store/src/main/kotlin/com/gemwallet/android/data/service/store/database/StakeDao.kt +++ b/android/data/services/store/src/main/kotlin/com/gemwallet/android/data/service/store/database/StakeDao.kt @@ -9,6 +9,7 @@ import com.gemwallet.android.data.service.store.database.entities.DbDelegationBa import com.gemwallet.android.data.service.store.database.entities.DbDelegationValidator import com.gemwallet.android.data.service.store.database.entities.RoomDelegation import com.wallet.core.primitives.Chain +import com.wallet.core.primitives.DelegationState import kotlinx.coroutines.flow.Flow @Dao @@ -92,10 +93,10 @@ abstract class StakeDao { " " + "FROM stake_delegation_base as base " + "INNER JOIN stake_delegation_validator as validator ON base.validator_id=validator.id " + - "WHERE base.delegation_id=:delegationId AND validator.id=:validatorId" + "WHERE base.delegation_id=:delegationId AND validator.id=:validatorId AND base.state=:state" ) - abstract fun getDelegation(validatorId: String, delegationId: String): Flow + abstract fun getDelegation(validatorId: String, delegationId: String, state: DelegationState): Flow @Transaction open suspend fun update( diff --git a/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt b/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt index cf9c706c1c..8ba408cf3e 100644 --- a/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt +++ b/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt @@ -35,6 +35,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import java.math.BigInteger import javax.inject.Inject @@ -51,11 +52,13 @@ class DelegationViewModel @Inject constructor( val validatorId = savedStateHandle.getStateFlow("validatorId", null).filterNotNull() val delegationId = savedStateHandle.getStateFlow("delegationId", null).filterNotNull() + val state = savedStateHandle.getStateFlow("state", null).filterNotNull() + .map { DelegationState.valueOf(it) } - val delegation = combine(validatorId, delegationId) { validatorId, delegationId -> Pair(validatorId, delegationId) } + val delegation = combine(validatorId, delegationId, state) { validatorId, delegationId, state -> Triple(validatorId, delegationId, state) } .flatMapLatest { - val (validatorId, delegationId) = it - stakeRepository.getDelegation(delegationId = delegationId, validatorId = validatorId) + val (validatorId, delegationId, state) = it + stakeRepository.getDelegation(delegationId = delegationId, validatorId = validatorId, state = state) } .stateIn(viewModelScope, SharingStarted.Eagerly, null) @@ -221,7 +224,8 @@ class DelegationViewModel @Inject constructor( assetId = assetInfo.value?.asset?.id!!, txType = type, validatorId = delegation.value?.validator?.id, - delegationId = delegation.value?.base?.delegationId!! + delegationId = delegation.value?.base?.delegationId!!, + delegationState = delegation.value?.base?.state, ) } } \ No newline at end of file diff --git a/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/StakeScreen.kt b/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/StakeScreen.kt index d15df5bbcf..a1b60ec75b 100644 --- a/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/StakeScreen.kt +++ b/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/StakeScreen.kt @@ -10,12 +10,13 @@ import com.gemwallet.android.ui.components.screen.LoadingScene import com.gemwallet.android.ui.models.actions.AmountTransactionAction import com.gemwallet.android.ui.models.actions.ConfirmTransactionAction import com.gemwallet.android.features.stake.viewmodels.StakeViewModel +import com.wallet.core.primitives.DelegationState @Composable fun StakeScreen( amountAction: AmountTransactionAction, onConfirm: ConfirmTransactionAction, - onDelegation: (String, String) -> Unit, + onDelegation: (String, String, DelegationState) -> Unit, onCancel: () -> Unit, viewModel: StakeViewModel = hiltViewModel() ) { diff --git a/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/components/StakeActions.kt b/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/components/StakeActions.kt index e4368d2d42..08ccaff232 100644 --- a/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/components/StakeActions.kt +++ b/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/components/StakeActions.kt @@ -22,6 +22,9 @@ internal fun LazyListScope.stakeActions( amountAction: AmountTransactionAction, onRewards: () -> Unit ) { + if (actions.isEmpty()) { + return + } item { SubheaderItem(R.string.common_manage) } diff --git a/android/features/earn/stake/viewmodels/src/main/kotlin/com/gemwallet/android/features/stake/viewmodels/StakeViewModel.kt b/android/features/earn/stake/viewmodels/src/main/kotlin/com/gemwallet/android/features/stake/viewmodels/StakeViewModel.kt index 8aad12d55b..d6810c0669 100644 --- a/android/features/earn/stake/viewmodels/src/main/kotlin/com/gemwallet/android/features/stake/viewmodels/StakeViewModel.kt +++ b/android/features/earn/stake/viewmodels/src/main/kotlin/com/gemwallet/android/features/stake/viewmodels/StakeViewModel.kt @@ -30,6 +30,7 @@ import com.wallet.core.primitives.Delegation import com.wallet.core.primitives.DelegationState import com.wallet.core.primitives.TransactionType import com.wallet.core.primitives.WalletType +import com.gemwallet.android.ext.isViewOnly import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -155,11 +156,11 @@ class StakeViewModel @Inject constructor( fun onDelegation( delegation: Delegation, - onOpenDetail: (String, String) -> Unit, + onOpenDetail: (String, String, DelegationState) -> Unit, onConfirm: ConfirmTransactionAction, ) { - if (delegation.base.state != DelegationState.AwaitingWithdrawal) { - onOpenDetail(delegation.validator.id, delegation.base.delegationId) + if (walletType.value?.isViewOnly == true || delegation.base.state != DelegationState.AwaitingWithdrawal) { + onOpenDetail(delegation.validator.id, delegation.base.delegationId, delegation.base.state) return } val assetInfo = assetInfo.value ?: return diff --git a/android/features/transfer_amount/viewmodels/src/main/kotlin/com/gemwallet/android/features/transfer_amount/viewmodels/AmountViewModel.kt b/android/features/transfer_amount/viewmodels/src/main/kotlin/com/gemwallet/android/features/transfer_amount/viewmodels/AmountViewModel.kt index 442c9d9930..e7a00b1c2b 100644 --- a/android/features/transfer_amount/viewmodels/src/main/kotlin/com/gemwallet/android/features/transfer_amount/viewmodels/AmountViewModel.kt +++ b/android/features/transfer_amount/viewmodels/src/main/kotlin/com/gemwallet/android/features/transfer_amount/viewmodels/AmountViewModel.kt @@ -114,7 +114,9 @@ class AmountViewModel @Inject constructor( TransactionType.StakeRedelegate, TransactionType.StakeWithdraw -> { val validatorId = params.validatorId ?: return@flatMapLatest flowOf(null) - stakeRepository.getDelegation(validatorId, params.delegationId ?: "") + val delegationId = params.delegationId ?: return@flatMapLatest flowOf(null) + val state = params.delegationState ?: return@flatMapLatest flowOf(null) + stakeRepository.getDelegation(validatorId, delegationId, state) } TransactionType.StakeRewards -> { val owner = assetInfo?.owner?.address ?: return@flatMapLatest flowOf(null) diff --git a/android/gemcore/src/main/kotlin/com/gemwallet/android/ext/Wallet.kt b/android/gemcore/src/main/kotlin/com/gemwallet/android/ext/Wallet.kt index b55606a1bf..017c6db709 100644 --- a/android/gemcore/src/main/kotlin/com/gemwallet/android/ext/Wallet.kt +++ b/android/gemcore/src/main/kotlin/com/gemwallet/android/ext/Wallet.kt @@ -4,9 +4,13 @@ import com.wallet.core.primitives.Account import com.wallet.core.primitives.AssetId import com.wallet.core.primitives.Chain import com.wallet.core.primitives.Wallet +import com.wallet.core.primitives.WalletType fun Wallet.getAccount(chain: Chain): Account? { return accounts.firstOrNull { it.chain == chain } } -fun Wallet.getAccount(assetId: AssetId): Account? = getAccount(assetId.chain) \ No newline at end of file +fun Wallet.getAccount(assetId: AssetId): Account? = getAccount(assetId.chain) + +val WalletType.isViewOnly: Boolean get() = this == WalletType.View +val WalletType.canSign: Boolean get() = !isViewOnly \ No newline at end of file diff --git a/android/gemcore/src/main/kotlin/com/gemwallet/android/model/AmountParams.kt b/android/gemcore/src/main/kotlin/com/gemwallet/android/model/AmountParams.kt index b6cf062da5..4b5611ab4a 100644 --- a/android/gemcore/src/main/kotlin/com/gemwallet/android/model/AmountParams.kt +++ b/android/gemcore/src/main/kotlin/com/gemwallet/android/model/AmountParams.kt @@ -4,6 +4,7 @@ import com.gemwallet.android.ext.urlDecode import com.gemwallet.android.ext.urlEncode import com.gemwallet.android.serializer.jsonEncoder import com.wallet.core.primitives.AssetId +import com.wallet.core.primitives.DelegationState import com.wallet.core.primitives.PerpetualDirection import com.wallet.core.primitives.TransactionType import kotlinx.serialization.Serializable @@ -17,6 +18,7 @@ data class AmountParams( val memo: String? = null, val validatorId: String? = null, // TODO: Separate to special subtype val delegationId: String? = null, // TODO: Separate to special subtype + val delegationState: DelegationState? = null, // TODO: Separate to special subtype val perpetualId: String? = null, // TODO: Separate to special subtype val perpetualDirection: PerpetualDirection? = null, // TODO: Separate to special subtype ) { @@ -48,11 +50,13 @@ data class AmountParams( txType: TransactionType, validatorId: String? = null, delegationId: String? = null, + delegationState: DelegationState? = null, ): AmountParams = AmountParams( assetId = assetId, txType = txType, delegationId = delegationId, validatorId = validatorId, + delegationState = delegationState, ) fun buildPerpetualOpenPosition( From affac7c400dfb381f84a680a0063580d6f91c6df Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 24 Apr 2026 10:42:51 +0500 Subject: [PATCH 2/4] Drop !! in DelegationViewModel.buildStake Make buildStake return nullable and null-guard callers via ?.let { call(it) } to avoid force-unwrap on delegation / assetInfo state flows. --- .../viewmodels/DelegationViewModel.kt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt b/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt index 8ba408cf3e..39f4495560 100644 --- a/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt +++ b/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt @@ -174,14 +174,14 @@ class DelegationViewModel @Inject constructor( .stateIn(viewModelScope, SharingStarted.Eagerly, null) fun onStake(call: AmountTransactionAction) { - call(buildStake(TransactionType.StakeDelegate)) + buildStake(TransactionType.StakeDelegate)?.let { call(it) } } fun onUnstake(amountCall: AmountTransactionAction, confirmCall: ConfirmTransactionAction) { val assetInfo = assetInfo.value ?: return val delegation = delegation.value ?: return if (assetInfo.chain.changeAmountOnUnstake) { - amountCall(buildStake(TransactionType.StakeUndelegate)) + buildStake(TransactionType.StakeUndelegate)?.let { amountCall(it) } return } val from = assetInfo.owner ?: return @@ -192,7 +192,7 @@ class DelegationViewModel @Inject constructor( } fun onRedelegate(call: AmountTransactionAction) { - call(buildStake(TransactionType.StakeRedelegate)) + buildStake(TransactionType.StakeRedelegate)?.let { call(it) } } fun onWithdraw(call: ConfirmTransactionAction) { @@ -219,13 +219,15 @@ class DelegationViewModel @Inject constructor( ) } - private fun buildStake(type: TransactionType): AmountParams { + private fun buildStake(type: TransactionType): AmountParams? { + val assetId = assetInfo.value?.asset?.id ?: return null + val delegation = delegation.value ?: return null return AmountParams.buildStake( - assetId = assetInfo.value?.asset?.id!!, + assetId = assetId, txType = type, - validatorId = delegation.value?.validator?.id, - delegationId = delegation.value?.base?.delegationId!!, - delegationState = delegation.value?.base?.state, + validatorId = delegation.validator.id, + delegationId = delegation.base.delegationId, + delegationState = delegation.base.state, ) } } \ No newline at end of file From 8d36d9c0da5c081b9d019a001622c04eca2a90e7 Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 24 Apr 2026 23:08:52 +0500 Subject: [PATCH 3/4] Remove delegation state parameter from APIs Remove the DelegationState parameter from delegation-related APIs and data access. Updated StakeDao to stop filtering by state, changed StakeRepository.getDelegation to accept only validatorId and delegationId, and removed DelegationState from routes, view models, screens, amount params, and call sites. Unused imports were cleaned up and tests adjusted to the new getDelegation signature. This simplifies delegation lookups by returning delegations regardless of state. --- .../gemwallet/android/ui/navigation/routes/Stake.kt | 9 ++++----- .../android/data/repositories/stake/StakeRepository.kt | 5 ++--- .../transactions/TransactionBalanceService.kt | 1 - .../transactions/TransactionBalanceServiceTest.kt | 5 ++--- .../android/data/service/store/database/StakeDao.kt | 5 ++--- .../earn/delegation/viewmodels/DelegationViewModel.kt | 10 +++------- .../android/features/stake/presents/StakeScreen.kt | 3 +-- .../features/stake/viewmodels/StakeViewModel.kt | 4 ++-- .../transfer_amount/viewmodels/AmountViewModel.kt | 4 +--- .../kotlin/com/gemwallet/android/model/AmountParams.kt | 4 ---- core | 2 +- 11 files changed, 18 insertions(+), 34 deletions(-) diff --git a/android/app/src/main/kotlin/com/gemwallet/android/ui/navigation/routes/Stake.kt b/android/app/src/main/kotlin/com/gemwallet/android/ui/navigation/routes/Stake.kt index 7ac5589a2c..acc022013b 100644 --- a/android/app/src/main/kotlin/com/gemwallet/android/ui/navigation/routes/Stake.kt +++ b/android/app/src/main/kotlin/com/gemwallet/android/ui/navigation/routes/Stake.kt @@ -11,27 +11,26 @@ import com.gemwallet.android.ui.models.actions.AmountTransactionAction import com.gemwallet.android.features.earn.delegation.presents.DelegationScene import com.gemwallet.android.features.stake.presents.StakeScreen import com.wallet.core.primitives.AssetId -import com.wallet.core.primitives.DelegationState import kotlinx.serialization.Serializable @Serializable data class StakeRoute(val assetId: String) @Serializable -data class DelegationRoute(val validatorId: String, val delegationId: String, val state: String) +data class DelegationRoute(val validatorId: String, val delegationId: String) fun NavController.navigateToStake(assetId: AssetId, navOptions: NavOptions? = null) { navigate(StakeRoute(assetId.toIdentifier()), navOptions ?: navOptions { launchSingleTop = true }) } -fun NavController.navigateToDelegation(validatorId: String, delegationId: String, state: DelegationState) { - navigate(DelegationRoute(validatorId, delegationId, state.name), navOptions = navOptions { launchSingleTop = true }) +fun NavController.navigateToDelegation(validatorId: String, delegationId: String) { + navigate(DelegationRoute(validatorId, delegationId), navOptions = navOptions { launchSingleTop = true }) } fun NavGraphBuilder.stake( onAmount: AmountTransactionAction, onConfirm: (ConfirmParams) -> Unit, - onDelegation: (String, String, DelegationState) -> Unit, + onDelegation: (String, String) -> Unit, onCancel: () -> Unit, ) { composable { entry -> diff --git a/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/stake/StakeRepository.kt b/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/stake/StakeRepository.kt index 1e8e3dffd9..8548582206 100644 --- a/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/stake/StakeRepository.kt +++ b/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/stake/StakeRepository.kt @@ -10,7 +10,6 @@ import com.wallet.core.primitives.AssetId import com.wallet.core.primitives.Chain import com.wallet.core.primitives.Delegation import com.wallet.core.primitives.DelegationBase -import com.wallet.core.primitives.DelegationState import com.wallet.core.primitives.DelegationValidator import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow @@ -88,8 +87,8 @@ class StakeRepository( .map { items -> items.mapNotNull { it.toModel() } } } - fun getDelegation(validatorId: String, delegationId: String, state: DelegationState): Flow { - return stakeDao.getDelegation(validatorId = validatorId, delegationId = delegationId, state = state) + fun getDelegation(validatorId: String, delegationId: String = ""): Flow { + return stakeDao.getDelegation(validatorId = validatorId, delegationId = delegationId) .map { it?.toModel() } } diff --git a/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceService.kt b/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceService.kt index 1f23dd4017..de1f850799 100644 --- a/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceService.kt +++ b/android/data/repositories/src/main/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceService.kt @@ -46,7 +46,6 @@ class TransactionBalanceService @Inject constructor( val currentDelegation = stakeRepository.getDelegation( validatorId = delegation.base.validatorId, delegationId = delegation.base.delegationId, - state = delegation.base.state, ).firstOrNull() ?: delegation return TransactionBalanceContext( delegationBalance = currentDelegation.base.balance.toBigIntegerOrNull() ?: BigInteger.ZERO, diff --git a/android/data/repositories/src/test/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceServiceTest.kt b/android/data/repositories/src/test/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceServiceTest.kt index ceb242b6eb..d1ec9c4b9f 100644 --- a/android/data/repositories/src/test/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceServiceTest.kt +++ b/android/data/repositories/src/test/kotlin/com/gemwallet/android/data/repositories/transactions/TransactionBalanceServiceTest.kt @@ -10,7 +10,6 @@ import com.gemwallet.android.testkit.mockAssetInfo import com.gemwallet.android.testkit.mockDelegation import com.gemwallet.android.testkit.mockDelegationValidator import com.gemwallet.android.testkit.mockAssetMonad -import com.wallet.core.primitives.DelegationState import com.wallet.core.primitives.TransactionType import io.mockk.coEvery import io.mockk.every @@ -76,7 +75,7 @@ class TransactionBalanceServiceTest { validatorId = "validator-1", ) every { - stakeRepository.getDelegation("validator-1", "delegation-1", DelegationState.Active) + stakeRepository.getDelegation("validator-1", "delegation-1") } returns flowOf( mockDelegation( assetId = asset.id, @@ -111,7 +110,7 @@ class TransactionBalanceServiceTest { validatorId = "validator-1", ) every { - stakeRepository.getDelegation("validator-1", "delegation-1", DelegationState.Active) + stakeRepository.getDelegation("validator-1", "delegation-1") } returns flowOf( mockDelegation( assetId = asset.id, diff --git a/android/data/services/store/src/main/kotlin/com/gemwallet/android/data/service/store/database/StakeDao.kt b/android/data/services/store/src/main/kotlin/com/gemwallet/android/data/service/store/database/StakeDao.kt index ec7f7dbb9a..aa8f590094 100644 --- a/android/data/services/store/src/main/kotlin/com/gemwallet/android/data/service/store/database/StakeDao.kt +++ b/android/data/services/store/src/main/kotlin/com/gemwallet/android/data/service/store/database/StakeDao.kt @@ -9,7 +9,6 @@ import com.gemwallet.android.data.service.store.database.entities.DbDelegationBa import com.gemwallet.android.data.service.store.database.entities.DbDelegationValidator import com.gemwallet.android.data.service.store.database.entities.RoomDelegation import com.wallet.core.primitives.Chain -import com.wallet.core.primitives.DelegationState import kotlinx.coroutines.flow.Flow @Dao @@ -93,10 +92,10 @@ abstract class StakeDao { " " + "FROM stake_delegation_base as base " + "INNER JOIN stake_delegation_validator as validator ON base.validator_id=validator.id " + - "WHERE base.delegation_id=:delegationId AND validator.id=:validatorId AND base.state=:state" + "WHERE base.delegation_id=:delegationId AND validator.id=:validatorId" ) - abstract fun getDelegation(validatorId: String, delegationId: String, state: DelegationState): Flow + abstract fun getDelegation(validatorId: String, delegationId: String): Flow @Transaction open suspend fun update( diff --git a/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt b/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt index 39f4495560..e2f8b9af2c 100644 --- a/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt +++ b/android/features/earn/delegation/viewmodels/src/main/kotlin/com/gemwallet/android/features/earn/delegation/viewmodels/DelegationViewModel.kt @@ -35,7 +35,6 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import java.math.BigInteger import javax.inject.Inject @@ -52,13 +51,11 @@ class DelegationViewModel @Inject constructor( val validatorId = savedStateHandle.getStateFlow("validatorId", null).filterNotNull() val delegationId = savedStateHandle.getStateFlow("delegationId", null).filterNotNull() - val state = savedStateHandle.getStateFlow("state", null).filterNotNull() - .map { DelegationState.valueOf(it) } - val delegation = combine(validatorId, delegationId, state) { validatorId, delegationId, state -> Triple(validatorId, delegationId, state) } + val delegation = combine(validatorId, delegationId) { validatorId, delegationId -> Pair(validatorId, delegationId) } .flatMapLatest { - val (validatorId, delegationId, state) = it - stakeRepository.getDelegation(delegationId = delegationId, validatorId = validatorId, state = state) + val (validatorId, delegationId) = it + stakeRepository.getDelegation(delegationId = delegationId, validatorId = validatorId) } .stateIn(viewModelScope, SharingStarted.Eagerly, null) @@ -227,7 +224,6 @@ class DelegationViewModel @Inject constructor( txType = type, validatorId = delegation.validator.id, delegationId = delegation.base.delegationId, - delegationState = delegation.base.state, ) } } \ No newline at end of file diff --git a/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/StakeScreen.kt b/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/StakeScreen.kt index a1b60ec75b..d15df5bbcf 100644 --- a/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/StakeScreen.kt +++ b/android/features/earn/stake/presents/src/main/kotlin/com/gemwallet/android/features/stake/presents/StakeScreen.kt @@ -10,13 +10,12 @@ import com.gemwallet.android.ui.components.screen.LoadingScene import com.gemwallet.android.ui.models.actions.AmountTransactionAction import com.gemwallet.android.ui.models.actions.ConfirmTransactionAction import com.gemwallet.android.features.stake.viewmodels.StakeViewModel -import com.wallet.core.primitives.DelegationState @Composable fun StakeScreen( amountAction: AmountTransactionAction, onConfirm: ConfirmTransactionAction, - onDelegation: (String, String, DelegationState) -> Unit, + onDelegation: (String, String) -> Unit, onCancel: () -> Unit, viewModel: StakeViewModel = hiltViewModel() ) { diff --git a/android/features/earn/stake/viewmodels/src/main/kotlin/com/gemwallet/android/features/stake/viewmodels/StakeViewModel.kt b/android/features/earn/stake/viewmodels/src/main/kotlin/com/gemwallet/android/features/stake/viewmodels/StakeViewModel.kt index d6810c0669..e7e638b8bd 100644 --- a/android/features/earn/stake/viewmodels/src/main/kotlin/com/gemwallet/android/features/stake/viewmodels/StakeViewModel.kt +++ b/android/features/earn/stake/viewmodels/src/main/kotlin/com/gemwallet/android/features/stake/viewmodels/StakeViewModel.kt @@ -156,11 +156,11 @@ class StakeViewModel @Inject constructor( fun onDelegation( delegation: Delegation, - onOpenDetail: (String, String, DelegationState) -> Unit, + onOpenDetail: (String, String) -> Unit, onConfirm: ConfirmTransactionAction, ) { if (walletType.value?.isViewOnly == true || delegation.base.state != DelegationState.AwaitingWithdrawal) { - onOpenDetail(delegation.validator.id, delegation.base.delegationId, delegation.base.state) + onOpenDetail(delegation.validator.id, delegation.base.delegationId) return } val assetInfo = assetInfo.value ?: return diff --git a/android/features/transfer_amount/viewmodels/src/main/kotlin/com/gemwallet/android/features/transfer_amount/viewmodels/AmountViewModel.kt b/android/features/transfer_amount/viewmodels/src/main/kotlin/com/gemwallet/android/features/transfer_amount/viewmodels/AmountViewModel.kt index e7a00b1c2b..442c9d9930 100644 --- a/android/features/transfer_amount/viewmodels/src/main/kotlin/com/gemwallet/android/features/transfer_amount/viewmodels/AmountViewModel.kt +++ b/android/features/transfer_amount/viewmodels/src/main/kotlin/com/gemwallet/android/features/transfer_amount/viewmodels/AmountViewModel.kt @@ -114,9 +114,7 @@ class AmountViewModel @Inject constructor( TransactionType.StakeRedelegate, TransactionType.StakeWithdraw -> { val validatorId = params.validatorId ?: return@flatMapLatest flowOf(null) - val delegationId = params.delegationId ?: return@flatMapLatest flowOf(null) - val state = params.delegationState ?: return@flatMapLatest flowOf(null) - stakeRepository.getDelegation(validatorId, delegationId, state) + stakeRepository.getDelegation(validatorId, params.delegationId ?: "") } TransactionType.StakeRewards -> { val owner = assetInfo?.owner?.address ?: return@flatMapLatest flowOf(null) diff --git a/android/gemcore/src/main/kotlin/com/gemwallet/android/model/AmountParams.kt b/android/gemcore/src/main/kotlin/com/gemwallet/android/model/AmountParams.kt index 4b5611ab4a..b6cf062da5 100644 --- a/android/gemcore/src/main/kotlin/com/gemwallet/android/model/AmountParams.kt +++ b/android/gemcore/src/main/kotlin/com/gemwallet/android/model/AmountParams.kt @@ -4,7 +4,6 @@ import com.gemwallet.android.ext.urlDecode import com.gemwallet.android.ext.urlEncode import com.gemwallet.android.serializer.jsonEncoder import com.wallet.core.primitives.AssetId -import com.wallet.core.primitives.DelegationState import com.wallet.core.primitives.PerpetualDirection import com.wallet.core.primitives.TransactionType import kotlinx.serialization.Serializable @@ -18,7 +17,6 @@ data class AmountParams( val memo: String? = null, val validatorId: String? = null, // TODO: Separate to special subtype val delegationId: String? = null, // TODO: Separate to special subtype - val delegationState: DelegationState? = null, // TODO: Separate to special subtype val perpetualId: String? = null, // TODO: Separate to special subtype val perpetualDirection: PerpetualDirection? = null, // TODO: Separate to special subtype ) { @@ -50,13 +48,11 @@ data class AmountParams( txType: TransactionType, validatorId: String? = null, delegationId: String? = null, - delegationState: DelegationState? = null, ): AmountParams = AmountParams( assetId = assetId, txType = txType, delegationId = delegationId, validatorId = validatorId, - delegationState = delegationState, ) fun buildPerpetualOpenPosition( diff --git a/core b/core index 2fe0b43b8b..180efdb33e 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 2fe0b43b8b41a8f63e3332d740dd52a13a028d78 +Subproject commit 180efdb33ea58f5437131005a65035bf110ff867 From 7e481a3de5667ff81e68f78b3da18d8fa1332c5f Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 24 Apr 2026 23:37:21 +0500 Subject: [PATCH 4/4] Use signStake and return byte array list Replace the call to signWithdrawal with signStake and map the resulting signatures to ByteArray. Previously the code wrapped a single toByteArray() in a list; this change returns a list of ByteArray from signStake to match the signer API and support multiple signatures. --- .../com/gemwallet/android/blockchain/services/SignService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/blockchain/src/main/kotlin/com/gemwallet/android/blockchain/services/SignService.kt b/android/blockchain/src/main/kotlin/com/gemwallet/android/blockchain/services/SignService.kt index 931faad2b8..f78debb29d 100644 --- a/android/blockchain/src/main/kotlin/com/gemwallet/android/blockchain/services/SignService.kt +++ b/android/blockchain/src/main/kotlin/com/gemwallet/android/blockchain/services/SignService.kt @@ -305,7 +305,7 @@ class SignService : SignClient { finalAmount = finalAmount, fee = fee, ) - return listOf(getSigner(params).signWithdrawal(data, privateKey).toByteArray()) + return getSigner(params).signStake(data, privateKey).map { it.toByteArray() } } override fun supported(chain: Chain): Boolean { return when (chain.toChainType()) {