Updated on 2026-08-14
This commit is contained in:
parent
df32ea7ab6
commit
4ef7082504
24 changed files with 214 additions and 185 deletions
|
|
@ -515,4 +515,10 @@ internal object WalletsDomainModule {
|
||||||
): HasSecuredWalletsUseCase {
|
): HasSecuredWalletsUseCase {
|
||||||
return HasSecuredWalletsUseCase(userWalletsListRepository = userWalletsListRepository)
|
return HasSecuredWalletsUseCase(userWalletsListRepository = userWalletsListRepository)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideSyncWalletWithRemoteUseCase(walletsRepository: WalletsRepository): SyncWalletWithRemoteUseCase {
|
||||||
|
return SyncWalletWithRemoteUseCase(walletsRepository = walletsRepository)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -50,9 +50,6 @@ interface TangemTechApi {
|
||||||
@Body userTokens: UserTokensResponse,
|
@Body userTokens: UserTokensResponse,
|
||||||
): ApiResponse<Unit>
|
): ApiResponse<Unit>
|
||||||
|
|
||||||
@POST("v1/user-tokens")
|
|
||||||
suspend fun markUserWallerWasCreated(@Body body: MarkUserWalletWasCreatedBody): ApiResponse<Unit>
|
|
||||||
|
|
||||||
/** Returns referral status by [walletId] */
|
/** Returns referral status by [walletId] */
|
||||||
@GET("v1/referral/{walletId}")
|
@GET("v1/referral/{walletId}")
|
||||||
suspend fun getReferralStatus(@Path("walletId") walletId: String): ApiResponse<ReferralResponse>
|
suspend fun getReferralStatus(@Path("walletId") walletId: String): ApiResponse<ReferralResponse>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,21 @@
|
||||||
package com.tangem.data.wallets.converters
|
package com.tangem.datasource.api.tangemTech.converters
|
||||||
|
|
||||||
import com.tangem.datasource.api.tangemTech.models.CardInfoBody
|
import com.tangem.datasource.api.tangemTech.models.CardInfoBody
|
||||||
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
|
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
|
||||||
|
import com.tangem.datasource.api.tangemTech.models.WalletType
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
|
|
||||||
internal object WalletIdBodyConverter {
|
object WalletIdBodyConverter {
|
||||||
|
|
||||||
fun convert(userWallet: UserWallet, publicKeys: Map<String, String>): WalletIdBody {
|
fun convert(userWallet: UserWallet, publicKeys: Map<String, String>? = null): WalletIdBody {
|
||||||
return WalletIdBody(
|
return WalletIdBody(
|
||||||
walletId = userWallet.walletId.stringValue,
|
walletId = userWallet.walletId.stringValue,
|
||||||
name = userWallet.name,
|
name = userWallet.name,
|
||||||
cards = publicKeys.map {
|
walletType = WalletType.from(userWallet),
|
||||||
|
cards = publicKeys?.map { publicKeyById ->
|
||||||
CardInfoBody(
|
CardInfoBody(
|
||||||
cardId = it.key,
|
cardId = publicKeyById.key,
|
||||||
cardPublicKey = it.value,
|
cardPublicKey = publicKeyById.value,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package com.tangem.datasource.api.tangemTech.models
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
|
||||||
import com.squareup.moshi.JsonClass
|
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
|
||||||
data class MarkUserWalletWasCreatedBody(
|
|
||||||
@Json(name = "user_wallet_id") val userWalletId: String,
|
|
||||||
)
|
|
||||||
|
|
@ -13,8 +13,10 @@ data class UserTokensResponse(
|
||||||
@Json(name = "version") val version: Int = 0,
|
@Json(name = "version") val version: Int = 0,
|
||||||
@Json(name = "group") val group: GroupType,
|
@Json(name = "group") val group: GroupType,
|
||||||
@Json(name = "sort") val sort: SortType,
|
@Json(name = "sort") val sort: SortType,
|
||||||
@Json(name = "notifyStatus") val notifyStatus: Boolean? = null,
|
|
||||||
@Json(name = "tokens") val tokens: List<Token> = emptyList(),
|
@Json(name = "tokens") val tokens: List<Token> = emptyList(),
|
||||||
|
@Json(name = "notifyStatus") val notifyStatus: Boolean? = null,
|
||||||
|
@Json(name = "name") val walletName: String? = null,
|
||||||
|
@Json(name = "type") val walletType: WalletType? = null,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@ import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
@Suppress("BooleanPropertyNaming")
|
|
||||||
data class WalletBody(
|
data class WalletBody(
|
||||||
@Json(name = "notifyStatus") val notifyStatus: Boolean? = null,
|
|
||||||
@Json(name = "name") val name: String? = null,
|
@Json(name = "name") val name: String? = null,
|
||||||
|
@Json(name = "type") val type: WalletType? = null,
|
||||||
)
|
)
|
||||||
|
|
@ -9,14 +9,4 @@ data class WalletIdBody(
|
||||||
@Json(name = "name") val name: String,
|
@Json(name = "name") val name: String,
|
||||||
@Json(name = "type") val walletType: WalletType? = null,
|
@Json(name = "type") val walletType: WalletType? = null,
|
||||||
@Json(name = "cards") val cards: List<CardInfoBody>? = null,
|
@Json(name = "cards") val cards: List<CardInfoBody>? = null,
|
||||||
) {
|
)
|
||||||
|
|
||||||
@JsonClass(generateAdapter = false)
|
|
||||||
enum class WalletType {
|
|
||||||
@Json(name = "card")
|
|
||||||
COLD,
|
|
||||||
|
|
||||||
@Json(name = "mobile")
|
|
||||||
HOT,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.tangem.datasource.api.tangemTech.models
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = false)
|
||||||
|
enum class WalletType {
|
||||||
|
@Json(name = "card")
|
||||||
|
COLD,
|
||||||
|
|
||||||
|
@Json(name = "mobile")
|
||||||
|
HOT,
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun from(userWallet: UserWallet?): WalletType? {
|
||||||
|
return when (userWallet) {
|
||||||
|
is UserWallet.Cold -> COLD
|
||||||
|
is UserWallet.Hot -> HOT
|
||||||
|
null -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
package com.tangem.data.wallets.converters
|
package com.tangem.datasource.api.tangemTech.converters
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import com.tangem.datasource.api.tangemTech.models.CardInfoBody
|
import com.tangem.datasource.api.tangemTech.models.CardInfoBody
|
||||||
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
|
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
|
||||||
|
import com.tangem.datasource.api.tangemTech.models.WalletType
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import org.junit.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
class WalletIdBodyConverterTest {
|
class WalletIdBodyConverterTest {
|
||||||
|
|
||||||
|
|
@ -36,6 +37,7 @@ class WalletIdBodyConverterTest {
|
||||||
WalletIdBody(
|
WalletIdBody(
|
||||||
walletId = walletId.stringValue,
|
walletId = walletId.stringValue,
|
||||||
name = walletName,
|
name = walletName,
|
||||||
|
walletType = WalletType.COLD,
|
||||||
cards = listOf(
|
cards = listOf(
|
||||||
CardInfoBody(
|
CardInfoBody(
|
||||||
cardId = "card1",
|
cardId = "card1",
|
||||||
|
|
@ -72,6 +74,7 @@ class WalletIdBodyConverterTest {
|
||||||
assertThat(result).isEqualTo(
|
assertThat(result).isEqualTo(
|
||||||
WalletIdBody(
|
WalletIdBody(
|
||||||
walletId = walletId.stringValue,
|
walletId = walletId.stringValue,
|
||||||
|
walletType = WalletType.COLD,
|
||||||
name = walletName,
|
name = walletName,
|
||||||
cards = emptyList(),
|
cards = emptyList(),
|
||||||
),
|
),
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
<CurrentIssues>
|
<CurrentIssues>
|
||||||
<ID>CanBeNonNullable:FetchWalletAccountsErrorHandler.kt$FetchWalletAccountsErrorHandler$savedAccountsResponse: GetWalletAccountsResponse?</ID>
|
<ID>CanBeNonNullable:FetchWalletAccountsErrorHandler.kt$FetchWalletAccountsErrorHandler$savedAccountsResponse: GetWalletAccountsResponse?</ID>
|
||||||
<ID>MultilineLambdaItParameter:DefaultAccountsCRUDRepository.kt$DefaultAccountsCRUDRepository${ if (it is HttpException && it.code == HttpException.Code.NOT_MODIFIED) { null } else { throw it } }</ID>
|
<ID>MultilineLambdaItParameter:DefaultAccountsCRUDRepository.kt$DefaultAccountsCRUDRepository${ if (it is HttpException && it.code == HttpException.Code.NOT_MODIFIED) { null } else { throw it } }</ID>
|
||||||
<ID>MultilineLambdaItParameter:FetchWalletAccountsErrorHandler.kt$FetchWalletAccountsErrorHandler${ it.copy( tokens = UserTokensResponseAccountIdEnricher(userWalletId = userWalletId, tokens = it.tokens), ) }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:GetWalletAccountsResponseExt.kt${ enrichedTokensByAccountId[it].orEmpty().map { token -> // Tokens from unexisting accounts should be copied to the main account token.copy(accountId = accountDTO.id) } }</ID>
|
<ID>MultilineLambdaItParameter:GetWalletAccountsResponseExt.kt${ enrichedTokensByAccountId[it].orEmpty().map { token -> // Tokens from unexisting accounts should be copied to the main account token.copy(accountId = accountDTO.id) } }</ID>
|
||||||
<ID>NoNameShadowing:GetWalletAccountsResponseExt.kt$tokens</ID>
|
<ID>NoNameShadowing:GetWalletAccountsResponseExt.kt$tokens</ID>
|
||||||
<ID>NullableToStringCall:AccountListCryptoCurrenciesProducer.kt$AccountListCryptoCurrenciesProducer$${this::class.simpleName}</ID>
|
<ID>NullableToStringCall:AccountListCryptoCurrenciesProducer.kt$AccountListCryptoCurrenciesProducer$${this::class.simpleName}</ID>
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,13 @@ import com.tangem.datasource.api.common.response.ApiResponseError.HttpException.
|
||||||
import com.tangem.datasource.api.common.response.ETAG_HEADER
|
import com.tangem.datasource.api.common.response.ETAG_HEADER
|
||||||
import com.tangem.datasource.api.common.response.isNetworkError
|
import com.tangem.datasource.api.common.response.isNetworkError
|
||||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||||
|
import com.tangem.datasource.api.tangemTech.converters.WalletIdBodyConverter
|
||||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||||
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
|
|
||||||
import com.tangem.datasource.api.tangemTech.models.WalletIdBody.WalletType
|
|
||||||
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
|
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
|
||||||
import com.tangem.datasource.api.tangemTech.models.account.WalletAccountDTO
|
import com.tangem.datasource.api.tangemTech.models.account.WalletAccountDTO
|
||||||
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
|
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
|
||||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
@ -110,9 +108,9 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor(
|
||||||
|
|
||||||
private suspend fun getFromLegacyStore(userWalletId: UserWalletId): UserTokensResponse? {
|
private suspend fun getFromLegacyStore(userWalletId: UserWalletId): UserTokensResponse? {
|
||||||
return userTokensResponseStore.getSyncOrNull(userWalletId)
|
return userTokensResponseStore.getSyncOrNull(userWalletId)
|
||||||
?.let {
|
?.let { response ->
|
||||||
it.copy(
|
response.copy(
|
||||||
tokens = UserTokensResponseAccountIdEnricher(userWalletId = userWalletId, tokens = it.tokens),
|
tokens = UserTokensResponseAccountIdEnricher(userWalletId = userWalletId, tokens = response.tokens),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.also { userTokensResponseStore.clear(userWalletId) }
|
.also { userTokensResponseStore.clear(userWalletId) }
|
||||||
|
|
@ -129,14 +127,7 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor(
|
||||||
|
|
||||||
val creationResponse = withContext(dispatchers.io) {
|
val creationResponse = withContext(dispatchers.io) {
|
||||||
tangemTechApi.createWallet(
|
tangemTechApi.createWallet(
|
||||||
body = WalletIdBody(
|
body = WalletIdBodyConverter.convert(userWallet),
|
||||||
walletId = userWalletId.stringValue,
|
|
||||||
name = userWallet.name,
|
|
||||||
walletType = when (userWallet) {
|
|
||||||
is UserWallet.Cold -> WalletType.COLD
|
|
||||||
is UserWallet.Hot -> WalletType.HOT
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import com.tangem.datasource.api.common.response.ETAG_HEADER
|
||||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||||
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
|
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
|
||||||
|
import com.tangem.datasource.api.tangemTech.models.WalletType
|
||||||
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
|
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
|
||||||
import com.tangem.datasource.api.tangemTech.models.account.WalletAccountDTO
|
import com.tangem.datasource.api.tangemTech.models.account.WalletAccountDTO
|
||||||
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
|
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
|
||||||
|
|
@ -124,7 +125,7 @@ class FetchWalletAccountsErrorHandlerTest {
|
||||||
WalletIdBody(
|
WalletIdBody(
|
||||||
walletId = userWalletId.stringValue,
|
walletId = userWalletId.stringValue,
|
||||||
name = walletName,
|
name = walletName,
|
||||||
walletType = WalletIdBody.WalletType.COLD,
|
walletType = WalletType.COLD,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} returns apiResponse
|
} returns apiResponse
|
||||||
|
|
@ -146,7 +147,7 @@ class FetchWalletAccountsErrorHandlerTest {
|
||||||
WalletIdBody(
|
WalletIdBody(
|
||||||
walletId = userWalletId.stringValue,
|
walletId = userWalletId.stringValue,
|
||||||
name = walletName,
|
name = walletName,
|
||||||
walletType = WalletIdBody.WalletType.COLD,
|
walletType = WalletType.COLD,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
eTagsStore.store(userWalletId, ETagsStore.Key.WalletAccounts, eTagValue)
|
eTagsStore.store(userWalletId, ETagsStore.Key.WalletAccounts, eTagValue)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ import com.tangem.data.common.api.safeApiCall
|
||||||
import com.tangem.data.common.tokens.UserTokensBackwardCompatibility
|
import com.tangem.data.common.tokens.UserTokensBackwardCompatibility
|
||||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||||
|
import com.tangem.datasource.api.tangemTech.models.WalletType
|
||||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||||
|
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
|
@ -13,8 +15,10 @@ import com.tangem.utils.retryer.RetryerPool
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
class UserTokensSaver(
|
class UserTokensSaver(
|
||||||
private val tangemTechApi: TangemTechApi,
|
private val tangemTechApi: TangemTechApi,
|
||||||
|
private val userWalletsStore: UserWalletsStore,
|
||||||
private val userTokensResponseStore: UserTokensResponseStore,
|
private val userTokensResponseStore: UserTokensResponseStore,
|
||||||
private val dispatchers: CoroutineDispatcherProvider,
|
private val dispatchers: CoroutineDispatcherProvider,
|
||||||
private val addressesEnricher: UserTokensResponseAddressesEnricher,
|
private val addressesEnricher: UserTokensResponseAddressesEnricher,
|
||||||
|
|
@ -48,7 +52,12 @@ class UserTokensSaver(
|
||||||
onFailSend: () -> Unit = {},
|
onFailSend: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
withContext(dispatchers.default) {
|
withContext(dispatchers.default) {
|
||||||
val enrichedResponse = response.enrichIf(userWalletId = userWalletId, condition = useEnricher)
|
val userWallet = userWalletsStore.getSyncOrNull(key = userWalletId)
|
||||||
|
|
||||||
|
val enrichedResponse = response.enrichIf(userWalletId = userWalletId, condition = useEnricher).copy(
|
||||||
|
walletName = userWallet?.name,
|
||||||
|
walletType = WalletType.from(userWallet),
|
||||||
|
)
|
||||||
|
|
||||||
safeApiCall(
|
safeApiCall(
|
||||||
call = {
|
call = {
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ internal object DataCommonModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideUserTokensSaver(
|
fun provideUserTokensSaver(
|
||||||
tangemTechApi: TangemTechApi,
|
tangemTechApi: TangemTechApi,
|
||||||
|
userWalletsStore: UserWalletsStore,
|
||||||
userTokensResponseStore: UserTokensResponseStore,
|
userTokensResponseStore: UserTokensResponseStore,
|
||||||
dispatchers: CoroutineDispatcherProvider,
|
dispatchers: CoroutineDispatcherProvider,
|
||||||
addressesEnricher: UserTokensResponseAddressesEnricher,
|
addressesEnricher: UserTokensResponseAddressesEnricher,
|
||||||
|
|
@ -75,6 +76,7 @@ internal object DataCommonModule {
|
||||||
): UserTokensSaver {
|
): UserTokensSaver {
|
||||||
return UserTokensSaver(
|
return UserTokensSaver(
|
||||||
tangemTechApi = tangemTechApi,
|
tangemTechApi = tangemTechApi,
|
||||||
|
userWalletsStore = userWalletsStore,
|
||||||
userTokensResponseStore = userTokensResponseStore,
|
userTokensResponseStore = userTokensResponseStore,
|
||||||
dispatchers = dispatchers,
|
dispatchers = dispatchers,
|
||||||
addressesEnricher = addressesEnricher,
|
addressesEnricher = addressesEnricher,
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,11 @@ import com.tangem.datasource.api.common.response.ApiResponse
|
||||||
import com.tangem.datasource.api.common.response.ApiResponseError
|
import com.tangem.datasource.api.common.response.ApiResponseError
|
||||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||||
|
import com.tangem.datasource.api.tangemTech.models.WalletType
|
||||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||||
|
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||||
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||||
import io.mockk.*
|
import io.mockk.*
|
||||||
|
|
@ -18,6 +21,7 @@ import org.junit.jupiter.api.TestInstance
|
||||||
class UserTokensSaverTest {
|
class UserTokensSaverTest {
|
||||||
|
|
||||||
private val tangemTechApi: TangemTechApi = mockk()
|
private val tangemTechApi: TangemTechApi = mockk()
|
||||||
|
private val userWalletsStore: UserWalletsStore = mockk(relaxUnitFun = true)
|
||||||
private val userTokensResponseStore: UserTokensResponseStore = mockk(relaxed = true)
|
private val userTokensResponseStore: UserTokensResponseStore = mockk(relaxed = true)
|
||||||
private val enricher: UserTokensResponseAddressesEnricher = mockk()
|
private val enricher: UserTokensResponseAddressesEnricher = mockk()
|
||||||
private val accountsFeatureToggles = mockk<AccountsFeatureToggles> {
|
private val accountsFeatureToggles = mockk<AccountsFeatureToggles> {
|
||||||
|
|
@ -26,6 +30,7 @@ class UserTokensSaverTest {
|
||||||
|
|
||||||
private val userTokensSaver: UserTokensSaver = UserTokensSaver(
|
private val userTokensSaver: UserTokensSaver = UserTokensSaver(
|
||||||
tangemTechApi = tangemTechApi,
|
tangemTechApi = tangemTechApi,
|
||||||
|
userWalletsStore = userWalletsStore,
|
||||||
userTokensResponseStore = userTokensResponseStore,
|
userTokensResponseStore = userTokensResponseStore,
|
||||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||||
addressesEnricher = enricher,
|
addressesEnricher = enricher,
|
||||||
|
|
@ -35,7 +40,7 @@ class UserTokensSaverTest {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
fun resetMocks() {
|
fun resetMocks() {
|
||||||
clearMocks(tangemTechApi, userTokensResponseStore, enricher)
|
clearMocks(tangemTechApi, userWalletsStore, userTokensResponseStore, enricher)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -77,20 +82,31 @@ class UserTokensSaverTest {
|
||||||
runTest {
|
runTest {
|
||||||
// GIVEN
|
// GIVEN
|
||||||
val userWalletId = UserWalletId("1234567890abcdef")
|
val userWalletId = UserWalletId("1234567890abcdef")
|
||||||
|
val userWallet = mockk<UserWallet.Cold> {
|
||||||
|
every { this@mockk.walletId } returns userWalletId
|
||||||
|
every { this@mockk.name } returns "Wallet"
|
||||||
|
}
|
||||||
|
|
||||||
val response = UserTokensResponse(
|
val response = UserTokensResponse(
|
||||||
version = 0,
|
version = 0,
|
||||||
group = UserTokensResponse.GroupType.NETWORK,
|
group = UserTokensResponse.GroupType.NETWORK,
|
||||||
sort = UserTokensResponse.SortType.BALANCE,
|
sort = UserTokensResponse.SortType.BALANCE,
|
||||||
tokens = emptyList(),
|
tokens = emptyList(),
|
||||||
|
walletName = userWallet.name,
|
||||||
|
walletType = WalletType.COLD,
|
||||||
)
|
)
|
||||||
val enrichedResponse = UserTokensResponse(
|
val enrichedResponse = UserTokensResponse(
|
||||||
version = 0,
|
version = 0,
|
||||||
group = UserTokensResponse.GroupType.NETWORK,
|
group = UserTokensResponse.GroupType.NETWORK,
|
||||||
sort = UserTokensResponse.SortType.MANUAL,
|
sort = UserTokensResponse.SortType.MANUAL,
|
||||||
tokens = emptyList(),
|
tokens = emptyList(),
|
||||||
|
walletName = userWallet.name,
|
||||||
|
walletType = WalletType.COLD,
|
||||||
)
|
)
|
||||||
val error = ApiResponseError.UnknownException(Exception("API Error"))
|
val error = ApiResponseError.UnknownException(Exception("API Error"))
|
||||||
var onFailSendCalled = false
|
var onFailSendCalled = false
|
||||||
|
|
||||||
|
coEvery { userWalletsStore.getSyncOrNull(userWalletId) } returns userWallet
|
||||||
coEvery { enricher(userWalletId, response) } returns enrichedResponse
|
coEvery { enricher(userWalletId, response) } returns enrichedResponse
|
||||||
coEvery { tangemTechApi.saveUserTokens(any(), any()) } returns ApiResponse.Error(error) as ApiResponse<Unit>
|
coEvery { tangemTechApi.saveUserTokens(any(), any()) } returns ApiResponse.Error(error) as ApiResponse<Unit>
|
||||||
|
|
||||||
|
|
@ -114,18 +130,29 @@ class UserTokensSaverTest {
|
||||||
fun `GIVEN user wallet id and response WHEN storeAndPush THEN should store and push enriched response`() = runTest {
|
fun `GIVEN user wallet id and response WHEN storeAndPush THEN should store and push enriched response`() = runTest {
|
||||||
// GIVEN
|
// GIVEN
|
||||||
val userWalletId = UserWalletId("1234567890abcdef")
|
val userWalletId = UserWalletId("1234567890abcdef")
|
||||||
|
val userWallet = mockk<UserWallet.Cold> {
|
||||||
|
every { this@mockk.walletId } returns userWalletId
|
||||||
|
every { this@mockk.name } returns "Wallet"
|
||||||
|
}
|
||||||
|
|
||||||
val response = UserTokensResponse(
|
val response = UserTokensResponse(
|
||||||
version = 0,
|
version = 0,
|
||||||
group = UserTokensResponse.GroupType.NETWORK,
|
group = UserTokensResponse.GroupType.NETWORK,
|
||||||
sort = UserTokensResponse.SortType.BALANCE,
|
sort = UserTokensResponse.SortType.BALANCE,
|
||||||
tokens = emptyList(),
|
tokens = emptyList(),
|
||||||
|
walletName = userWallet.name,
|
||||||
|
walletType = WalletType.COLD,
|
||||||
)
|
)
|
||||||
val enrichedResponse = UserTokensResponse(
|
val enrichedResponse = UserTokensResponse(
|
||||||
version = 0,
|
version = 0,
|
||||||
group = UserTokensResponse.GroupType.NETWORK,
|
group = UserTokensResponse.GroupType.NETWORK,
|
||||||
sort = UserTokensResponse.SortType.BALANCE,
|
sort = UserTokensResponse.SortType.BALANCE,
|
||||||
tokens = emptyList(),
|
tokens = emptyList(),
|
||||||
|
walletName = userWallet.name,
|
||||||
|
walletType = WalletType.COLD,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
coEvery { userWalletsStore.getSyncOrNull(userWalletId) } returns userWallet
|
||||||
coEvery { enricher(userWalletId, response) } returns enrichedResponse
|
coEvery { enricher(userWalletId, response) } returns enrichedResponse
|
||||||
coEvery {
|
coEvery {
|
||||||
tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse)
|
tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse)
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,6 @@
|
||||||
<SmellBaseline>
|
<SmellBaseline>
|
||||||
<ManuallySuppressedIssues/>
|
<ManuallySuppressedIssues/>
|
||||||
<CurrentIssues>
|
<CurrentIssues>
|
||||||
<ID>BooleanPropertyNaming:DefaultWalletsRepository.kt$DefaultWalletsRepository$val legacySaveWalletsInTheApp = appPreferencesStore.getSyncOrNull( key = PreferencesKeys.SAVE_USER_WALLETS_KEY, )</ID>
|
|
||||||
<ID>BooleanPropertyNaming:DefaultWalletsRepository.kt$DefaultWalletsRepository$val legacyShouldSaveAccessCode = appPreferencesStore.getSyncOrNull( key = PreferencesKeys.SHOULD_SAVE_ACCESS_CODES_KEY, )</ID>
|
|
||||||
<ID>BooleanPropertyNaming:DefaultWalletsRepository.kt$DefaultWalletsRepository$val requireAccessCode = appPreferencesStore.getSyncOrNull( key = PreferencesKeys.REQUIRE_ACCESS_CODE_KEY, )</ID>
|
|
||||||
<ID>BooleanPropertyNaming:DefaultWalletsRepository.kt$DefaultWalletsRepository$val useBiometricAuthentication = appPreferencesStore.getSyncOrNull( key = PreferencesKeys.USE_BIOMETRIC_AUTHENTICATION_KEY, )</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:DefaultColdMapDerivationsRepository.kt$DefaultColdMapDerivationsRepository${ networkFactory.create( blockchain = Blockchain.fromNetworkId(it.value) ?: return@mapNotNull null, extraDerivationPath = null, userWallet = userWallet, ) }</ID>
|
<ID>MultilineLambdaItParameter:DefaultColdMapDerivationsRepository.kt$DefaultColdMapDerivationsRepository${ networkFactory.create( blockchain = Blockchain.fromNetworkId(it.value) ?: return@mapNotNull null, extraDerivationPath = null, userWallet = userWallet, ) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:DefaultDerivationsRepository.kt$DefaultDerivationsRepository${ userWallet.update(it.first) it.second }</ID>
|
<ID>MultilineLambdaItParameter:DefaultDerivationsRepository.kt$DefaultDerivationsRepository${ userWallet.update(it.first) it.second }</ID>
|
||||||
<ID>MultilineLambdaItParameter:DefaultHotMapDerivationsRepository.kt$DefaultHotMapDerivationsRepository${ networkFactory.create( blockchain = Blockchain.fromNetworkId(it.value) ?: return@mapNotNull null, extraDerivationPath = null, userWallet = userWallet, ) }</ID>
|
<ID>MultilineLambdaItParameter:DefaultHotMapDerivationsRepository.kt$DefaultHotMapDerivationsRepository${ networkFactory.create( blockchain = Blockchain.fromNetworkId(it.value) ?: return@mapNotNull null, extraDerivationPath = null, userWallet = userWallet, ) }</ID>
|
||||||
|
|
@ -14,19 +10,9 @@
|
||||||
<ID>MultilineLambdaItParameter:DefaultHotWalletAccessCodeAttemptsRepository.kt$DefaultHotWalletAccessCodeAttemptsRepository${ while (true) { emit(toState(id, it.attempts, it.deadline, it.bootCount)) val remaining = remainingSeconds(it.deadline, it.bootCount) if (remaining <= 0) break delay(timeMillis = 1000) } }</ID>
|
<ID>MultilineLambdaItParameter:DefaultHotWalletAccessCodeAttemptsRepository.kt$DefaultHotWalletAccessCodeAttemptsRepository${ while (true) { emit(toState(id, it.attempts, it.deadline, it.bootCount)) val remaining = remainingSeconds(it.deadline, it.bootCount) if (remaining <= 0) break delay(timeMillis = 1000) } }</ID>
|
||||||
<ID>MultilineLambdaItParameter:DefaultHotWalletAccessor.kt$DefaultHotWalletAccessor${ block(UnlockHotWallet(hotWalletId, it)).also { hotWalletPasswordRequester.successfulAuthentication() hotWalletPasswordRequester.dismiss() } }</ID>
|
<ID>MultilineLambdaItParameter:DefaultHotWalletAccessor.kt$DefaultHotWalletAccessor${ block(UnlockHotWallet(hotWalletId, it)).also { hotWalletPasswordRequester.successfulAuthentication() hotWalletPasswordRequester.dismiss() } }</ID>
|
||||||
<ID>MultilineLambdaItParameter:DefaultHotWalletAccessor.kt$DefaultHotWalletAccessor${ tangemHotSdk.getContextUnlock(it).also { unlockHotWallet -> contextualUnlockHotWallet[hotWalletId] = unlockHotWallet } }</ID>
|
<ID>MultilineLambdaItParameter:DefaultHotWalletAccessor.kt$DefaultHotWalletAccessor${ tangemHotSdk.getContextUnlock(it).also { unlockHotWallet -> contextualUnlockHotWallet[hotWalletId] = unlockHotWallet } }</ID>
|
||||||
<ID>MultilineLambdaItParameter:DefaultWalletsRepository.kt$DefaultWalletsRepository${ if (it is HttpException && it.code == HttpException.Code.NOT_FOUND) { Status.NOTIFIED } else { Status.NOT_NEEDED } }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:DefaultWalletsRepository.kt$DefaultWalletsRepository${ it.getOrDefault( key = userWalletId, defaultValue = SeedPhraseNotificationsStatus.NOT_NEEDED, ) }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:DefaultWalletsRepository.kt$DefaultWalletsRepository${ it.setObjectMap( key = PreferencesKeys.NOTIFICATIONS_ENABLED_STATES_KEY, value = it.getObjectMap<Boolean>(PreferencesKeys.NOTIFICATIONS_ENABLED_STATES_KEY) .plus(userWalletId.stringValue to isEnabled), ) }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:DefaultWalletsRepository.kt$DefaultWalletsRepository${ it.setObjectMap( key = PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY, value = it.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY) .plus(userWalletId.stringValue to false), ) }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:DefaultWalletsRepository.kt$DefaultWalletsRepository${ it.setObjectMap( key = PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY, value = it.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY) .plus(userWalletId.stringValue to true), ) }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:DefaultWalletsRepository.kt$DefaultWalletsRepository${ it.toMutableMap().apply { this[id] = value } }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:DefaultWalletsRepository.kt$DefaultWalletsRepository${ val added = it[PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY].orEmpty() it[PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY] = added + userWalletId.stringValue }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:TangemHotWalletSigner.kt$TangemHotWalletSigner${ Timber.e(it) return if (it is TangemSdkError) { CompletionResult.Failure(it) } else { CompletionResult.Failure(TangemSdkError.ExceptionError(it)) } }</ID>
|
<ID>MultilineLambdaItParameter:TangemHotWalletSigner.kt$TangemHotWalletSigner${ Timber.e(it) return if (it is TangemSdkError) { CompletionResult.Failure(it) } else { CompletionResult.Failure(TangemSdkError.ExceptionError(it)) } }</ID>
|
||||||
<ID>MultilineLambdaItParameter:WalletIdBodyConverter.kt$WalletIdBodyConverter${ CardInfoBody( cardId = it.key, cardPublicKey = it.value, ) }</ID>
|
|
||||||
<ID>NamedArguments:DefaultHotWalletAccessCodeAttemptsRepository.kt$DefaultHotWalletAccessCodeAttemptsRepository$toState(id, count, deadline, boot)</ID>
|
<ID>NamedArguments:DefaultHotWalletAccessCodeAttemptsRepository.kt$DefaultHotWalletAccessCodeAttemptsRepository$toState(id, count, deadline, boot)</ID>
|
||||||
<ID>NamedArguments:DefaultHotWalletAccessCodeAttemptsRepository.kt$DefaultHotWalletAccessCodeAttemptsRepository$toState(id, it.attempts, it.deadline, it.bootCount)</ID>
|
<ID>NamedArguments:DefaultHotWalletAccessCodeAttemptsRepository.kt$DefaultHotWalletAccessCodeAttemptsRepository$toState(id, it.attempts, it.deadline, it.bootCount)</ID>
|
||||||
<ID>NoNameShadowing:DefaultWalletsRepository.kt$DefaultWalletsRepository$error</ID>
|
|
||||||
<ID>NoNameShadowing:DefaultWalletsRepository.kt$DefaultWalletsRepository${ UserWalletId(it.key) }</ID>
|
|
||||||
<ID>SuspendFunSwallowedCancellation:DefaultHotWalletAccessor.kt$DefaultHotWalletAccessor$runCatching</ID>
|
<ID>SuspendFunSwallowedCancellation:DefaultHotWalletAccessor.kt$DefaultHotWalletAccessor$runCatching</ID>
|
||||||
<ID>SuspendFunSwallowedCancellation:TangemHotWalletSigner.kt$TangemHotWalletSigner$runCatching</ID>
|
<ID>SuspendFunSwallowedCancellation:TangemHotWalletSigner.kt$TangemHotWalletSigner$runCatching</ID>
|
||||||
<ID>UnnecessaryLet:MissedDerivationsFinder.kt$MissedDerivationsFinder$let(::findByNetworks)</ID>
|
<ID>UnnecessaryLet:MissedDerivationsFinder.kt$MissedDerivationsFinder$let(::findByNetworks)</ID>
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,17 @@ import arrow.core.Either
|
||||||
import arrow.core.left
|
import arrow.core.left
|
||||||
import arrow.core.right
|
import arrow.core.right
|
||||||
import com.tangem.data.wallets.converters.UserWalletRemoteInfoConverter
|
import com.tangem.data.wallets.converters.UserWalletRemoteInfoConverter
|
||||||
import com.tangem.data.wallets.converters.WalletIdBodyConverter
|
|
||||||
import com.tangem.datasource.api.common.AuthProvider
|
import com.tangem.datasource.api.common.AuthProvider
|
||||||
import com.tangem.datasource.api.common.response.ApiResponseError.HttpException
|
import com.tangem.datasource.api.common.response.ApiResponseError.HttpException
|
||||||
import com.tangem.datasource.api.common.response.fold
|
import com.tangem.datasource.api.common.response.fold
|
||||||
import com.tangem.datasource.api.common.response.getOrThrow
|
import com.tangem.datasource.api.common.response.getOrThrow
|
||||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||||
import com.tangem.datasource.api.tangemTech.models.*
|
import com.tangem.datasource.api.tangemTech.converters.WalletIdBodyConverter
|
||||||
|
import com.tangem.datasource.api.tangemTech.models.PromocodeActivationBody
|
||||||
|
import com.tangem.datasource.api.tangemTech.models.SeedPhraseNotificationDTO
|
||||||
import com.tangem.datasource.api.tangemTech.models.SeedPhraseNotificationDTO.Status
|
import com.tangem.datasource.api.tangemTech.models.SeedPhraseNotificationDTO.Status
|
||||||
import com.tangem.datasource.api.tangemTech.models.WalletIdBody.WalletType
|
import com.tangem.datasource.api.tangemTech.models.WalletBody
|
||||||
|
import com.tangem.datasource.api.tangemTech.models.WalletType
|
||||||
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
||||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||||
|
|
@ -62,25 +64,25 @@ internal class DefaultWalletsRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun useBiometricAuthentication(): Boolean {
|
override suspend fun useBiometricAuthentication(): Boolean {
|
||||||
val useBiometricAuthentication = appPreferencesStore.getSyncOrNull(
|
val shouldUseBiometricAuth = appPreferencesStore.getSyncOrNull(
|
||||||
key = PreferencesKeys.USE_BIOMETRIC_AUTHENTICATION_KEY,
|
key = PreferencesKeys.USE_BIOMETRIC_AUTHENTICATION_KEY,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (useBiometricAuthentication != null) {
|
if (shouldUseBiometricAuth != null) {
|
||||||
return useBiometricAuthentication
|
return shouldUseBiometricAuth
|
||||||
}
|
}
|
||||||
|
|
||||||
val legacySaveWalletsInTheApp = appPreferencesStore.getSyncOrNull(
|
val isLegacySaveWalletsInTheApp = appPreferencesStore.getSyncOrNull(
|
||||||
key = PreferencesKeys.SAVE_USER_WALLETS_KEY,
|
key = PreferencesKeys.SAVE_USER_WALLETS_KEY,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (legacySaveWalletsInTheApp != null) {
|
if (isLegacySaveWalletsInTheApp != null) {
|
||||||
// Migrate legacy setting to new one
|
// Migrate legacy setting to new one
|
||||||
appPreferencesStore.store(
|
appPreferencesStore.store(
|
||||||
key = PreferencesKeys.USE_BIOMETRIC_AUTHENTICATION_KEY,
|
key = PreferencesKeys.USE_BIOMETRIC_AUTHENTICATION_KEY,
|
||||||
value = legacySaveWalletsInTheApp,
|
value = isLegacySaveWalletsInTheApp,
|
||||||
)
|
)
|
||||||
return legacySaveWalletsInTheApp
|
return isLegacySaveWalletsInTheApp
|
||||||
} else {
|
} else {
|
||||||
// Default value for new users
|
// Default value for new users
|
||||||
setUseBiometricAuthentication(false)
|
setUseBiometricAuthentication(false)
|
||||||
|
|
@ -93,25 +95,25 @@ internal class DefaultWalletsRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun requireAccessCode(): Boolean {
|
override suspend fun requireAccessCode(): Boolean {
|
||||||
val requireAccessCode = appPreferencesStore.getSyncOrNull(
|
val isRequireAccessCode = appPreferencesStore.getSyncOrNull(
|
||||||
key = PreferencesKeys.REQUIRE_ACCESS_CODE_KEY,
|
key = PreferencesKeys.REQUIRE_ACCESS_CODE_KEY,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (requireAccessCode != null) {
|
if (isRequireAccessCode != null) {
|
||||||
return requireAccessCode
|
return isRequireAccessCode
|
||||||
}
|
}
|
||||||
|
|
||||||
val legacyShouldSaveAccessCode = appPreferencesStore.getSyncOrNull(
|
val isLegacyShouldSaveAccessCode = appPreferencesStore.getSyncOrNull(
|
||||||
key = PreferencesKeys.SHOULD_SAVE_ACCESS_CODES_KEY,
|
key = PreferencesKeys.SHOULD_SAVE_ACCESS_CODES_KEY,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (legacyShouldSaveAccessCode != null) {
|
if (isLegacyShouldSaveAccessCode != null) {
|
||||||
// Migrate legacy setting to new one
|
// Migrate legacy setting to new one
|
||||||
appPreferencesStore.store(
|
appPreferencesStore.store(
|
||||||
key = PreferencesKeys.REQUIRE_ACCESS_CODE_KEY,
|
key = PreferencesKeys.REQUIRE_ACCESS_CODE_KEY,
|
||||||
value = legacyShouldSaveAccessCode.not(),
|
value = isLegacyShouldSaveAccessCode.not(),
|
||||||
)
|
)
|
||||||
return legacyShouldSaveAccessCode.not()
|
return isLegacyShouldSaveAccessCode.not()
|
||||||
} else {
|
} else {
|
||||||
// Default value for new users
|
// Default value for new users
|
||||||
setRequireAccessCode(true)
|
setRequireAccessCode(true)
|
||||||
|
|
@ -130,10 +132,10 @@ internal class DefaultWalletsRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setHasWalletsWithRing(userWalletId: UserWalletId) {
|
override suspend fun setHasWalletsWithRing(userWalletId: UserWalletId) {
|
||||||
appPreferencesStore.editData {
|
appPreferencesStore.editData { mutablePreferences ->
|
||||||
val added = it[PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY].orEmpty()
|
val added = mutablePreferences[PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY].orEmpty()
|
||||||
|
|
||||||
it[PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY] = added + userWalletId.stringValue
|
mutablePreferences[PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY] = added + userWalletId.stringValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,8 +143,8 @@ internal class DefaultWalletsRepository(
|
||||||
return channelFlow {
|
return channelFlow {
|
||||||
launch {
|
launch {
|
||||||
seedPhraseNotificationVisibilityStore.get()
|
seedPhraseNotificationVisibilityStore.get()
|
||||||
.map {
|
.map { map ->
|
||||||
it.getOrDefault(
|
map.getOrDefault(
|
||||||
key = userWalletId,
|
key = userWalletId,
|
||||||
defaultValue = SeedPhraseNotificationsStatus.NOT_NEEDED,
|
defaultValue = SeedPhraseNotificationsStatus.NOT_NEEDED,
|
||||||
)
|
)
|
||||||
|
|
@ -169,8 +171,8 @@ internal class DefaultWalletsRepository(
|
||||||
tangemTechApi.getSeedPhraseNotificationStatus(walletId = userWalletId.stringValue).getOrThrow()
|
tangemTechApi.getSeedPhraseNotificationStatus(walletId = userWalletId.stringValue).getOrThrow()
|
||||||
}.fold(
|
}.fold(
|
||||||
onSuccess = { it.status },
|
onSuccess = { it.status },
|
||||||
onFailure = {
|
onFailure = { throwable ->
|
||||||
if (it is HttpException && it.code == HttpException.Code.NOT_FOUND) {
|
if (throwable is HttpException && throwable.code == HttpException.Code.NOT_FOUND) {
|
||||||
Status.NOTIFIED
|
Status.NOTIFIED
|
||||||
} else {
|
} else {
|
||||||
Status.NOT_NEEDED
|
Status.NOT_NEEDED
|
||||||
|
|
@ -245,27 +247,12 @@ internal class DefaultWalletsRepository(
|
||||||
updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED)
|
updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun markWallet2WasCreated(userWalletId: UserWalletId) {
|
|
||||||
runCatching(dispatchers.io) {
|
|
||||||
tangemTechApi.markUserWallerWasCreated(
|
|
||||||
body = MarkUserWalletWasCreatedBody(userWalletId = userWalletId.stringValue),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun createWallet(userWalletId: UserWalletId) {
|
override suspend fun createWallet(userWalletId: UserWalletId) {
|
||||||
withContext(dispatchers.io) {
|
runCatching(dispatchers.io) {
|
||||||
val userWallet = userWalletsStore.getSyncStrict(key = userWalletId)
|
val userWallet = userWalletsStore.getSyncStrict(key = userWalletId)
|
||||||
|
|
||||||
tangemTechApi.createWallet(
|
tangemTechApi.createWallet(
|
||||||
body = WalletIdBody(
|
body = WalletIdBodyConverter.convert(userWallet = userWallet),
|
||||||
walletId = userWalletId.stringValue,
|
|
||||||
name = userWallet.name,
|
|
||||||
walletType = when (userWallet) {
|
|
||||||
is UserWallet.Cold -> WalletType.COLD
|
|
||||||
is UserWallet.Hot -> WalletType.HOT
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -293,8 +280,8 @@ internal class DefaultWalletsRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updateNotificationVisibility(id: UserWalletId, value: SeedPhraseNotificationsStatus) {
|
private suspend fun updateNotificationVisibility(id: UserWalletId, value: SeedPhraseNotificationsStatus) {
|
||||||
return seedPhraseNotificationVisibilityStore.update {
|
return seedPhraseNotificationVisibilityStore.update { map ->
|
||||||
it.toMutableMap().apply {
|
map.toMutableMap().apply {
|
||||||
this[id] = value
|
this[id] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -306,23 +293,23 @@ internal class DefaultWalletsRepository(
|
||||||
|
|
||||||
override fun nftEnabledStatuses(): Flow<Map<UserWalletId, Boolean>> = appPreferencesStore
|
override fun nftEnabledStatuses(): Flow<Map<UserWalletId, Boolean>> = appPreferencesStore
|
||||||
.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY)
|
.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY)
|
||||||
.map { it.mapKeys { UserWalletId(it.key) } }
|
.map { map -> map.mapKeys { UserWalletId(it.key) } }
|
||||||
|
|
||||||
override suspend fun enableNFT(userWalletId: UserWalletId) {
|
override suspend fun enableNFT(userWalletId: UserWalletId) {
|
||||||
appPreferencesStore.editData {
|
appPreferencesStore.editData { mutablePreferences ->
|
||||||
it.setObjectMap(
|
mutablePreferences.setObjectMap(
|
||||||
key = PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY,
|
key = PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY,
|
||||||
value = it.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY)
|
value = mutablePreferences.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY)
|
||||||
.plus(userWalletId.stringValue to true),
|
.plus(userWalletId.stringValue to true),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun disableNFT(userWalletId: UserWalletId) {
|
override suspend fun disableNFT(userWalletId: UserWalletId) {
|
||||||
appPreferencesStore.editData {
|
appPreferencesStore.editData { mutablePreferences ->
|
||||||
it.setObjectMap(
|
mutablePreferences.setObjectMap(
|
||||||
key = PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY,
|
key = PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY,
|
||||||
value = it.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY)
|
value = mutablePreferences.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY)
|
||||||
.plus(userWalletId.stringValue to false),
|
.plus(userWalletId.stringValue to false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -338,10 +325,10 @@ internal class DefaultWalletsRepository(
|
||||||
.firstOrNull() == true
|
.firstOrNull() == true
|
||||||
|
|
||||||
override suspend fun setNotificationsEnabled(userWalletId: UserWalletId, isEnabled: Boolean) {
|
override suspend fun setNotificationsEnabled(userWalletId: UserWalletId, isEnabled: Boolean) {
|
||||||
appPreferencesStore.editData {
|
appPreferencesStore.editData { mutablePreferences ->
|
||||||
it.setObjectMap(
|
mutablePreferences.setObjectMap(
|
||||||
key = PreferencesKeys.NOTIFICATIONS_ENABLED_STATES_KEY,
|
key = PreferencesKeys.NOTIFICATIONS_ENABLED_STATES_KEY,
|
||||||
value = it.getObjectMap<Boolean>(PreferencesKeys.NOTIFICATIONS_ENABLED_STATES_KEY)
|
value = mutablePreferences.getObjectMap<Boolean>(PreferencesKeys.NOTIFICATIONS_ENABLED_STATES_KEY)
|
||||||
.plus(userWalletId.stringValue to isEnabled),
|
.plus(userWalletId.stringValue to isEnabled),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -358,9 +345,11 @@ internal class DefaultWalletsRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setWalletName(walletId: String, walletName: String) = withContext(dispatchers.io) {
|
override suspend fun setWalletName(walletId: String, walletName: String) = withContext(dispatchers.io) {
|
||||||
|
val userWallet = userWalletsStore.getSyncOrNull(key = UserWalletId(walletId))
|
||||||
|
|
||||||
tangemTechApi.updateWallet(
|
tangemTechApi.updateWallet(
|
||||||
walletId = walletId,
|
walletId = walletId,
|
||||||
body = WalletBody(name = walletName),
|
body = WalletBody(name = walletName, type = WalletType.from(userWallet)),
|
||||||
).getOrThrow()
|
).getOrThrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,18 +408,20 @@ internal class DefaultWalletsRepository(
|
||||||
promoCode = promoCode,
|
promoCode = promoCode,
|
||||||
address = bitcoinAddress,
|
address = bitcoinAddress,
|
||||||
),
|
),
|
||||||
).fold({
|
).fold(
|
||||||
return@fold it.status.right()
|
onSuccess = { it.status.right() },
|
||||||
}, { error ->
|
onError = { apiResponseError ->
|
||||||
val error = when (error) {
|
val error = when (apiResponseError) {
|
||||||
is HttpException -> when (error.code) {
|
is HttpException -> when (apiResponseError.code) {
|
||||||
HttpException.Code.NOT_FOUND -> ActivatePromoCodeError.InvalidPromoCode
|
HttpException.Code.NOT_FOUND -> ActivatePromoCodeError.InvalidPromoCode
|
||||||
HttpException.Code.CONFLICT -> ActivatePromoCodeError.PromocodeAlreadyUsed
|
HttpException.Code.CONFLICT -> ActivatePromoCodeError.PromocodeAlreadyUsed
|
||||||
|
else -> ActivatePromoCodeError.ActivationFailed
|
||||||
|
}
|
||||||
else -> ActivatePromoCodeError.ActivationFailed
|
else -> ActivatePromoCodeError.ActivationFailed
|
||||||
}
|
}
|
||||||
else -> ActivatePromoCodeError.ActivationFailed
|
|
||||||
}
|
error.left()
|
||||||
return@fold error.left()
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
==========================================
|
==========================================
|
||||||
Detekt Baseline Updater & Issue Counter
|
Detekt Baseline Updater & Issue Counter
|
||||||
==========================================
|
==========================================
|
||||||
Date: 2025-11-20 16:34:32
|
Date: 2025-11-21 15:22:23
|
||||||
|
|
||||||
Updating detekt baseline for debug variant...
|
Updating detekt baseline for debug variant...
|
||||||
|
|
||||||
|
|
@ -13,13 +13,13 @@ Counting issues in baseline files...
|
||||||
==========================================
|
==========================================
|
||||||
|
|
||||||
Summary:
|
Summary:
|
||||||
Total Issues: 1744
|
Total Issues: 1720
|
||||||
Modules with Issues: 90
|
Modules with Issues: 90
|
||||||
Average Issues per Module: 19
|
Average Issues per Module: 19
|
||||||
|
|
||||||
Progress:
|
Progress:
|
||||||
Fixed: 58 out of 1802 (3%)
|
Fixed: 82 out of 1802 (4%)
|
||||||
Remaining: 1744
|
Remaining: 1720
|
||||||
|
|
||||||
==========================================
|
==========================================
|
||||||
All Modules with Issues (sorted by count)
|
All Modules with Issues (sorted by count)
|
||||||
|
|
@ -29,11 +29,11 @@ Module Issues
|
||||||
────────────────────────────────────────────────────────────────
|
────────────────────────────────────────────────────────────────
|
||||||
features/wallet/impl 170
|
features/wallet/impl 170
|
||||||
features/markets/impl 155
|
features/markets/impl 155
|
||||||
features/onboarding-v2/impl 137
|
features/onboarding-v2/impl 131
|
||||||
features/onramp/impl 89
|
features/onramp/impl 89
|
||||||
features/send-v2/impl 80
|
features/send-v2/impl 80
|
||||||
features/swap/impl 73
|
features/swap/impl 73
|
||||||
features/hot-wallet/impl 61
|
features/hot-wallet/impl 58
|
||||||
features/staking/impl 56
|
features/staking/impl 56
|
||||||
data/wallet-connect 55
|
data/wallet-connect 55
|
||||||
features/swap-v2/impl 53
|
features/swap-v2/impl 53
|
||||||
|
|
@ -42,7 +42,6 @@ features/tokendetails/impl 49
|
||||||
features/manage-tokens/impl 45
|
features/manage-tokens/impl 45
|
||||||
domain/wallets 39
|
domain/wallets 39
|
||||||
features/nft/impl 36
|
features/nft/impl 36
|
||||||
data/wallets 32
|
|
||||||
features/tester/impl 31
|
features/tester/impl 31
|
||||||
features/yield-supply/impl 28
|
features/yield-supply/impl 28
|
||||||
domain/tokens 28
|
domain/tokens 28
|
||||||
|
|
@ -52,6 +51,7 @@ common/ui 26
|
||||||
data/visa 23
|
data/visa 23
|
||||||
features/tangempay/details/impl 22
|
features/tangempay/details/impl 22
|
||||||
data/nft 20
|
data/nft 20
|
||||||
|
data/wallets 18
|
||||||
features/swap/data 15
|
features/swap/data 15
|
||||||
data/swap 13
|
data/swap 13
|
||||||
domain/account/status 12
|
domain/account/status 12
|
||||||
|
|
@ -69,10 +69,10 @@ data/networks 9
|
||||||
features/welcome/impl 8
|
features/welcome/impl 8
|
||||||
features/home/impl 8
|
features/home/impl 8
|
||||||
domain/transaction 8
|
domain/transaction 8
|
||||||
data/account 8
|
|
||||||
libs/tangem-sdk-api 7
|
libs/tangem-sdk-api 7
|
||||||
data/txhistory 7
|
data/txhistory 7
|
||||||
data/tokens 7
|
data/tokens 7
|
||||||
|
data/account 7
|
||||||
features/send-v2/api 6
|
features/send-v2/api 6
|
||||||
domain/markets 6
|
domain/markets 6
|
||||||
data/wallet-manager 6
|
data/wallet-manager 6
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,6 @@ interface WalletsRepository {
|
||||||
|
|
||||||
suspend fun acceptSeedPhraseSecondNotification(userWalletId: UserWalletId)
|
suspend fun acceptSeedPhraseSecondNotification(userWalletId: UserWalletId)
|
||||||
|
|
||||||
suspend fun markWallet2WasCreated(userWalletId: UserWalletId)
|
|
||||||
|
|
||||||
suspend fun createWallet(userWalletId: UserWalletId)
|
suspend fun createWallet(userWalletId: UserWalletId)
|
||||||
|
|
||||||
fun nftEnabledStatus(userWalletId: UserWalletId): Flow<Boolean>
|
fun nftEnabledStatus(userWalletId: UserWalletId): Flow<Boolean>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.tangem.domain.wallets.usecase
|
||||||
|
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||||
|
import com.tangem.utils.coroutines.runSuspendCatching
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use case to sync wallet with remote
|
||||||
|
*
|
||||||
|
[REDACTED_AUTHOR]
|
||||||
|
*/
|
||||||
|
class SyncWalletWithRemoteUseCase(
|
||||||
|
private val walletsRepository: WalletsRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend operator fun invoke(userWalletId: UserWalletId) {
|
||||||
|
runSuspendCatching { walletsRepository.createWallet(userWalletId) }
|
||||||
|
.onFailure(Timber::e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,7 +25,6 @@
|
||||||
<ID>MultilineLambdaItParameter:AddExistingWalletImportModel.kt$AddExistingWalletImportModel${ Timber.e(it) setImportProgress(false) }</ID>
|
<ID>MultilineLambdaItParameter:AddExistingWalletImportModel.kt$AddExistingWalletImportModel${ Timber.e(it) setImportProgress(false) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:AddExistingWalletImportModel.kt$AddExistingWalletImportModel${ setImportProgress(false) when (it) { is SaveWalletError.DataError -> Timber.e(it.toString(), "Unable to save user wallet") is SaveWalletError.WalletAlreadySaved -> { uiMessageSender.send( SnackbarMessage(resourceReference(R.string.hw_import_seed_phrase_already_imported)), ) } } }</ID>
|
<ID>MultilineLambdaItParameter:AddExistingWalletImportModel.kt$AddExistingWalletImportModel${ setImportProgress(false) when (it) { is SaveWalletError.DataError -> Timber.e(it.toString(), "Unable to save user wallet") is SaveWalletError.WalletAlreadySaved -> { uiMessageSender.send( SnackbarMessage(resourceReference(R.string.hw_import_seed_phrase_already_imported)), ) } } }</ID>
|
||||||
<ID>MultilineLambdaItParameter:CreateHardwareWalletModel.kt$CreateHardwareWalletModel${ delay(HIDE_PROGRESS_DELAY) setLoading(false) when (it) { is SaveWalletError.DataError -> Timber.e(it.toString(), "Unable to save user wallet") is SaveWalletError.WalletAlreadySaved -> { userWalletsListRepository.unlock( userWalletId = userWallet.walletId, unlockMethod = UserWalletsListRepository.UnlockMethod.Scan(scanResponse), ).onRight { router.replaceAll(AppRoute.Wallet) } } } }</ID>
|
<ID>MultilineLambdaItParameter:CreateHardwareWalletModel.kt$CreateHardwareWalletModel${ delay(HIDE_PROGRESS_DELAY) setLoading(false) when (it) { is SaveWalletError.DataError -> Timber.e(it.toString(), "Unable to save user wallet") is SaveWalletError.WalletAlreadySaved -> { userWalletsListRepository.unlock( userWalletId = userWallet.walletId, unlockMethod = UserWalletsListRepository.UnlockMethod.Scan(scanResponse), ).onRight { router.replaceAll(AppRoute.Wallet) } } } }</ID>
|
||||||
<ID>MultilineLambdaItParameter:CreateMobileWalletModel.kt$CreateMobileWalletModel${ Timber.e(it) uiState.update { it.copy(createButtonLoading = false) } }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:ForgetWalletModel.kt$ForgetWalletModel${ Timber.e("Unable to delete wallet: $it") uiMessageSender.send( message = SnackbarMessage(resourceReference(R.string.common_unknown_error)), ) return@launch }</ID>
|
<ID>MultilineLambdaItParameter:ForgetWalletModel.kt$ForgetWalletModel${ Timber.e("Unable to delete wallet: $it") uiMessageSender.send( message = SnackbarMessage(resourceReference(R.string.common_unknown_error)), ) return@launch }</ID>
|
||||||
<ID>MultilineLambdaItParameter:ForgetWalletModel.kt$ForgetWalletModel${ val newValue = !it.firstCheckboxChecked it.copy( firstCheckboxChecked = newValue, isForgetButtonEnabled = newValue && it.secondCheckboxChecked, ) }</ID>
|
<ID>MultilineLambdaItParameter:ForgetWalletModel.kt$ForgetWalletModel${ val newValue = !it.firstCheckboxChecked it.copy( firstCheckboxChecked = newValue, isForgetButtonEnabled = newValue && it.secondCheckboxChecked, ) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:ForgetWalletModel.kt$ForgetWalletModel${ val newValue = !it.secondCheckboxChecked it.copy( secondCheckboxChecked = newValue, isForgetButtonEnabled = it.firstCheckboxChecked && newValue, ) }</ID>
|
<ID>MultilineLambdaItParameter:ForgetWalletModel.kt$ForgetWalletModel${ val newValue = !it.secondCheckboxChecked it.copy( secondCheckboxChecked = newValue, isForgetButtonEnabled = it.firstCheckboxChecked && newValue, ) }</ID>
|
||||||
|
|
@ -52,7 +51,6 @@
|
||||||
<ID>MultilineLambdaItParameter:UpgradeWalletModel.kt$UpgradeWalletModel${ // Check if user attempted to upgrade before but something went wrong and a full reset is required val userWallet = coldUserWalletBuilderFactory.create(it).build() val sameWalletButNotFinishedBackup by lazy { userWallet?.walletId == params.userWalletId && BackupValidator.isValidFull(it.card).not() } val otherWalletAndAlreadyCreated by lazy { userWallet?.walletId != params.userWalletId && it.card.wallets.map { it.curve }.toSet().isNotEmpty() } if (userWallet != null && (sameWalletButNotFinishedBackup || otherWalletAndAlreadyCreated)) { startResetCardsFlow.emit(userWallet) return@doOnSuccess } delay(DELAY_SDK_DIALOG_CLOSE) tangemSdkManager.changeDisplayedCardIdNumbersCount(it) navigateToUpgradeFlow(it) }</ID>
|
<ID>MultilineLambdaItParameter:UpgradeWalletModel.kt$UpgradeWalletModel${ // Check if user attempted to upgrade before but something went wrong and a full reset is required val userWallet = coldUserWalletBuilderFactory.create(it).build() val sameWalletButNotFinishedBackup by lazy { userWallet?.walletId == params.userWalletId && BackupValidator.isValidFull(it.card).not() } val otherWalletAndAlreadyCreated by lazy { userWallet?.walletId != params.userWalletId && it.card.wallets.map { it.curve }.toSet().isNotEmpty() } if (userWallet != null && (sameWalletButNotFinishedBackup || otherWalletAndAlreadyCreated)) { startResetCardsFlow.emit(userWallet) return@doOnSuccess } delay(DELAY_SDK_DIALOG_CLOSE) tangemSdkManager.changeDisplayedCardIdNumbersCount(it) navigateToUpgradeFlow(it) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:ViewPhraseContent.kt${ EnumeratedTwoColumnGridItem( index = it + 1, mnemonic = "word${it + 1}", ) }</ID>
|
<ID>MultilineLambdaItParameter:ViewPhraseContent.kt${ EnumeratedTwoColumnGridItem( index = it + 1, mnemonic = "word${it + 1}", ) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:ViewPhraseModel.kt$ViewPhraseModel${ it.copy( words = words.mapIndexed { index, s -> EnumeratedTwoColumnGridItem(index + 1, s) }.toImmutableList(), ) }</ID>
|
<ID>MultilineLambdaItParameter:ViewPhraseModel.kt$ViewPhraseModel${ it.copy( words = words.mapIndexed { index, s -> EnumeratedTwoColumnGridItem(index + 1, s) }.toImmutableList(), ) }</ID>
|
||||||
<ID>NoNameShadowing:CreateMobileWalletModel.kt$CreateMobileWalletModel${ it.copy(createButtonLoading = false) }</ID>
|
|
||||||
<ID>NoNameShadowing:ManualBackupCheckModel.kt$ManualBackupCheckModel${ it.copy(completeButtonProgress = false) }</ID>
|
<ID>NoNameShadowing:ManualBackupCheckModel.kt$ManualBackupCheckModel${ it.copy(completeButtonProgress = false) }</ID>
|
||||||
<ID>PropertyUsedBeforeDeclaration:AddExistingWalletImportModel.kt$AddExistingWalletImportModel$uiState</ID>
|
<ID>PropertyUsedBeforeDeclaration:AddExistingWalletImportModel.kt$AddExistingWalletImportModel$uiState</ID>
|
||||||
<ID>ReusedModifierInstance:AddExistingWalletImportContent.kt$OutlineTextFieldWithIcon( modifier = modifier .padding(horizontal = 16.dp) .fillMaxWidth(), value = state.passPhrase, onValueChange = state.passPhraseChange, iconResId = R.drawable.ic_information_24, iconColor = TangemTheme.colors.icon.informative, label = stringResourceSafe(id = R.string.common_passphrase), placeholder = stringResourceSafe(id = R.string.send_optional_field), onIconClick = state.onPassphraseInfoClick, keyboardOptions = KeyboardOptions( autoCorrectEnabled = false, keyboardType = KeyboardType.Password, ), )</ID>
|
<ID>ReusedModifierInstance:AddExistingWalletImportContent.kt$OutlineTextFieldWithIcon( modifier = modifier .padding(horizontal = 16.dp) .fillMaxWidth(), value = state.passPhrase, onValueChange = state.passPhraseChange, iconResId = R.drawable.ic_information_24, iconColor = TangemTheme.colors.icon.informative, label = stringResourceSafe(id = R.string.common_passphrase), placeholder = stringResourceSafe(id = R.string.send_optional_field), onIconClick = state.onPassphraseInfoClick, keyboardOptions = KeyboardOptions( autoCorrectEnabled = false, keyboardType = KeyboardType.Password, ), )</ID>
|
||||||
|
|
@ -60,7 +58,6 @@
|
||||||
<ID>ReusedModifierInstance:HotWalletStepper.kt$TangemTopAppBar( startButton = if (state.showBackButton) { TopAppBarButtonUM.Back(onBackClick) } else { null }, endButton = when { state.showSkipButton -> TopAppBarButtonUM.Text( text = resourceReference(R.string.common_skip), onClicked = onSkipClick, ) state.showFeedbackButton -> TopAppBarButtonUM.Icon( iconRes = R.drawable.ic_chat_24, onClicked = onFeedbackClick, ) else -> null }, title = state.title, containerColor = TangemTheme.colors.background.primary, modifier = modifier, titleAlignment = Alignment.CenterHorizontally, )</ID>
|
<ID>ReusedModifierInstance:HotWalletStepper.kt$TangemTopAppBar( startButton = if (state.showBackButton) { TopAppBarButtonUM.Back(onBackClick) } else { null }, endButton = when { state.showSkipButton -> TopAppBarButtonUM.Text( text = resourceReference(R.string.common_skip), onClicked = onSkipClick, ) state.showFeedbackButton -> TopAppBarButtonUM.Icon( iconRes = R.drawable.ic_chat_24, onClicked = onFeedbackClick, ) else -> null }, title = state.title, containerColor = TangemTheme.colors.background.primary, modifier = modifier, titleAlignment = Alignment.CenterHorizontally, )</ID>
|
||||||
<ID>SuspendFunSwallowedCancellation:AccessCodeModel.kt$AccessCodeModel$runCatching</ID>
|
<ID>SuspendFunSwallowedCancellation:AccessCodeModel.kt$AccessCodeModel$runCatching</ID>
|
||||||
<ID>SuspendFunSwallowedCancellation:AddExistingWalletImportModel.kt$AddExistingWalletImportModel$runCatching</ID>
|
<ID>SuspendFunSwallowedCancellation:AddExistingWalletImportModel.kt$AddExistingWalletImportModel$runCatching</ID>
|
||||||
<ID>SuspendFunSwallowedCancellation:CreateMobileWalletModel.kt$CreateMobileWalletModel$runCatching</ID>
|
|
||||||
<ID>SuspendFunSwallowedCancellation:ManualBackupCheckModel.kt$ManualBackupCheckModel$runCatching</ID>
|
<ID>SuspendFunSwallowedCancellation:ManualBackupCheckModel.kt$ManualBackupCheckModel$runCatching</ID>
|
||||||
<ID>SuspendFunSwallowedCancellation:ManualBackupPhraseModel.kt$ManualBackupPhraseModel$runCatching</ID>
|
<ID>SuspendFunSwallowedCancellation:ManualBackupPhraseModel.kt$ManualBackupPhraseModel$runCatching</ID>
|
||||||
</CurrentIssues>
|
</CurrentIssues>
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,14 @@ import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.navigation.Router
|
import com.tangem.core.decompose.navigation.Router
|
||||||
import com.tangem.domain.wallets.builder.HotUserWalletBuilder
|
import com.tangem.domain.wallets.builder.HotUserWalletBuilder
|
||||||
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
||||||
|
import com.tangem.domain.wallets.usecase.SyncWalletWithRemoteUseCase
|
||||||
import com.tangem.features.hotwallet.createmobilewallet.entity.CreateMobileWalletUM
|
import com.tangem.features.hotwallet.createmobilewallet.entity.CreateMobileWalletUM
|
||||||
import com.tangem.hot.sdk.TangemHotSdk
|
import com.tangem.hot.sdk.TangemHotSdk
|
||||||
import com.tangem.hot.sdk.model.HotAuth
|
import com.tangem.hot.sdk.model.HotAuth
|
||||||
import com.tangem.hot.sdk.model.MnemonicType
|
import com.tangem.hot.sdk.model.MnemonicType
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
import com.tangem.utils.coroutines.runSuspendCatching
|
||||||
|
import kotlinx.coroutines.NonCancellable
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
@ -19,11 +22,13 @@ import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
@ModelScoped
|
@ModelScoped
|
||||||
internal class CreateMobileWalletModel @Inject constructor(
|
internal class CreateMobileWalletModel @Inject constructor(
|
||||||
override val dispatchers: CoroutineDispatcherProvider,
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
private val hotUserWalletBuilderFactory: HotUserWalletBuilder.Factory,
|
private val hotUserWalletBuilderFactory: HotUserWalletBuilder.Factory,
|
||||||
private val saveUserWalletUseCase: SaveWalletUseCase,
|
private val saveUserWalletUseCase: SaveWalletUseCase,
|
||||||
|
private val syncWalletWithRemoteUseCase: SyncWalletWithRemoteUseCase,
|
||||||
private val router: Router,
|
private val router: Router,
|
||||||
private val tangemHotSdk: TangemHotSdk,
|
private val tangemHotSdk: TangemHotSdk,
|
||||||
private val trackingContextProxy: TrackingContextProxy,
|
private val trackingContextProxy: TrackingContextProxy,
|
||||||
|
|
@ -58,18 +63,21 @@ internal class CreateMobileWalletModel @Inject constructor(
|
||||||
it.copy(createButtonLoading = true)
|
it.copy(createButtonLoading = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
runCatching {
|
runSuspendCatching {
|
||||||
val hotWalletId = tangemHotSdk.generateWallet(HotAuth.NoAuth, mnemonicType = MnemonicType.Words12)
|
val hotWalletId = tangemHotSdk.generateWallet(HotAuth.NoAuth, mnemonicType = MnemonicType.Words12)
|
||||||
val hotUserWalletBuilder = hotUserWalletBuilderFactory.create(hotWalletId)
|
val hotUserWalletBuilder = hotUserWalletBuilderFactory.create(hotWalletId)
|
||||||
val userWallet = hotUserWalletBuilder.build()
|
val userWallet = hotUserWalletBuilder.build()
|
||||||
saveUserWalletUseCase(userWallet)
|
|
||||||
router.replaceAll(AppRoute.Wallet)
|
|
||||||
}.onFailure {
|
|
||||||
Timber.e(it)
|
|
||||||
|
|
||||||
uiState.update {
|
saveUserWalletUseCase(userWallet)
|
||||||
it.copy(createButtonLoading = false)
|
|
||||||
|
launch(NonCancellable) {
|
||||||
|
syncWalletWithRemoteUseCase(userWalletId = userWallet.walletId)
|
||||||
}
|
}
|
||||||
|
router.replaceAll(AppRoute.Wallet)
|
||||||
|
}.onFailure { throwable ->
|
||||||
|
Timber.e(throwable)
|
||||||
|
|
||||||
|
uiState.update { it.copy(createButtonLoading = false) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
<ID>BooleanPropertyNaming:MultiWalletBackupUM.kt$MultiWalletBackupUMDialog$val warningCancelColor: Boolean = false</ID>
|
<ID>BooleanPropertyNaming:MultiWalletBackupUM.kt$MultiWalletBackupUMDialog$val warningCancelColor: Boolean = false</ID>
|
||||||
<ID>BooleanPropertyNaming:MultiWalletCreateWalletModel.kt$MultiWalletCreateWalletModel$val cardDoesNotSupportBackup = result.data.card.settings.isBackupAllowed.not()</ID>
|
<ID>BooleanPropertyNaming:MultiWalletCreateWalletModel.kt$MultiWalletCreateWalletModel$val cardDoesNotSupportBackup = result.data.card.settings.isBackupAllowed.not()</ID>
|
||||||
<ID>BooleanPropertyNaming:MultiWalletCreateWalletUM.kt$MultiWalletCreateWalletUM$val showOtherOptionsButton: Boolean</ID>
|
<ID>BooleanPropertyNaming:MultiWalletCreateWalletUM.kt$MultiWalletCreateWalletUM$val showOtherOptionsButton: Boolean</ID>
|
||||||
<ID>BooleanPropertyNaming:MultiWalletFinalizeModel.kt$MultiWalletFinalizeModel$private var walletHasBackupError = false</ID>
|
|
||||||
<ID>BooleanPropertyNaming:MultiWalletFinalizeUM.kt$MultiWalletFinalizeUM$val scanPrimary: Boolean = true</ID>
|
<ID>BooleanPropertyNaming:MultiWalletFinalizeUM.kt$MultiWalletFinalizeUM$val scanPrimary: Boolean = true</ID>
|
||||||
<ID>BooleanPropertyNaming:MultiWalletSeedPhraseUM.kt$MultiWalletSeedPhraseUM.GeneratedWordsCheck$val createWalletButtonEnabled: Boolean = false</ID>
|
<ID>BooleanPropertyNaming:MultiWalletSeedPhraseUM.kt$MultiWalletSeedPhraseUM.GeneratedWordsCheck$val createWalletButtonEnabled: Boolean = false</ID>
|
||||||
<ID>BooleanPropertyNaming:MultiWalletSeedPhraseUM.kt$MultiWalletSeedPhraseUM.GeneratedWordsCheck$val createWalletButtonProgress: Boolean = false</ID>
|
<ID>BooleanPropertyNaming:MultiWalletSeedPhraseUM.kt$MultiWalletSeedPhraseUM.GeneratedWordsCheck$val createWalletButtonProgress: Boolean = false</ID>
|
||||||
|
|
@ -76,8 +75,6 @@
|
||||||
<ID>MultilineLambdaItParameter:MultiWalletCreateWalletComponent.kt$MultiWalletCreateWalletComponent${ it.copy( stackSize = 2, stackMaxSize = 9, ) }</ID>
|
<ID>MultilineLambdaItParameter:MultiWalletCreateWalletComponent.kt$MultiWalletCreateWalletComponent${ it.copy( stackSize = 2, stackMaxSize = 9, ) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:MultiWalletCreateWalletModel.kt$MultiWalletCreateWalletModel${ it.copy( currentScanResponse = it.currentScanResponse.copy( card = result.data.card, derivedKeys = result.data.derivedKeys, primaryCard = result.data.primaryCard, ), ) }</ID>
|
<ID>MultilineLambdaItParameter:MultiWalletCreateWalletModel.kt$MultiWalletCreateWalletModel${ it.copy( currentScanResponse = it.currentScanResponse.copy( card = result.data.card, derivedKeys = result.data.derivedKeys, primaryCard = result.data.primaryCard, ), ) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:MultiWalletFinalizeComponent.kt$MultiWalletFinalizeComponent${ it.copy( stackSize = 7, stackMaxSize = 9, ) }</ID>
|
<ID>MultilineLambdaItParameter:MultiWalletFinalizeComponent.kt$MultiWalletFinalizeComponent${ it.copy( stackSize = 7, stackMaxSize = 9, ) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:MultiWalletFinalizeModel.kt$MultiWalletFinalizeModel${ it is UserWallet.Cold && it.scanResponse.primaryCard?.cardId == scanResponse.primaryCard?.cardId }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:MultiWalletFinalizeModel.kt$MultiWalletFinalizeModel${ it.requireColdWallet().copy( scanResponse = scanResponse.updateScanResponseAfterBackup(), ) }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:MultiWalletScanPrimaryComponent.kt$MultiWalletScanPrimaryComponent${ it.copy( stackSize = 4, stackMaxSize = 9, ) }</ID>
|
<ID>MultilineLambdaItParameter:MultiWalletScanPrimaryComponent.kt$MultiWalletScanPrimaryComponent${ it.copy( stackSize = 4, stackMaxSize = 9, ) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:MultiWalletScanPrimaryModel.kt$MultiWalletScanPrimaryModel${ it.copy( currentScanResponse = scanResponse.copy( primaryCard = result.data, ), ) }</ID>
|
<ID>MultilineLambdaItParameter:MultiWalletScanPrimaryModel.kt$MultiWalletScanPrimaryModel${ it.copy( currentScanResponse = scanResponse.copy( primaryCard = result.data, ), ) }</ID>
|
||||||
<ID>MultilineLambdaItParameter:MultiWalletSeedPhraseComponent.kt$MultiWalletSeedPhraseComponent${ // change stepper state based on the stack of the current step @Suppress("MagicNumber") params.innerNavigation.update { st -> st.copy( stackSize = 3 + it.order, stackMaxSize = 11, ) } val title = when (it) { is MultiWalletSeedPhraseUM.Import -> R.string.onboarding_seed_intro_button_import is MultiWalletSeedPhraseUM.GenerateSeedPhrase, is MultiWalletSeedPhraseUM.GeneratedWordsCheck, is MultiWalletSeedPhraseUM.Start, -> R.string.onboarding_create_wallet_header } params.parentParams.titleProvider.changeTitle(text = resourceReference(title)) }</ID>
|
<ID>MultilineLambdaItParameter:MultiWalletSeedPhraseComponent.kt$MultiWalletSeedPhraseComponent${ // change stepper state based on the stack of the current step @Suppress("MagicNumber") params.innerNavigation.update { st -> st.copy( stackSize = 3 + it.order, stackMaxSize = 11, ) } val title = when (it) { is MultiWalletSeedPhraseUM.Import -> R.string.onboarding_seed_intro_button_import is MultiWalletSeedPhraseUM.GenerateSeedPhrase, is MultiWalletSeedPhraseUM.GeneratedWordsCheck, is MultiWalletSeedPhraseUM.Start, -> R.string.onboarding_create_wallet_header } params.parentParams.titleProvider.changeTitle(text = resourceReference(title)) }</ID>
|
||||||
|
|
@ -123,7 +120,6 @@
|
||||||
<ID>ReusedModifierInstance:OnboardingVisaAccessCode.kt$OutlineTextFieldWithIcon( modifier = modifier .padding(horizontal = 16.dp) .focusRequester(focusRequester) .fillMaxWidth(), iconResId = if (state.accessCodeHidden) { R.drawable.ic_eye_outline_24 } else { R.drawable.ic_eye_off_outline_24 }, iconColor = TangemTheme.colors.icon.primary1, onIconClick = state.onAccessCodeHideClick, value = if (reEnterAccessCodeState) { state.accessCodeSecond } else { state.accessCodeFirst }, onValueChange = if (reEnterAccessCodeState) { state.onAccessCodeSecondChange } else { state.onAccessCodeFirstChange }, label = stringResourceSafe(id = R.string.onboarding_wallet_info_title_third), isError = state.codesNotMatchError || state.atLeastMinCharsError, visualTransformation = if (state.accessCodeHidden) { PasswordVisualTransformation() } else { VisualTransformation.None }, caption = when { state.codesNotMatchError && reEnterAccessCodeState -> stringResourceSafe(R.string.onboarding_access_codes_doesnt_match) state.atLeastMinCharsError && !reEnterAccessCodeState -> stringResourceSafe(R.string.onboarding_access_code_too_short) else -> null }, )</ID>
|
<ID>ReusedModifierInstance:OnboardingVisaAccessCode.kt$OutlineTextFieldWithIcon( modifier = modifier .padding(horizontal = 16.dp) .focusRequester(focusRequester) .fillMaxWidth(), iconResId = if (state.accessCodeHidden) { R.drawable.ic_eye_outline_24 } else { R.drawable.ic_eye_off_outline_24 }, iconColor = TangemTheme.colors.icon.primary1, onIconClick = state.onAccessCodeHideClick, value = if (reEnterAccessCodeState) { state.accessCodeSecond } else { state.accessCodeFirst }, onValueChange = if (reEnterAccessCodeState) { state.onAccessCodeSecondChange } else { state.onAccessCodeFirstChange }, label = stringResourceSafe(id = R.string.onboarding_wallet_info_title_third), isError = state.codesNotMatchError || state.atLeastMinCharsError, visualTransformation = if (state.accessCodeHidden) { PasswordVisualTransformation() } else { VisualTransformation.None }, caption = when { state.codesNotMatchError && reEnterAccessCodeState -> stringResourceSafe(R.string.onboarding_access_codes_doesnt_match) state.atLeastMinCharsError && !reEnterAccessCodeState -> stringResourceSafe(R.string.onboarding_access_code_too_short) else -> null }, )</ID>
|
||||||
<ID>ReusedModifierInstance:OnboardingVisaPinCode.kt$PinCode( modifier = modifier, value = state.pinCode, onValueChange = state.onPinCodeChange, focusRequester = focusRequester, )</ID>
|
<ID>ReusedModifierInstance:OnboardingVisaPinCode.kt$PinCode( modifier = modifier, value = state.pinCode, onValueChange = state.onPinCodeChange, focusRequester = focusRequester, )</ID>
|
||||||
<ID>ReusedModifierInstance:OnboardingVisaWelcome.kt$Image( painter = painterResource(R.drawable.img_card_visa), contentDescription = null, modifier = modifier .align(Alignment.Center) .onSizeChanged { cardHeightPx = it.height } .widthIn(max = 512.dp) .fillMaxWidth(), )</ID>
|
<ID>ReusedModifierInstance:OnboardingVisaWelcome.kt$Image( painter = painterResource(R.drawable.img_card_visa), contentDescription = null, modifier = modifier .align(Alignment.Center) .onSizeChanged { cardHeightPx = it.height } .widthIn(max = 512.dp) .fillMaxWidth(), )</ID>
|
||||||
<ID>SuspendFunSwallowedCancellation:MultiWalletFinalizeModel.kt$MultiWalletFinalizeModel$runCatching</ID>
|
|
||||||
<ID>UnreachableCode:OnboardingNoteCreateWalletModel.kt$OnboardingNoteCreateWalletModel$params.childParams.commonState.value.scanResponse ?: return@launch</ID>
|
<ID>UnreachableCode:OnboardingNoteCreateWalletModel.kt$OnboardingNoteCreateWalletModel$params.childParams.commonState.value.scanResponse ?: return@launch</ID>
|
||||||
<ID>UnsafeCallOnNullableType:MultiWalletBackupModel.kt$MultiWalletBackupModel$backupServiceHolder.backupService.get()!!</ID>
|
<ID>UnsafeCallOnNullableType:MultiWalletBackupModel.kt$MultiWalletBackupModel$backupServiceHolder.backupService.get()!!</ID>
|
||||||
<ID>UnsafeCallOnNullableType:OnboardingEntryModel.kt$OnboardingEntryModel$userWalletsListManager.asLockable()?.isLocked!!</ID>
|
<ID>UnsafeCallOnNullableType:OnboardingEntryModel.kt$OnboardingEntryModel$userWalletsListManager.asLockable()?.isLocked!!</ID>
|
||||||
|
|
@ -136,8 +132,6 @@
|
||||||
<ID>UseEmptyCounterpart:OnboardingVisaAnalyticsEvent.kt$OnboardingVisaAnalyticsEvent$mapOf()</ID>
|
<ID>UseEmptyCounterpart:OnboardingVisaAnalyticsEvent.kt$OnboardingVisaAnalyticsEvent$mapOf()</ID>
|
||||||
<ID>UseEmptyCounterpart:VisaAnalyticsEvent.kt$VisaAnalyticsEvent$mapOf()</ID>
|
<ID>UseEmptyCounterpart:VisaAnalyticsEvent.kt$VisaAnalyticsEvent$mapOf()</ID>
|
||||||
<ID>UseEmptyCounterpart:WalletArtwork.kt$listOf()</ID>
|
<ID>UseEmptyCounterpart:WalletArtwork.kt$listOf()</ID>
|
||||||
<ID>UseOrEmpty:MultiWalletFinalizeModel.kt$MultiWalletFinalizeModel$backupService.backupCardIds.firstOrNull()?.lastMasked() ?: ""</ID>
|
|
||||||
<ID>UseOrEmpty:MultiWalletFinalizeModel.kt$MultiWalletFinalizeModel$backupService.backupCardIds.getOrNull(cardIndex + 1) ?.lastMasked() ?: ""</ID>
|
|
||||||
<ID>UseOrEmpty:OnboardingVisaPinCode.kt$value.getOrNull(index)?.toString() ?: ""</ID>
|
<ID>UseOrEmpty:OnboardingVisaPinCode.kt$value.getOrNull(index)?.toString() ?: ""</ID>
|
||||||
</CurrentIssues>
|
</CurrentIssues>
|
||||||
</SmellBaseline>
|
</SmellBaseline>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
import com.tangem.core.decompose.ui.UiMessageSender
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
|
||||||
import com.tangem.domain.card.repository.CardRepository
|
import com.tangem.domain.card.repository.CardRepository
|
||||||
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
|
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
|
||||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||||
|
|
@ -25,6 +24,7 @@ import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
|
||||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||||
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
||||||
|
import com.tangem.domain.wallets.usecase.SyncWalletWithRemoteUseCase
|
||||||
import com.tangem.domain.wallets.usecase.UpdateWalletUseCase
|
import com.tangem.domain.wallets.usecase.UpdateWalletUseCase
|
||||||
import com.tangem.features.onboarding.v2.common.ui.CantLeaveBackupDialog
|
import com.tangem.features.onboarding.v2.common.ui.CantLeaveBackupDialog
|
||||||
import com.tangem.features.onboarding.v2.impl.R
|
import com.tangem.features.onboarding.v2.impl.R
|
||||||
|
|
@ -63,6 +63,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
||||||
private val saveWalletUseCase: SaveWalletUseCase,
|
private val saveWalletUseCase: SaveWalletUseCase,
|
||||||
private val getUserWalletsUseCase: GetWalletsUseCase,
|
private val getUserWalletsUseCase: GetWalletsUseCase,
|
||||||
private val updateWalletUseCase: UpdateWalletUseCase,
|
private val updateWalletUseCase: UpdateWalletUseCase,
|
||||||
|
private val syncWalletWithRemoteUseCase: SyncWalletWithRemoteUseCase,
|
||||||
private val cardRepository: CardRepository,
|
private val cardRepository: CardRepository,
|
||||||
private val onboardingRepository: OnboardingRepository,
|
private val onboardingRepository: OnboardingRepository,
|
||||||
private val walletsRepository: WalletsRepository,
|
private val walletsRepository: WalletsRepository,
|
||||||
|
|
@ -76,7 +77,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
||||||
|
|
||||||
private val backupCardIds = backupServiceHolder.backupService.get()?.backupCardIds.orEmpty()
|
private val backupCardIds = backupServiceHolder.backupService.get()?.backupCardIds.orEmpty()
|
||||||
|
|
||||||
private var walletHasBackupError = false
|
private var hasWalletBackupError = false
|
||||||
private var hasRing = false
|
private var hasRing = false
|
||||||
|
|
||||||
val uiState = _uiState.asStateFlow()
|
val uiState = _uiState.asStateFlow()
|
||||||
|
|
@ -182,9 +183,9 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
||||||
_uiState.update { st ->
|
_uiState.update { st ->
|
||||||
st.copy(
|
st.copy(
|
||||||
step = MultiWalletFinalizeUM.Step.BackupDevice1,
|
step = MultiWalletFinalizeUM.Step.BackupDevice1,
|
||||||
isRing = backupService.backupCardsBatchIds.getOrNull(0)?.let { isRing(it) } == true,
|
isRing = backupService.backupCardsBatchIds.getOrNull(0)?.let(::isRing) == true,
|
||||||
scanPrimary = false,
|
scanPrimary = false,
|
||||||
cardNumber = backupService.backupCardIds.firstOrNull()?.lastMasked() ?: "",
|
cardNumber = backupService.backupCardIds.firstOrNull()?.lastMasked().orEmpty(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +208,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
||||||
is CompletionResult.Success -> {
|
is CompletionResult.Success -> {
|
||||||
val backupValidator = BackupValidator()
|
val backupValidator = BackupValidator()
|
||||||
if (backupValidator.isValidBackupStatus(CardDTO(result.data)).not()) {
|
if (backupValidator.isValidBackupStatus(CardDTO(result.data)).not()) {
|
||||||
walletHasBackupError = true
|
hasWalletBackupError = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backupService.currentState == BackupService.State.Finished) {
|
if (backupService.currentState == BackupService.State.Finished) {
|
||||||
|
|
@ -220,7 +221,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
||||||
isRing = backupService.backupCardsBatchIds
|
isRing = backupService.backupCardsBatchIds
|
||||||
.getOrNull(cardIndex + 1)?.let { isRing(it) } == true,
|
.getOrNull(cardIndex + 1)?.let { isRing(it) } == true,
|
||||||
cardNumber = backupService.backupCardIds.getOrNull(cardIndex + 1)
|
cardNumber = backupService.backupCardIds.getOrNull(cardIndex + 1)
|
||||||
?.lastMasked() ?: "",
|
?.lastMasked().orEmpty(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +247,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
||||||
|
|
||||||
// Validate wallet before saving
|
// Validate wallet before saving
|
||||||
// If something went wrong - start full reset flow
|
// If something went wrong - start full reset flow
|
||||||
if (walletHasBackupError || !backupValidator.isValidFull(scanResponse.card)) {
|
if (hasWalletBackupError || !backupValidator.isValidFull(scanResponse.card)) {
|
||||||
startFullResetFlow.emit(
|
startFullResetFlow.emit(
|
||||||
userWalletCreated.copy(
|
userWalletCreated.copy(
|
||||||
scanResponse = scanResponse.updateScanResponseAfterBackup(),
|
scanResponse = scanResponse.updateScanResponseAfterBackup(),
|
||||||
|
|
@ -269,16 +270,16 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
||||||
}
|
}
|
||||||
OnboardingMultiWalletComponent.Mode.AddBackup -> {
|
OnboardingMultiWalletComponent.Mode.AddBackup -> {
|
||||||
val userWallet = getUserWalletsUseCase.invokeSync()
|
val userWallet = getUserWalletsUseCase.invokeSync()
|
||||||
.firstOrNull {
|
.firstOrNull { userWallet ->
|
||||||
it is UserWallet.Cold &&
|
userWallet is UserWallet.Cold &&
|
||||||
it.scanResponse.primaryCard?.cardId == scanResponse.primaryCard?.cardId
|
userWallet.scanResponse.primaryCard?.cardId == scanResponse.primaryCard?.cardId
|
||||||
}
|
}
|
||||||
?: userWalletCreated
|
?: userWalletCreated
|
||||||
|
|
||||||
updateWalletUseCase.invoke(
|
updateWalletUseCase.invoke(
|
||||||
userWalletId = userWallet.walletId,
|
userWalletId = userWallet.walletId,
|
||||||
update = {
|
update = { wallet ->
|
||||||
it.requireColdWallet().copy(
|
wallet.requireColdWallet().copy(
|
||||||
scanResponse = scanResponse.updateScanResponseAfterBackup(),
|
scanResponse = scanResponse.updateScanResponseAfterBackup(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -313,20 +314,8 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
||||||
it.copy(resultUserWallet = userWallet)
|
it.copy(resultUserWallet = userWallet)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userWallet.scanResponse.cardTypesResolver.isWallet2() && userWallet.isImported) {
|
launch(NonCancellable) {
|
||||||
launch(NonCancellable) {
|
syncWalletWithRemoteUseCase(userWalletId = userWallet.walletId)
|
||||||
runCatching {
|
|
||||||
walletsRepository.markWallet2WasCreated(userWallet.walletId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userWallet.isMultiCurrency) {
|
|
||||||
launch(NonCancellable) {
|
|
||||||
runCatching {
|
|
||||||
walletsRepository.createWallet(userWallet.walletId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// user wallet is fully created and saved, remove scan response from preferences
|
// user wallet is fully created and saved, remove scan response from preferences
|
||||||
|
|
@ -343,7 +332,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
||||||
return requireNotNull(
|
return requireNotNull(
|
||||||
value = coldUserWalletBuilderFactory.create(scanResponse = scanResponse)
|
value = coldUserWalletBuilderFactory.create(scanResponse = scanResponse)
|
||||||
.backupCardsIds(backupCardIds.toSet())
|
.backupCardsIds(backupCardIds.toSet())
|
||||||
.hasBackupError(walletHasBackupError)
|
.hasBackupError(hasWalletBackupError)
|
||||||
.build(),
|
.build(),
|
||||||
lazyMessage = { "User wallet not created" },
|
lazyMessage = { "User wallet not created" },
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue