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.
This commit is contained in:
2026-03-09 02:46:49 +03:00
parent 44fd64496b
commit 8d150266fb
2 changed files with 10 additions and 8 deletions
@@ -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.domain.sessions.WalletConnectSessionsUseCase
import io.novafoundation.nova.feature_wallet_connect_api.presentation.mapNumberOfActiveSessionsToUi 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.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.feature_account_api.data.ethereum.transaction.TransactionOrigin
import io.novafoundation.nova.runtime.ext.ChainGeneses import io.novafoundation.nova.runtime.ext.ChainGeneses
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
@@ -454,14 +455,14 @@ class BalanceListViewModel(
launchUnit { launchUnit {
try { try {
val chain = chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE) val chain = chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE)
val result = extrinsicService.submitExtrinsic(chain, TransactionOrigin.SelectedWallet) { val result = extrinsicService.submitExtrinsicAndAwaitExecution(chain, TransactionOrigin.SelectedWallet) {
call( call(
moduleName = "StakingScore", moduleName = "StakingScore",
callName = "start_score_tracking", callName = "start_score_tracking",
arguments = emptyMap() arguments = emptyMap()
) )
} }
result.getOrThrow() result.requireOk()
_showTrackingSuccessEvent.postValue(Event(Unit)) _showTrackingSuccessEvent.postValue(Event(Unit))
refreshDashboard() refreshDashboard()
} catch (e: Exception) { } catch (e: Exception) {
@@ -8,6 +8,7 @@ import io.novafoundation.nova.common.resources.ResourceManager
import io.novafoundation.nova.common.utils.Event 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.ethereum.transaction.TransactionOrigin
import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService 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.interfaces.SelectedAccountUseCase
import io.novafoundation.nova.feature_account_api.domain.model.addressIn import io.novafoundation.nova.feature_account_api.domain.model.addressIn
import io.novafoundation.nova.feature_assets.R import io.novafoundation.nova.feature_assets.R
@@ -147,7 +148,7 @@ class CitizenshipViewModel(
"referrer" to referrerAccountId "referrer" to referrerAccountId
) )
val result = extrinsicService.submitExtrinsic( val result = extrinsicService.submitExtrinsicAndAwaitExecution(
chain = chain, chain = chain,
origin = TransactionOrigin.SelectedWallet origin = TransactionOrigin.SelectedWallet
) { ) {
@@ -157,7 +158,7 @@ class CitizenshipViewModel(
arguments = arguments arguments = arguments
) )
} }
result.getOrThrow() result.requireOk()
showToast(resourceManager.getString(R.string.citizenship_success)) showToast(resourceManager.getString(R.string.citizenship_success))
_citizenshipStatus.postValue(CitizenshipStatus.PENDING_REFERRAL) _citizenshipStatus.postValue(CitizenshipStatus.PENDING_REFERRAL)
@@ -177,7 +178,7 @@ class CitizenshipViewModel(
try { try {
val chain = peopleChain ?: chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE) val chain = peopleChain ?: chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE)
val result = extrinsicService.submitExtrinsic( val result = extrinsicService.submitExtrinsicAndAwaitExecution(
chain = chain, chain = chain,
origin = TransactionOrigin.SelectedWallet origin = TransactionOrigin.SelectedWallet
) { ) {
@@ -187,7 +188,7 @@ class CitizenshipViewModel(
arguments = emptyMap() arguments = emptyMap()
) )
} }
result.getOrThrow() result.requireOk()
showToast(resourceManager.getString(R.string.citizenship_success)) showToast(resourceManager.getString(R.string.citizenship_success))
_citizenshipStatus.postValue(CitizenshipStatus.APPROVED) _citizenshipStatus.postValue(CitizenshipStatus.APPROVED)
@@ -223,7 +224,7 @@ class CitizenshipViewModel(
try { try {
val chain = peopleChain ?: chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE) val chain = peopleChain ?: chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE)
val result = extrinsicService.submitExtrinsic( val result = extrinsicService.submitExtrinsicAndAwaitExecution(
chain = chain, chain = chain,
origin = TransactionOrigin.SelectedWallet origin = TransactionOrigin.SelectedWallet
) { ) {
@@ -233,7 +234,7 @@ class CitizenshipViewModel(
arguments = mapOf("applicant" to applicantAccountId) arguments = mapOf("applicant" to applicantAccountId)
) )
} }
result.getOrThrow() result.requireOk()
showToast(resourceManager.getString(R.string.citizenship_approve_success)) showToast(resourceManager.getString(R.string.citizenship_approve_success))
// Reload the list // Reload the list