From 8d150266fb02408bf11f37d442415d1c7a265217 Mon Sep 17 00:00:00 2001 From: Kurdistan Tech Ministry Date: Mon, 9 Mar 2026 02:46:49 +0300 Subject: [PATCH] fix: detect on-chain dispatch errors for citizenship and staking extrinsics Switch from submitExtrinsic (fire-and-forget) to submitExtrinsicAndAwaitExecution which waits for block inclusion and checks ExtrinsicFailed events. Previously the app showed success even when pallet-level errors occurred (e.g. ReferrerNotCitizen, AlreadyExists). Now dispatch errors are properly surfaced to the user. --- .../balance/list/BalanceListViewModel.kt | 5 +++-- .../citizenship/CitizenshipViewModel.kt | 13 +++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/balance/list/BalanceListViewModel.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/balance/list/BalanceListViewModel.kt index 571568e..03d4305 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/balance/list/BalanceListViewModel.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/balance/list/BalanceListViewModel.kt @@ -66,6 +66,7 @@ import io.novafoundation.nova.feature_wallet_api.presentation.model.FractionPart import io.novafoundation.nova.feature_wallet_connect_api.domain.sessions.WalletConnectSessionsUseCase import io.novafoundation.nova.feature_wallet_connect_api.presentation.mapNumberOfActiveSessionsToUi import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService +import io.novafoundation.nova.feature_account_api.data.extrinsic.execution.requireOk import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.TransactionOrigin import io.novafoundation.nova.runtime.ext.ChainGeneses import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry @@ -454,14 +455,14 @@ class BalanceListViewModel( launchUnit { try { val chain = chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE) - val result = extrinsicService.submitExtrinsic(chain, TransactionOrigin.SelectedWallet) { + val result = extrinsicService.submitExtrinsicAndAwaitExecution(chain, TransactionOrigin.SelectedWallet) { call( moduleName = "StakingScore", callName = "start_score_tracking", arguments = emptyMap() ) } - result.getOrThrow() + result.requireOk() _showTrackingSuccessEvent.postValue(Event(Unit)) refreshDashboard() } catch (e: Exception) { diff --git a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/citizenship/CitizenshipViewModel.kt b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/citizenship/CitizenshipViewModel.kt index a5724be..dba588d 100644 --- a/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/citizenship/CitizenshipViewModel.kt +++ b/feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/citizenship/CitizenshipViewModel.kt @@ -8,6 +8,7 @@ import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.Event import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.TransactionOrigin import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService +import io.novafoundation.nova.feature_account_api.data.extrinsic.execution.requireOk import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase import io.novafoundation.nova.feature_account_api.domain.model.addressIn import io.novafoundation.nova.feature_assets.R @@ -147,7 +148,7 @@ class CitizenshipViewModel( "referrer" to referrerAccountId ) - val result = extrinsicService.submitExtrinsic( + val result = extrinsicService.submitExtrinsicAndAwaitExecution( chain = chain, origin = TransactionOrigin.SelectedWallet ) { @@ -157,7 +158,7 @@ class CitizenshipViewModel( arguments = arguments ) } - result.getOrThrow() + result.requireOk() showToast(resourceManager.getString(R.string.citizenship_success)) _citizenshipStatus.postValue(CitizenshipStatus.PENDING_REFERRAL) @@ -177,7 +178,7 @@ class CitizenshipViewModel( try { val chain = peopleChain ?: chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE) - val result = extrinsicService.submitExtrinsic( + val result = extrinsicService.submitExtrinsicAndAwaitExecution( chain = chain, origin = TransactionOrigin.SelectedWallet ) { @@ -187,7 +188,7 @@ class CitizenshipViewModel( arguments = emptyMap() ) } - result.getOrThrow() + result.requireOk() showToast(resourceManager.getString(R.string.citizenship_success)) _citizenshipStatus.postValue(CitizenshipStatus.APPROVED) @@ -223,7 +224,7 @@ class CitizenshipViewModel( try { val chain = peopleChain ?: chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE) - val result = extrinsicService.submitExtrinsic( + val result = extrinsicService.submitExtrinsicAndAwaitExecution( chain = chain, origin = TransactionOrigin.SelectedWallet ) { @@ -233,7 +234,7 @@ class CitizenshipViewModel( arguments = mapOf("applicant" to applicantAccountId) ) } - result.getOrThrow() + result.requireOk() showToast(resourceManager.getString(R.string.citizenship_approve_success)) // Reload the list