Updated on 2026-08-14

This commit is contained in:
Tangem 2025-11-10 17:01:15 +04:00
parent 7c9e533757
commit 1de582a28c
8 changed files with 50 additions and 28 deletions

View file

@ -139,7 +139,7 @@ interface TangemTechApi {
suspend fun getWallets(@Path("app_id") appId: String): ApiResponse<List<WalletResponse>>
@POST("v1/user-wallets/wallets")
suspend fun createWallet(@Body body: OnlyWalletIdBody): ApiResponse<Unit>
suspend fun createWallet(@Body body: WalletIdBody): ApiResponse<Unit>
// endregion
// promo

View file

@ -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 OnlyWalletIdBody(
@Json(name = "id") val walletId: String,
)

View file

@ -7,5 +7,5 @@ import com.squareup.moshi.JsonClass
data class WalletIdBody(
@Json(name = "id") val walletId: String,
@Json(name = "name") val name: String,
@Json(name = "cards") val cards: List<CardInfoBody>,
@Json(name = "cards") val cards: List<CardInfoBody>? = null,
)

View file

@ -10,12 +10,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.isNetworkError
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.OnlyWalletIdBody
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
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.toUserTokensResponse
import com.tangem.datasource.local.token.UserTokensResponseStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
@ -37,9 +38,11 @@ import javax.inject.Singleton
*
[REDACTED_AUTHOR]
*/
@Suppress("LongParameterList")
@Singleton
internal class FetchWalletAccountsErrorHandler @Inject constructor(
private val tangemTechApi: TangemTechApi,
private val userWalletsStore: UserWalletsStore,
private val userTokensSaver: UserTokensSaver,
private val userTokensResponseStore: UserTokensResponseStore,
private val defaultWalletAccountsResponseFactory: DefaultWalletAccountsResponseFactory,
@ -117,9 +120,14 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor(
*/
private suspend fun createWallet(userWalletId: UserWalletId): String? {
val userWallet = userWalletsStore.getSyncOrNull(key = userWalletId) ?: return null
val creationResponse = withContext(dispatchers.io) {
tangemTechApi.createWallet(
body = OnlyWalletIdBody(walletId = userWalletId.stringValue),
body = WalletIdBody(
walletId = userWalletId.stringValue,
name = userWallet.name,
),
)
}

View file

@ -10,18 +10,17 @@ import com.tangem.datasource.api.common.response.ApiResponseError
import com.tangem.datasource.api.common.response.ApiResponseError.HttpException.Code
import com.tangem.datasource.api.common.response.ETAG_HEADER
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.OnlyWalletIdBody
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
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.toUserTokensResponse
import com.tangem.datasource.local.token.UserTokensResponseStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.clearMocks
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import io.mockk.*
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@ -34,6 +33,7 @@ import org.junit.jupiter.api.TestInstance
class FetchWalletAccountsErrorHandlerTest {
private val tangemTechApi: TangemTechApi = mockk()
private val userWalletsStore: UserWalletsStore = mockk()
private val userTokensSaver: UserTokensSaver = mockk(relaxUnitFun = true)
private val userTokensResponseStore: UserTokensResponseStore = mockk(relaxUnitFun = true)
private val defaultWalletAccountsResponseFactory: DefaultWalletAccountsResponseFactory = mockk()
@ -41,6 +41,7 @@ class FetchWalletAccountsErrorHandlerTest {
private val handler = FetchWalletAccountsErrorHandler(
tangemTechApi = tangemTechApi,
userWalletsStore = userWalletsStore,
userTokensSaver = userTokensSaver,
userTokensResponseStore = userTokensResponseStore,
defaultWalletAccountsResponseFactory = defaultWalletAccountsResponseFactory,
@ -111,8 +112,15 @@ class FetchWalletAccountsErrorHandlerTest {
code = Code.CREATED,
)
val walletName = "Wallet"
val userWallet = mockk<UserWallet> {
every { this@mockk.walletId } returns userWalletId
every { this@mockk.name } returns walletName
}
coEvery { userWalletsStore.getSyncOrNull(userWalletId) } returns userWallet
coEvery {
tangemTechApi.createWallet(OnlyWalletIdBody(userWalletId.stringValue))
tangemTechApi.createWallet(WalletIdBody(walletId = userWalletId.stringValue, name = walletName))
} returns apiResponse
coEvery { pushWalletAccounts(userWalletId, listOf(accountDTO)) } returns savedAccountsResponse
@ -128,7 +136,7 @@ class FetchWalletAccountsErrorHandlerTest {
// Assert
coVerify {
userTokensSaver.pushWithRetryer(userWalletId, response = savedAccountsResponse.toUserTokensResponse())
tangemTechApi.createWallet(OnlyWalletIdBody(userWalletId.stringValue))
tangemTechApi.createWallet(WalletIdBody(walletId = userWalletId.stringValue, name = "Wallet"))
eTagsStore.store(userWalletId, ETagsStore.Key.WalletAccounts, eTagValue)
pushWalletAccounts(userWalletId, listOf(accountDTO))
storeWalletAccounts(userWalletId, savedAccountsResponse)

View file

@ -254,8 +254,13 @@ internal class DefaultWalletsRepository(
override suspend fun createWallet(userWalletId: UserWalletId) {
withContext(dispatchers.io) {
val userWallet = userWalletsStore.getSyncStrict(key = userWalletId)
tangemTechApi.createWallet(
body = OnlyWalletIdBody(userWalletId.stringValue),
body = WalletIdBody(
walletId = userWalletId.stringValue,
name = userWallet.name,
),
)
}
}

View file

@ -8,9 +8,9 @@ import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.common.response.ApiResponseError.HttpException
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.WalletResponse
import com.tangem.datasource.api.tangemTech.models.PromocodeActivationBody
import com.tangem.datasource.api.tangemTech.models.PromocodeActivationResponse
import com.tangem.datasource.api.tangemTech.models.WalletResponse
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.domain.models.wallet.UserWallet
@ -226,15 +226,17 @@ class DefaultWalletsRepositoryTest {
// THEN
coVerify(exactly = 1) {
tangemTechApi.associateApplicationIdWithWallets(
eq(applicationId),
match { body ->
applicationId = eq(applicationId),
body = match { body ->
body.size == 2 &&
body.any {
it.walletId == wallet1Id && it.cards.any { card -> card.cardPublicKey == "public_key_1" } &&
it.walletId == wallet1Id &&
it.cards!!.any { card -> card.cardPublicKey == "public_key_1" } &&
it.name == "Wallet 1"
} &&
body.any {
it.walletId == wallet2Id && it.cards.any { card -> card.cardPublicKey == "public_key_2" } &&
it.walletId == wallet2Id &&
it.cards!!.any { card -> card.cardPublicKey == "public_key_2" } &&
it.name == "Wallet 2"
}
},

View file

@ -304,11 +304,19 @@ internal class MultiWalletFinalizeModel @Inject constructor(
}
if (userWallet.scanResponse.cardTypesResolver.isWallet2() && userWallet.isImported) {
launch(NonCancellable) { walletsRepository.markWallet2WasCreated(userWallet.walletId) }
launch(NonCancellable) {
runCatching {
walletsRepository.markWallet2WasCreated(userWallet.walletId)
}
}
}
if (userWallet.isMultiCurrency) {
launch(NonCancellable) { walletsRepository.createWallet(userWallet.walletId) }
launch(NonCancellable) {
runCatching {
walletsRepository.createWallet(userWallet.walletId)
}
}
}
// user wallet is fully created and saved, remove scan response from preferences