Updated on 2026-08-14
This commit is contained in:
commit
99acc9718b
5 changed files with 96 additions and 13 deletions
|
|
@ -82,7 +82,7 @@ internal class DefaultAddressSyncComponent(
|
|||
model.onIntent(AddressSyncIntent.Sync)
|
||||
},
|
||||
)
|
||||
AddressSyncState.NoTokens -> LaunchedEffect(Unit) {
|
||||
AddressSyncState.Exit -> LaunchedEffect(Unit) {
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.onboarding.v2.addresssync.model
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.onboarding.v2.addresssync.navigation.AddressSyncStep
|
||||
|
||||
internal sealed interface AddressSyncIntent {
|
||||
|
|
@ -9,6 +10,11 @@ internal sealed interface AddressSyncIntent {
|
|||
|
||||
internal sealed class AddressSyncState {
|
||||
data object Loading : AddressSyncState()
|
||||
data class Success(val currenciesCount: Int) : AddressSyncState()
|
||||
data object NoTokens : AddressSyncState()
|
||||
data class Success(
|
||||
val currencies: List<CryptoCurrency>,
|
||||
val isButtonLoading: Boolean = false,
|
||||
) : AddressSyncState() {
|
||||
val currenciesCount: Int = currencies.size
|
||||
}
|
||||
data object Exit : AddressSyncState()
|
||||
}
|
||||
|
|
@ -12,11 +12,13 @@ import com.tangem.domain.settings.CanUseBiometryUseCase
|
|||
import com.tangem.domain.settings.ShouldAskPermissionUseCase
|
||||
import com.tangem.domain.settings.ShouldShowAskBiometryUseCase
|
||||
import com.tangem.domain.tokens.MultiWalletAccountListFetcher
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.features.onboarding.v2.addresssync.navigation.AddressSyncStep
|
||||
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
|
||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
|
@ -31,6 +33,7 @@ internal class AddressSyncModel @Inject constructor(
|
|||
private val shouldAskPermissionUseCase: ShouldAskPermissionUseCase,
|
||||
private val multiWalletAccountListFetcher: MultiWalletAccountListFetcher,
|
||||
private val multiAccountListSupplier: MultiAccountListSupplier,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -107,7 +110,7 @@ internal class AddressSyncModel @Inject constructor(
|
|||
params = MultiWalletAccountListFetcher.Params(userWalletId = walletId),
|
||||
).fold(
|
||||
ifLeft = {
|
||||
state.value = AddressSyncState.NoTokens
|
||||
state.value = AddressSyncState.Exit
|
||||
},
|
||||
ifRight = {
|
||||
handleAddressSyncStep()
|
||||
|
|
@ -125,9 +128,9 @@ internal class AddressSyncModel @Inject constructor(
|
|||
}
|
||||
.onEach { currencies ->
|
||||
val updatedState = if (currencies.isEmpty()) {
|
||||
AddressSyncState.NoTokens
|
||||
AddressSyncState.Exit
|
||||
} else {
|
||||
AddressSyncState.Success(currenciesCount = currencies.size)
|
||||
AddressSyncState.Success(currencies = currencies)
|
||||
}
|
||||
state.value = updatedState
|
||||
}
|
||||
|
|
@ -135,7 +138,23 @@ internal class AddressSyncModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun startSyncing() {
|
||||
TODO("Will be implemented during [REDACTED_TASK_KEY]")
|
||||
modelScope.launch {
|
||||
val successWithLoading = (state.value as AddressSyncState.Success).copy(isButtonLoading = true)
|
||||
state.value = successWithLoading
|
||||
val cryptoCurrencies = successWithLoading.currencies
|
||||
derivePublicKeysUseCase(
|
||||
userWalletId = walletId,
|
||||
currencies = cryptoCurrencies,
|
||||
).fold(
|
||||
ifLeft = { throwable ->
|
||||
state.value = successWithLoading.copy(
|
||||
isButtonLoading = false,
|
||||
)
|
||||
TangemLogger.e("Failed to derive public keys", throwable)
|
||||
},
|
||||
ifRight = { state.value = AddressSyncState.Exit },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ internal fun AddressSyncButtonScreen(
|
|||
top = TangemTheme.dimens.spacing154,
|
||||
bottom = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
showProgress = state.isButtonLoading,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -98,7 +99,9 @@ private fun ColumnScope.AddressSyncDescription(currenciesCount: Int) {
|
|||
private fun AddressSyncButtonScreenPreview() {
|
||||
TangemThemePreview {
|
||||
AddressSyncButtonScreen(
|
||||
state = AddressSyncState.Success(currenciesCount = 2),
|
||||
state = AddressSyncState.Success(
|
||||
currencies = emptyList(),
|
||||
),
|
||||
onSyncClick = {},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.domain.settings.CanUseBiometryUseCase
|
|||
import com.tangem.domain.settings.ShouldAskPermissionUseCase
|
||||
import com.tangem.domain.settings.ShouldShowAskBiometryUseCase
|
||||
import com.tangem.domain.tokens.MultiWalletAccountListFetcher
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.features.onboarding.v2.TitleProvider
|
||||
import com.tangem.features.onboarding.v2.addresssync.navigation.AddressSyncStep
|
||||
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
|
||||
|
|
@ -39,6 +40,7 @@ internal class AddressSyncModelTest {
|
|||
private val shouldAskPermissionUseCase: ShouldAskPermissionUseCase = mockk()
|
||||
private val multiWalletAccountListFetcher: MultiWalletAccountListFetcher = mockk()
|
||||
private val multiAccountListSupplier: MultiAccountListSupplier = mockk()
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase = mockk()
|
||||
private val paramsContainer: ParamsContainer = mockk()
|
||||
private val testInnerNavigation = MutableStateFlow(
|
||||
value = MultiWalletInnerNavigationState(
|
||||
|
|
@ -62,6 +64,7 @@ internal class AddressSyncModelTest {
|
|||
coEvery { shouldShowAskBiometryUseCase() } returns false
|
||||
coEvery { shouldAskPermissionUseCase(PUSH_PERMISSION) } returns false
|
||||
coEvery { multiWalletAccountListFetcher.invoke(any()) } returns Either.Right(Unit)
|
||||
coEvery { derivePublicKeysUseCase(any(), any()) } returns Either.Right(Unit)
|
||||
every { multiAccountListSupplier() } returns flowOf(
|
||||
listOf(AccountList.empty(userWalletId = walletId)),
|
||||
)
|
||||
|
|
@ -154,7 +157,7 @@ internal class AddressSyncModelTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN multiAccountListSupplier emits no currencies WHEN model is created THEN state is NoTokens`() = runTest {
|
||||
fun `GIVEN multiAccountListSupplier emits no currencies WHEN model is created THEN state is Exit`() = runTest {
|
||||
every { multiAccountListSupplier() } returns flowOf(
|
||||
listOf(
|
||||
AccountList.empty(
|
||||
|
|
@ -172,7 +175,7 @@ internal class AddressSyncModelTest {
|
|||
params = MultiWalletAccountListFetcher.Params(userWalletId = walletId)
|
||||
)
|
||||
}
|
||||
Assertions.assertEquals(AddressSyncState.NoTokens, model.state.value)
|
||||
Assertions.assertEquals(AddressSyncState.Exit, model.state.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -196,13 +199,13 @@ internal class AddressSyncModelTest {
|
|||
)
|
||||
}
|
||||
Assertions.assertEquals(
|
||||
AddressSyncState.Success(currenciesCount = currencies.size),
|
||||
AddressSyncState.Success(currencies),
|
||||
model.state.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN multiWalletAccountListFetcher emits error WHEN model is created THEN get NoToken state`() = runTest {
|
||||
fun `WHEN multiWalletAccountListFetcher emits error WHEN model is created THEN get Exit state`() = runTest {
|
||||
val currencies = listOf<CryptoCurrency>(mockk(), mockk(), mockk())
|
||||
coEvery { multiWalletAccountListFetcher.invoke(any()) } returns Either.Left(
|
||||
value = IllegalStateException("Test")
|
||||
|
|
@ -226,7 +229,58 @@ internal class AddressSyncModelTest {
|
|||
)
|
||||
}
|
||||
Assertions.assertEquals(
|
||||
AddressSyncState.NoTokens,
|
||||
AddressSyncState.Exit,
|
||||
model.state.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN success state WHEN Sync THEN state becomes Exit`() = runTest {
|
||||
val currencies = listOf<CryptoCurrency>(mockk(), mockk(), mockk())
|
||||
every { multiAccountListSupplier() } returns flowOf(
|
||||
listOf(
|
||||
AccountList.empty(
|
||||
userWalletId = walletId,
|
||||
cryptoCurrencies = currencies,
|
||||
),
|
||||
),
|
||||
)
|
||||
coEvery { derivePublicKeysUseCase(walletId, currencies) } returns Either.Right(Unit)
|
||||
|
||||
val model = createModel(this)
|
||||
advanceUntilIdle()
|
||||
|
||||
model.onIntent(AddressSyncIntent.Sync)
|
||||
advanceUntilIdle()
|
||||
|
||||
coVerify { derivePublicKeysUseCase(walletId, currencies) }
|
||||
Assertions.assertEquals(AddressSyncState.Exit, model.state.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN success state WHEN Sync AND derive fails THEN button loading is reset`() = runTest {
|
||||
val currencies = listOf<CryptoCurrency>(mockk(), mockk(), mockk())
|
||||
every { multiAccountListSupplier() } returns flowOf(
|
||||
listOf(
|
||||
AccountList.empty(
|
||||
userWalletId = walletId,
|
||||
cryptoCurrencies = currencies,
|
||||
),
|
||||
),
|
||||
)
|
||||
coEvery { derivePublicKeysUseCase(walletId, currencies) } returns Either.Left(
|
||||
value = IllegalStateException("Test"),
|
||||
)
|
||||
|
||||
val model = createModel(this)
|
||||
advanceUntilIdle()
|
||||
|
||||
model.onIntent(AddressSyncIntent.Sync)
|
||||
advanceUntilIdle()
|
||||
|
||||
coVerify { derivePublicKeysUseCase(walletId, currencies) }
|
||||
Assertions.assertEquals(
|
||||
AddressSyncState.Success(currencies = currencies, isButtonLoading = false),
|
||||
model.state.value,
|
||||
)
|
||||
}
|
||||
|
|
@ -254,6 +308,7 @@ internal class AddressSyncModelTest {
|
|||
shouldAskPermissionUseCase = shouldAskPermissionUseCase,
|
||||
multiWalletAccountListFetcher = multiWalletAccountListFetcher,
|
||||
multiAccountListSupplier = multiAccountListSupplier,
|
||||
derivePublicKeysUseCase = derivePublicKeysUseCase,
|
||||
paramsContainer = paramsContainer,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue