Updated on 2026-08-14
This commit is contained in:
parent
8541957ee3
commit
189ffd9927
73 changed files with 547 additions and 409 deletions
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.common.extensions
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.builder.UserWalletIdBuilder
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.tap.common.analytics.paramsInterceptor.LinkedCardContextInterceptor
|
||||
|
||||
/**
|
||||
|
|
@ -21,6 +22,15 @@ fun Analytics.setContext(scanResponse: ScanResponse) {
|
|||
addParamsInterceptor(LinkedCardContextInterceptor(scanResponse))
|
||||
}
|
||||
|
||||
fun Analytics.setContext(userWallet: UserWallet) {
|
||||
setUserId(userWallet.walletId.stringValue)
|
||||
// TODO add product type for hot ([REDACTED_TASK_KEY])
|
||||
|
||||
if (userWallet is UserWallet.Cold) {
|
||||
addParamsInterceptor(LinkedCardContextInterceptor(userWallet.scanResponse))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Erases the context
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.blockchain.common.Wallet
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.tap.common.extensions.setContext
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -35,14 +34,15 @@ class TapWalletManager(
|
|||
}
|
||||
|
||||
private suspend fun loadUserWalletData(userWallet: UserWallet) {
|
||||
Analytics.setContext(userWallet.requireColdWallet().scanResponse) // [REDACTED_TASK_KEY]
|
||||
val scanResponse = userWallet.scanResponse
|
||||
Analytics.setContext(userWallet)
|
||||
|
||||
tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse)
|
||||
|
||||
withMainContext {
|
||||
// Order is important
|
||||
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
|
||||
if (userWallet is UserWallet.Cold) {
|
||||
val scanResponse = userWallet.scanResponse
|
||||
tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse)
|
||||
withMainContext {
|
||||
// Order is important
|
||||
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ internal class DefaultDerivationsRepository(
|
|||
networkFactory.create(
|
||||
blockchain = Blockchain.fromNetworkId(it.value) ?: return@mapNotNull null,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -91,7 +91,7 @@ internal class DefaultDerivationsRepository(
|
|||
networkFactory.create(
|
||||
blockchain = Blockchain.fromNetworkId(backendId) ?: return@mapNotNull null,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockTy
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isLocked
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey
|
||||
import com.tangem.tap.domain.userWalletList.repository.SelectedUserWalletRepository
|
||||
import com.tangem.tap.domain.userWalletList.repository.UserWalletsKeysRepository
|
||||
|
|
@ -208,8 +207,7 @@ internal class BiometricUserWalletsListManager(
|
|||
changeSelectedUserWallet: Boolean,
|
||||
canOverridePublicInfo: Boolean,
|
||||
): CompletionResult<Unit> {
|
||||
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
val encryptionKey = userWallet.scanResponse.card.encryptionKey
|
||||
val encryptionKey = userWallet.encryptionKey
|
||||
?.let { UserWalletEncryptionKey(userWallet.walletId, it) }
|
||||
?: return CompletionResult.Success(Unit) // No encryption key, no need to save
|
||||
|
||||
|
|
|
|||
|
|
@ -2,31 +2,44 @@ package com.tangem.tap.domain.userWalletList.model
|
|||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.tangem.domain.models.MobileWallet
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.visa.model.VisaCardActivationStatus
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class UserWalletSensitiveInformation(
|
||||
// Cold
|
||||
@Json(name = "wallets")
|
||||
val wallets: List<CardDTO.Wallet>,
|
||||
val wallets: List<CardDTO.Wallet>?,
|
||||
@Json(name = "visaCardActivationStatus")
|
||||
val visaCardActivationStatus: VisaCardActivationStatus? = null,
|
||||
// Hot
|
||||
@Json(name = "mobileWallets")
|
||||
val mobileWallets: List<MobileWallet>? = null,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class UserWalletPublicInformation(
|
||||
// Common
|
||||
@Json(name = "name")
|
||||
val name: String,
|
||||
@Json(name = "walletId")
|
||||
val walletId: UserWalletId,
|
||||
// Cold
|
||||
@Json(name = "cardsInWallet")
|
||||
val cardsInWallet: Set<String>,
|
||||
@Json(name = "scanResponse")
|
||||
val scanResponse: ScanResponse,
|
||||
val scanResponse: ScanResponse?,
|
||||
@Json(name = "isMultiCurrency")
|
||||
val isMultiCurrency: Boolean,
|
||||
@Json(name = "hasBackupError")
|
||||
val hasBackupError: Boolean = false,
|
||||
// Hot
|
||||
@Json(name = "hotWalletId")
|
||||
val hotWalletId: HotWalletId? = null,
|
||||
@Json(name = "backedUp")
|
||||
val backedUp: Boolean? = null,
|
||||
)
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.domain.userWalletList.utils
|
|||
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.tap.domain.userWalletList.model.UserWalletPublicInformation
|
||||
import com.tangem.tap.domain.userWalletList.model.UserWalletSensitiveInformation
|
||||
|
||||
|
|
@ -10,8 +11,12 @@ internal val UserWallet.sensitiveInformation: UserWalletSensitiveInformation
|
|||
is UserWallet.Cold -> UserWalletSensitiveInformation(
|
||||
wallets = scanResponse.card.wallets,
|
||||
visaCardActivationStatus = scanResponse.visaCardActivationStatus,
|
||||
mobileWallets = null,
|
||||
)
|
||||
is UserWallet.Hot -> UserWalletSensitiveInformation(
|
||||
wallets = null,
|
||||
mobileWallets = this.wallets,
|
||||
)
|
||||
is UserWallet.Hot -> TODO("[REDACTED_TASK_KEY]")
|
||||
}
|
||||
|
||||
internal val UserWallet.publicInformation: UserWalletPublicInformation
|
||||
|
|
@ -28,19 +33,39 @@ internal val UserWallet.publicInformation: UserWalletPublicInformation
|
|||
visaCardActivationStatus = null,
|
||||
),
|
||||
hasBackupError = hasBackupError,
|
||||
hotWalletId = null,
|
||||
backedUp = null,
|
||||
)
|
||||
is UserWallet.Hot -> UserWalletPublicInformation(
|
||||
name = name,
|
||||
walletId = walletId,
|
||||
isMultiCurrency = isMultiCurrency,
|
||||
cardsInWallet = emptySet(),
|
||||
scanResponse = null,
|
||||
hotWalletId = hotWalletId,
|
||||
backedUp = backedUp,
|
||||
)
|
||||
is UserWallet.Hot -> TODO("[REDACTED_TASK_KEY]")
|
||||
}
|
||||
|
||||
internal fun UserWalletPublicInformation.toUserWallet(): UserWallet {
|
||||
return UserWallet.Cold(
|
||||
name = name,
|
||||
walletId = walletId,
|
||||
cardsInWallet = cardsInWallet,
|
||||
scanResponse = scanResponse,
|
||||
isMultiCurrency = isMultiCurrency,
|
||||
hasBackupError = hasBackupError,
|
||||
)
|
||||
return if (hotWalletId != null) {
|
||||
UserWallet.Hot(
|
||||
name = name,
|
||||
walletId = walletId,
|
||||
hotWalletId = hotWalletId,
|
||||
wallets = null,
|
||||
backedUp = backedUp!!,
|
||||
)
|
||||
} else {
|
||||
UserWallet.Cold(
|
||||
name = name,
|
||||
walletId = walletId,
|
||||
cardsInWallet = cardsInWallet,
|
||||
scanResponse = scanResponse!!,
|
||||
isMultiCurrency = isMultiCurrency,
|
||||
hasBackupError = hasBackupError,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun List<UserWalletPublicInformation>.toUserWallets(): List<UserWallet> {
|
||||
|
|
@ -53,13 +78,15 @@ internal fun UserWallet.updateWith(sensitiveInformation: UserWalletSensitiveInfo
|
|||
copy(
|
||||
scanResponse = scanResponse.copy(
|
||||
card = scanResponse.card.copy(
|
||||
wallets = sensitiveInformation.wallets,
|
||||
wallets = sensitiveInformation.wallets!!,
|
||||
),
|
||||
visaCardActivationStatus = sensitiveInformation.visaCardActivationStatus,
|
||||
),
|
||||
)
|
||||
}
|
||||
is UserWallet.Hot -> TODO("[REDACTED_TASK_KEY]")
|
||||
is UserWallet.Hot -> copy(
|
||||
wallets = sensitiveInformation.mobileWallets,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
package com.tangem.tap.domain.userWalletList.utils
|
||||
|
||||
import com.tangem.common.extensions.calculateSha256
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.common.extensions.calculateHmacSha256
|
||||
import com.tangem.domain.models.MobileWallet
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
internal val CardDTO.encryptionKey: ByteArray?
|
||||
get() = findPublicKey(wallets)?.let { calculateEncryptionKey(it) }
|
||||
internal val UserWallet.encryptionKey: ByteArray?
|
||||
get() = when (this) {
|
||||
is UserWallet.Cold -> findPublicKey(this.scanResponse.card.wallets)
|
||||
is UserWallet.Hot -> findPublicKey(this.wallets.orEmpty())
|
||||
}?.let { calculateEncryptionKey(it) }
|
||||
|
||||
private fun calculateEncryptionKey(publicKey: ByteArray): ByteArray {
|
||||
val message = MESSAGE_FOR_ENCRYPTION_KEY.toByteArray()
|
||||
|
|
@ -15,8 +20,12 @@ private fun calculateEncryptionKey(publicKey: ByteArray): ByteArray {
|
|||
}
|
||||
|
||||
private fun findPublicKey(wallets: List<CardDTO.Wallet>): ByteArray? {
|
||||
return wallets.firstOrNull()
|
||||
?.publicKey
|
||||
return wallets.firstOrNull()?.publicKey
|
||||
}
|
||||
|
||||
@JvmName("findPublicKeyInMobileWallets")
|
||||
private fun findPublicKey(wallets: List<MobileWallet>): ByteArray? {
|
||||
return wallets.firstOrNull()?.publicKey
|
||||
}
|
||||
|
||||
private const val MESSAGE_FOR_ENCRYPTION_KEY = "UserWalletEncryptionKey"
|
||||
|
|
@ -14,7 +14,6 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
@ -422,8 +421,7 @@ class WalletConnectInteractor(
|
|||
}
|
||||
|
||||
private fun getCardId(userWallet: UserWallet): String? {
|
||||
userWallet.requireColdWallet() // [REDACTED_TASK_KEY]
|
||||
return if (userWallet.scanResponse.card.backupStatus?.isActive != true) {
|
||||
return if (userWallet is UserWallet.Cold && userWallet.scanResponse.card.backupStatus?.isActive != true) {
|
||||
userWallet.cardId
|
||||
} else { // if wallet has backup, any card from wallet can be used to sign
|
||||
null
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ import com.tangem.domain.settings.IncrementAppLaunchCounterUseCase
|
|||
import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase
|
||||
import com.tangem.domain.staking.FetchStakingTokensUseCase
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.usecase.AssociateWalletsWithApplicationIdUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetSavedWalletChangesUseCase
|
||||
|
|
@ -191,12 +190,7 @@ internal class MainViewModel @Inject constructor(
|
|||
userWalletsListManager.selectedUserWallet
|
||||
.distinctUntilChanged()
|
||||
.onEach { userWallet ->
|
||||
when (userWallet) {
|
||||
is UserWallet.Cold -> Analytics.setContext(userWallet.scanResponse)
|
||||
is UserWallet.Hot -> {
|
||||
// TODO [REDACTED_TASK_KEY]
|
||||
}
|
||||
}
|
||||
Analytics.setContext(userWallet)
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import com.tangem.domain.common.util.cardTypesResolver
|
|||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
|
||||
import com.tangem.domain.wallets.legacy.unlockIfLockable
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.tap.backupService
|
||||
import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
|
||||
import com.tangem.tap.common.extensions.*
|
||||
|
|
@ -95,7 +95,7 @@ internal class WelcomeMiddleware {
|
|||
}
|
||||
.doOnSuccess { selectedUserWallet ->
|
||||
sendSignedInAnalyticsEvent(
|
||||
scanResponse = selectedUserWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = selectedUserWallet,
|
||||
signInType = Basic.SignedIn.SignInType.Biometric,
|
||||
)
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ internal class WelcomeMiddleware {
|
|||
store.dispatchWithMain(WelcomeAction.ProceedWithCard.Error(error))
|
||||
}
|
||||
.doOnSuccess {
|
||||
sendSignedInAnalyticsEvent(scanResponse = scanResponse, signInType = Basic.SignedIn.SignInType.Card)
|
||||
sendSignedInAnalyticsEvent(userWallet, signInType = Basic.SignedIn.SignInType.Card)
|
||||
|
||||
store.dispatchNavigationAction { replaceAll(AppRoute.Wallet) }
|
||||
store.dispatchWithMain(WelcomeAction.ProceedWithCard.Success)
|
||||
|
|
@ -142,7 +142,14 @@ internal class WelcomeMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun sendSignedInAnalyticsEvent(scanResponse: ScanResponse, signInType: Basic.SignedIn.SignInType) {
|
||||
private fun sendSignedInAnalyticsEvent(userWallet: UserWallet, signInType: Basic.SignedIn.SignInType) {
|
||||
// TODO [REDACTED_TASK_KEY]
|
||||
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return
|
||||
}
|
||||
|
||||
val scanResponse = userWallet.scanResponse
|
||||
val currency = ParamCardCurrencyConverter().convert(
|
||||
value = scanResponse.cardTypesResolver,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,18 +4,17 @@ import com.tangem.common.extensions.toHexString
|
|||
import com.tangem.datasource.api.common.AuthProvider
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
|
||||
internal class DefaultAuthProvider(private val userWalletsListManager: UserWalletsListManager) : AuthProvider {
|
||||
|
||||
override fun getCardPublicKey(): String {
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync
|
||||
|
||||
return when (userWallet) {
|
||||
is UserWallet.Cold -> userWallet.scanResponse.card.cardPublicKey.toHexString()
|
||||
is UserWallet.Hot -> userWallet.wallets?.firstOrNull()?.publicKey?.toHexString() ?: ""
|
||||
null -> ""
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return userWallet.scanResponse.card.cardPublicKey.toHexString()
|
||||
}
|
||||
|
||||
override fun getCardId(): String {
|
||||
|
|
@ -25,7 +24,7 @@ internal class DefaultAuthProvider(private val userWalletsListManager: UserWalle
|
|||
return ""
|
||||
}
|
||||
|
||||
return userWallet.requireColdWallet().scanResponse.card.cardId
|
||||
return userWallet.scanResponse.card.cardId
|
||||
}
|
||||
|
||||
override fun getCardsPublicKeys(): Map<String, String> {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
|||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.domain.model.Currency
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
|
|
@ -25,10 +24,8 @@ internal class CryptoCurrencyConverter(
|
|||
cryptoCurrencyFactory.createCoin(
|
||||
blockchain = value.blockchain,
|
||||
extraDerivationPath = value.derivationPath,
|
||||
scanResponse = requireNotNull(
|
||||
store.inject(DaggerGraphState::generalUserWalletsListManager).selectedUserWalletSync
|
||||
?.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
?.scanResponse,
|
||||
userWallet = requireNotNull(
|
||||
store.inject(DaggerGraphState::generalUserWalletsListManager).selectedUserWalletSync,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -37,10 +34,8 @@ internal class CryptoCurrencyConverter(
|
|||
sdkToken = value.token,
|
||||
blockchain = value.blockchain,
|
||||
extraDerivationPath = value.derivationPath,
|
||||
scanResponse = requireNotNull(
|
||||
store.inject(DaggerGraphState::generalUserWalletsListManager).selectedUserWalletSync
|
||||
?.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
?.scanResponse,
|
||||
userWallet = requireNotNull(
|
||||
store.inject(DaggerGraphState::generalUserWalletsListManager).selectedUserWalletSync,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ internal class DefaultDerivationsRepositoryTest {
|
|||
runCatching {
|
||||
repository.derivePublicKeys(
|
||||
userWalletId = defaultUserWalletId,
|
||||
currencies = MockCryptoCurrencyFactory(userWallet.scanResponse).ethereum.let(::listOf),
|
||||
currencies = MockCryptoCurrencyFactory(userWallet).ethereum.let(::listOf),
|
||||
)
|
||||
}
|
||||
.onSuccess { Truth.assertThat(it) }
|
||||
|
|
@ -129,7 +129,7 @@ internal class DefaultDerivationsRepositoryTest {
|
|||
runCatching {
|
||||
repository.derivePublicKeys(
|
||||
userWalletId = defaultUserWalletId,
|
||||
currencies = MockCryptoCurrencyFactory(userWallet.scanResponse).ethereum.let(::listOf),
|
||||
currencies = MockCryptoCurrencyFactory(userWallet).ethereum.let(::listOf),
|
||||
)
|
||||
}
|
||||
.onSuccess { error("Should throws exception") }
|
||||
|
|
@ -155,7 +155,7 @@ internal class DefaultDerivationsRepositoryTest {
|
|||
runCatching {
|
||||
repository.derivePublicKeys(
|
||||
userWalletId = defaultUserWalletId,
|
||||
currencies = MockCryptoCurrencyFactory(userWallet.scanResponse).ethereum.let(::listOf),
|
||||
currencies = MockCryptoCurrencyFactory(userWallet).ethereum.let(::listOf),
|
||||
)
|
||||
}
|
||||
.onSuccess { Truth.assertThat(it) }
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.common.card.EllipticCurve
|
|||
import com.tangem.common.extensions.ByteArrayKey
|
||||
import com.tangem.common.test.domain.card.MockScanResponseFactory
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.common.test.domain.wallet.MockUserWalletFactory
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.domain.common.configs.GenericCardConfig
|
||||
import com.tangem.domain.common.configs.MultiWalletCardConfig
|
||||
|
|
@ -34,9 +35,10 @@ internal class MissedDerivationsFinderTest {
|
|||
fun `empty derivations for non supported blockchains`() {
|
||||
// Bls is not supported
|
||||
val scanResponse = MockScanResponseFactory.create(cardConfig = GenericCardConfig(2), derivedKeys = emptyMap())
|
||||
val userWallet = MockUserWalletFactory.create(scanResponse)
|
||||
val finder = MissedDerivationsFinder(scanResponse)
|
||||
|
||||
val currencies = MockCryptoCurrencyFactory(scanResponse).chia.let(::listOf)
|
||||
val currencies = MockCryptoCurrencyFactory(userWallet).chia.let(::listOf)
|
||||
val actual = finder.find(currencies)
|
||||
|
||||
Truth.assertThat(actual).isEmpty()
|
||||
|
|
@ -55,9 +57,10 @@ internal class MissedDerivationsFinderTest {
|
|||
),
|
||||
)
|
||||
}
|
||||
val userWallet = MockUserWalletFactory.create(scanResponse)
|
||||
val finder = MissedDerivationsFinder(scanResponse)
|
||||
|
||||
val currencies = MockCryptoCurrencyFactory(scanResponse).chiaAndEthereum
|
||||
val currencies = MockCryptoCurrencyFactory(userWallet).chiaAndEthereum
|
||||
val actual = finder.find(currencies)
|
||||
|
||||
Truth.assertThat(actual).containsExactly(
|
||||
|
|
@ -69,9 +72,10 @@ internal class MissedDerivationsFinderTest {
|
|||
@Test
|
||||
fun `derivations for custom token`() {
|
||||
val scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap())
|
||||
val userWallet = MockUserWalletFactory.create(scanResponse)
|
||||
val finder = MissedDerivationsFinder(scanResponse)
|
||||
|
||||
val currencies = MockCryptoCurrencyFactory(scanResponse).ethereumTokenWithBinanceDerivation
|
||||
val currencies = MockCryptoCurrencyFactory(userWallet).ethereumTokenWithBinanceDerivation
|
||||
val actual = finder.find(currencies)
|
||||
|
||||
Truth.assertThat(actual).containsExactly(
|
||||
|
|
@ -86,9 +90,10 @@ internal class MissedDerivationsFinderTest {
|
|||
@Test
|
||||
fun `derivations for cardano`() {
|
||||
val scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap())
|
||||
val userWallet = MockUserWalletFactory.create(scanResponse)
|
||||
val finder = MissedDerivationsFinder(scanResponse)
|
||||
|
||||
val currencies = MockCryptoCurrencyFactory(scanResponse).cardano.let(::listOf)
|
||||
val currencies = MockCryptoCurrencyFactory(userWallet).cardano.let(::listOf)
|
||||
val actual = finder.find(currencies)
|
||||
|
||||
Truth.assertThat(actual).containsExactly(
|
||||
|
|
@ -111,9 +116,10 @@ internal class MissedDerivationsFinderTest {
|
|||
cardConfig = Wallet2CardConfig,
|
||||
derivedKeys = DerivedKeysMocks.ethereumDerivedKeys,
|
||||
)
|
||||
val userWallet = MockUserWalletFactory.create(scanResponse)
|
||||
val finder = MissedDerivationsFinder(scanResponse)
|
||||
|
||||
val currencies = MockCryptoCurrencyFactory(scanResponse).ethereum.let(::listOf)
|
||||
val currencies = MockCryptoCurrencyFactory(userWallet).ethereum.let(::listOf)
|
||||
val actual = finder.find(currencies)
|
||||
|
||||
Truth.assertThat(actual).isEmpty()
|
||||
|
|
@ -125,9 +131,10 @@ internal class MissedDerivationsFinderTest {
|
|||
cardConfig = MultiWalletCardConfig,
|
||||
derivedKeys = DerivedKeysMocks.ethereumDerivedKeys,
|
||||
)
|
||||
val userWallet = MockUserWalletFactory.create(scanResponse)
|
||||
val finder = MissedDerivationsFinder(scanResponse)
|
||||
|
||||
val currencies = MockCryptoCurrencyFactory(scanResponse).ethereumAndStellar
|
||||
val currencies = MockCryptoCurrencyFactory(userWallet).ethereumAndStellar
|
||||
val actual = finder.find(currencies)
|
||||
|
||||
Truth.assertThat(actual).containsExactly(
|
||||
|
|
|
|||
|
|
@ -6,18 +6,19 @@ import com.tangem.blockchain.common.Token
|
|||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
import com.tangem.common.test.domain.card.MockScanResponseFactory
|
||||
import com.tangem.common.test.domain.wallet.MockUserWalletFactory
|
||||
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
||||
import com.tangem.domain.common.DerivationStyleProvider
|
||||
import com.tangem.domain.common.configs.GenericCardConfig
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class MockCryptoCurrencyFactory(private val scanResponse: ScanResponse = defaultScanResponse) {
|
||||
class MockCryptoCurrencyFactory(private val userWallet: UserWallet.Cold = defaultUserWallet) {
|
||||
|
||||
private val factory = CryptoCurrencyFactory(excludedBlockchains = ExcludedBlockchains())
|
||||
|
||||
|
|
@ -49,7 +50,7 @@ class MockCryptoCurrencyFactory(private val scanResponse: ScanResponse = default
|
|||
val derivationPath = createDerivationPath(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
cardDerivationStyleProvider = scanResponse.derivationStyleProvider,
|
||||
cardDerivationStyleProvider = userWallet.scanResponse.derivationStyleProvider,
|
||||
)
|
||||
|
||||
val network = Network(
|
||||
|
|
@ -72,7 +73,7 @@ class MockCryptoCurrencyFactory(private val scanResponse: ScanResponse = default
|
|||
fun createCustomToken(blockchain: Blockchain, derivationBlockchain: Blockchain): CryptoCurrency {
|
||||
val derivationPath = Network.DerivationPath.Custom(
|
||||
value = derivationBlockchain.derivationPath(
|
||||
scanResponse.derivationStyleProvider.getDerivationStyle(),
|
||||
userWallet.scanResponse.derivationStyleProvider.getDerivationStyle(),
|
||||
)!!.rawPath,
|
||||
)
|
||||
|
||||
|
|
@ -114,7 +115,7 @@ class MockCryptoCurrencyFactory(private val scanResponse: ScanResponse = default
|
|||
),
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)!!
|
||||
}
|
||||
|
||||
|
|
@ -161,9 +162,11 @@ class MockCryptoCurrencyFactory(private val scanResponse: ScanResponse = default
|
|||
|
||||
private companion object {
|
||||
|
||||
val defaultScanResponse = MockScanResponseFactory.create(
|
||||
cardConfig = GenericCardConfig(2),
|
||||
derivedKeys = emptyMap(),
|
||||
val defaultUserWallet = MockUserWalletFactory.create(
|
||||
scanResponse = MockScanResponseFactory.create(
|
||||
cardConfig = GenericCardConfig(2),
|
||||
derivedKeys = emptyMap(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@ package com.tangem.data.common.currency
|
|||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
|
|
@ -57,23 +56,23 @@ interface CardCryptoCurrencyFactory {
|
|||
/**
|
||||
* Create default coins for multi currency card
|
||||
*
|
||||
* @param scanResponse scan response
|
||||
* @param userWallet user wallet
|
||||
*/
|
||||
fun createDefaultCoinsForMultiCurrencyCard(scanResponse: ScanResponse): List<CryptoCurrency.Coin>
|
||||
fun createDefaultCoinsForMultiCurrencyWallet(userWallet: UserWallet): List<CryptoCurrency.Coin>
|
||||
|
||||
/**
|
||||
* Create primary currency for single currency card
|
||||
*
|
||||
* @param scanResponse scan response
|
||||
* @param userWallet user wallet
|
||||
*/
|
||||
@Throws
|
||||
fun createPrimaryCurrencyForSingleCurrencyCard(scanResponse: ScanResponse): CryptoCurrency
|
||||
fun createPrimaryCurrencyForSingleCurrencyCard(userWallet: UserWallet.Cold): CryptoCurrency
|
||||
|
||||
/**
|
||||
* Create currencies for single currency card with token (like, NODL)
|
||||
*
|
||||
* @param scanResponse scan response
|
||||
* @param userWallet user wallet
|
||||
*/
|
||||
@Throws
|
||||
fun createCurrenciesForSingleCurrencyCardWithToken(scanResponse: ScanResponse): List<CryptoCurrency>
|
||||
fun createCurrenciesForSingleCurrencyCardWithToken(userWallet: UserWallet.Cold): List<CryptoCurrency>
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import com.tangem.blockchainsdk.utils.toCoinId
|
|||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import timber.log.Timber
|
||||
import com.tangem.blockchain.common.Token as SdkToken
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ class CryptoCurrencyFactory(
|
|||
sdkToken: SdkToken,
|
||||
blockchain: Blockchain,
|
||||
extraDerivationPath: String?,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
): CryptoCurrency.Token? {
|
||||
if (blockchain == Blockchain.Unknown) {
|
||||
Timber.e("Unable to map the SDK token to the domain token with Unknown blockchain")
|
||||
|
|
@ -56,7 +56,7 @@ class CryptoCurrencyFactory(
|
|||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
|
||||
val id = getTokenId(network, sdkToken)
|
||||
|
|
@ -76,7 +76,7 @@ class CryptoCurrencyFactory(
|
|||
fun createCoin(
|
||||
blockchain: Blockchain,
|
||||
extraDerivationPath: String?,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
): CryptoCurrency.Coin? {
|
||||
if (blockchain == Blockchain.Unknown) {
|
||||
Timber.e("Unable to map the SDK token to the domain token with Unknown blockchain")
|
||||
|
|
@ -86,15 +86,15 @@ class CryptoCurrencyFactory(
|
|||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
|
||||
return createCoin(network)
|
||||
}
|
||||
|
||||
fun createCoin(networkId: String, extraDerivationPath: String?, scanResponse: ScanResponse): CryptoCurrency.Coin? {
|
||||
fun createCoin(networkId: String, extraDerivationPath: String?, userWallet: UserWallet): CryptoCurrency.Coin? {
|
||||
val blockchain = Blockchain.fromNetworkId(networkId) ?: Blockchain.Unknown
|
||||
return createCoin(blockchain, extraDerivationPath, scanResponse)
|
||||
return createCoin(blockchain, extraDerivationPath, userWallet)
|
||||
}
|
||||
|
||||
fun createCoin(network: Network): CryptoCurrency.Coin {
|
||||
|
|
@ -115,7 +115,7 @@ class CryptoCurrencyFactory(
|
|||
token: Token,
|
||||
networkId: String,
|
||||
extraDerivationPath: String?,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
): CryptoCurrency.Token? {
|
||||
val sdkToken = SdkToken(
|
||||
name = token.name,
|
||||
|
|
@ -129,7 +129,7 @@ class CryptoCurrencyFactory(
|
|||
sdkToken = sdkToken,
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,8 @@ class CryptoCurrencyFactory(
|
|||
decimals = cryptoCurrency.decimals,
|
||||
id = cryptoCurrency.id.rawCurrencyId?.value,
|
||||
)
|
||||
val blockchain = Blockchain.fromNetworkId(cryptoCurrency.network.backendId) ?: Blockchain.Unknown
|
||||
val blockchain =
|
||||
Blockchain.fromNetworkId(cryptoCurrency.network.backendId) ?: Blockchain.Unknown
|
||||
val id = getTokenId(network, sdkToken)
|
||||
return CryptoCurrency.Token(
|
||||
id = id,
|
||||
|
|
|
|||
|
|
@ -11,11 +11,9 @@ import com.tangem.domain.common.util.cardTypesResolver
|
|||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
|
||||
/**
|
||||
* Default implementation of factory for creating list of [CryptoCurrency] for selected card
|
||||
|
|
@ -54,12 +52,12 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
|
||||
// single-currency wallet with token (NODL)
|
||||
if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
val currencies = createCurrenciesForSingleCurrencyCardWithToken(userWallet.scanResponse)
|
||||
val currencies = createCurrenciesForSingleCurrencyCardWithToken(userWallet)
|
||||
return mapOf(cardNetwork to currencies)
|
||||
}
|
||||
|
||||
// single-currency wallet
|
||||
val primaryCurrency = createPrimaryCurrencyForSingleCurrencyCard(userWallet.scanResponse)
|
||||
val primaryCurrency = createPrimaryCurrencyForSingleCurrencyCard(userWallet)
|
||||
return mapOf(cardNetwork to listOf(primaryCurrency))
|
||||
}
|
||||
|
||||
|
|
@ -82,11 +80,11 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
|
||||
// single-currency wallet with token (NODL)
|
||||
if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
return createCurrenciesForSingleCurrencyCardWithToken(userWallet.scanResponse)
|
||||
return createCurrenciesForSingleCurrencyCardWithToken(userWallet)
|
||||
}
|
||||
|
||||
// single-currency wallet
|
||||
return createPrimaryCurrencyForSingleCurrencyCard(userWallet.scanResponse).let(::listOf)
|
||||
return createPrimaryCurrencyForSingleCurrencyCard(userWallet).let(::listOf)
|
||||
}
|
||||
|
||||
override suspend fun createCurrenciesForMultiCurrencyCard(
|
||||
|
|
@ -98,44 +96,54 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
return getMultiWalletCurrencies(userWallet = userWallet, networks = networks)
|
||||
}
|
||||
|
||||
override fun createDefaultCoinsForMultiCurrencyCard(scanResponse: ScanResponse): List<CryptoCurrency.Coin> {
|
||||
require(scanResponse.cardTypesResolver.isMultiwalletAllowed()) { "It isn't multi-currency wallet" }
|
||||
override fun createDefaultCoinsForMultiCurrencyWallet(userWallet: UserWallet): List<CryptoCurrency.Coin> {
|
||||
require(userWallet.isMultiCurrency) { "It isn't multi-currency wallet" }
|
||||
|
||||
val card = scanResponse.card
|
||||
val blockchains = when (userWallet) {
|
||||
is UserWallet.Cold -> {
|
||||
val card = userWallet.scanResponse.card
|
||||
|
||||
var blockchains = if (demoConfig.isDemoCardId(card.cardId)) {
|
||||
demoConfig.demoBlockchains
|
||||
} else {
|
||||
listOf(Blockchain.Bitcoin, Blockchain.Ethereum)
|
||||
}
|
||||
var blockchainsInternal = if (demoConfig.isDemoCardId(card.cardId)) {
|
||||
demoConfig.demoBlockchains
|
||||
} else {
|
||||
listOf(Blockchain.Bitcoin, Blockchain.Ethereum)
|
||||
}
|
||||
|
||||
if (card.isTestCard) {
|
||||
blockchains = blockchains.mapNotNull { it.getTestnetVersion() }
|
||||
if (card.isTestCard) {
|
||||
blockchainsInternal = blockchainsInternal.mapNotNull { it.getTestnetVersion() }
|
||||
}
|
||||
|
||||
blockchainsInternal
|
||||
}
|
||||
|
||||
is UserWallet.Hot -> listOf(Blockchain.Bitcoin, Blockchain.Ethereum)
|
||||
}
|
||||
|
||||
return blockchains.mapNotNull {
|
||||
cryptoCurrencyFactory.createCoin(
|
||||
blockchain = it,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createPrimaryCurrencyForSingleCurrencyCard(scanResponse: ScanResponse): CryptoCurrency {
|
||||
require(scanResponse.cardTypesResolver.isSingleWallet()) { "It isn't single-currency wallet" }
|
||||
override fun createPrimaryCurrencyForSingleCurrencyCard(userWallet: UserWallet.Cold): CryptoCurrency {
|
||||
require(userWallet.scanResponse.cardTypesResolver.isSingleWallet()) {
|
||||
"It isn't single-currency wallet"
|
||||
}
|
||||
|
||||
return with(getSingleWalletCurrencies(scanResponse)) {
|
||||
return with(getSingleWalletCurrencies(userWallet)) {
|
||||
primaryToken ?: coin
|
||||
}
|
||||
}
|
||||
|
||||
override fun createCurrenciesForSingleCurrencyCardWithToken(scanResponse: ScanResponse): List<CryptoCurrency> {
|
||||
require(scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
override fun createCurrenciesForSingleCurrencyCardWithToken(userWallet: UserWallet.Cold): List<CryptoCurrency> {
|
||||
require(userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
"It isn't single-currency wallet with token"
|
||||
}
|
||||
|
||||
return with(getSingleWalletCurrencies(scanResponse)) {
|
||||
return with(getSingleWalletCurrencies(userWallet)) {
|
||||
listOfNotNull(coin, primaryToken)
|
||||
}
|
||||
}
|
||||
|
|
@ -151,7 +159,7 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
tokens = response.tokens.filter { token ->
|
||||
networks.any { it.backendId == token.networkId && it.derivationPath.value == token.derivationPath }
|
||||
},
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
.groupBy(CryptoCurrency::network)
|
||||
|
||||
|
|
@ -169,19 +177,19 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
|
||||
return responseCryptoCurrenciesFactory.createCurrencies(
|
||||
tokens = response.tokens.filter { token -> token.networkId in networkIds },
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
.groupBy { it.network.id.rawId }
|
||||
}
|
||||
|
||||
private fun getSingleWalletCurrencies(scanResponse: ScanResponse): SingleWalletCurrencies {
|
||||
val resolver = scanResponse.cardTypesResolver
|
||||
private fun getSingleWalletCurrencies(userWallet: UserWallet.Cold): SingleWalletCurrencies {
|
||||
val resolver = userWallet.cardTypesResolver
|
||||
val blockchain = resolver.getBlockchain()
|
||||
|
||||
val coin = cryptoCurrencyFactory.createCoin(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
|
||||
requireNotNull(coin) { "Coin for the single currency card cannot be null" }
|
||||
|
|
@ -191,12 +199,15 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
sdkToken = token,
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
return SingleWalletCurrencies(coin = coin, primaryToken = primaryToken)
|
||||
}
|
||||
|
||||
private data class SingleWalletCurrencies(val coin: CryptoCurrency, val primaryToken: CryptoCurrency?)
|
||||
private data class SingleWalletCurrencies(
|
||||
val coin: CryptoCurrency,
|
||||
val primaryToken: CryptoCurrency?,
|
||||
)
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import com.tangem.data.common.network.NetworkFactory
|
|||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import com.tangem.blockchain.common.Token as SdkToken
|
||||
|
|
@ -17,41 +17,41 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
|
|||
private val networkFactory: NetworkFactory,
|
||||
) {
|
||||
|
||||
fun createCurrency(currencyId: String, response: UserTokensResponse, scanResponse: ScanResponse): CryptoCurrency {
|
||||
fun createCurrency(currencyId: String, response: UserTokensResponse, userWallet: UserWallet): CryptoCurrency {
|
||||
return response.tokens
|
||||
.asSequence()
|
||||
.mapNotNull { createCurrency(it, scanResponse) }
|
||||
.mapNotNull { createCurrency(it, userWallet) }
|
||||
.first { it.id.value == currencyId }
|
||||
}
|
||||
|
||||
fun createCurrencies(response: UserTokensResponse, scanResponse: ScanResponse): List<CryptoCurrency> {
|
||||
return createCurrencies(tokens = response.tokens, scanResponse = scanResponse)
|
||||
fun createCurrencies(response: UserTokensResponse, userWallet: UserWallet): List<CryptoCurrency> {
|
||||
return createCurrencies(tokens = response.tokens, userWallet = userWallet)
|
||||
}
|
||||
|
||||
fun createCurrencies(tokens: List<UserTokensResponse.Token>, scanResponse: ScanResponse): List<CryptoCurrency> {
|
||||
fun createCurrencies(tokens: List<UserTokensResponse.Token>, userWallet: UserWallet): List<CryptoCurrency> {
|
||||
return tokens
|
||||
.asSequence()
|
||||
.mapNotNull { createCurrency(it, scanResponse) }
|
||||
.mapNotNull { createCurrency(it, userWallet) }
|
||||
.distinctBy(CryptoCurrency::id)
|
||||
.toList()
|
||||
}
|
||||
|
||||
fun createCurrency(responseToken: UserTokensResponse.Token, scanResponse: ScanResponse): CryptoCurrency? {
|
||||
fun createCurrency(responseToken: UserTokensResponse.Token, userWallet: UserWallet): CryptoCurrency? {
|
||||
var blockchain = Blockchain.fromNetworkId(responseToken.networkId)
|
||||
if (blockchain == null || blockchain == Blockchain.Unknown) {
|
||||
Timber.e("Unable to find a blockchain with the network ID: ${responseToken.networkId}")
|
||||
return null
|
||||
}
|
||||
|
||||
if (scanResponse.cardTypesResolver.isTestCard()) {
|
||||
if (userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isTestCard()) {
|
||||
blockchain = blockchain.getTestnetVersion() ?: blockchain
|
||||
}
|
||||
|
||||
val sdkToken = createSdkToken(responseToken)
|
||||
return if (sdkToken == null) {
|
||||
createCoin(blockchain, responseToken, scanResponse)
|
||||
createCoin(blockchain, responseToken, userWallet)
|
||||
} else {
|
||||
createToken(blockchain, sdkToken, responseToken.derivationPath, scanResponse)
|
||||
createToken(blockchain, sdkToken, responseToken.derivationPath, userWallet)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,12 +70,12 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
|
|||
private fun createCoin(
|
||||
blockchain: Blockchain,
|
||||
responseToken: UserTokensResponse.Token,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
): CryptoCurrency.Coin? {
|
||||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = responseToken.derivationPath,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
|
||||
return CryptoCurrency.Coin(
|
||||
|
|
@ -105,12 +105,12 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
|
|||
blockchain: Blockchain,
|
||||
sdkToken: Token,
|
||||
responseDerivationPath: String?,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
): CryptoCurrency.Token? {
|
||||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = responseDerivationPath,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
|
||||
val id = getTokenId(network, sdkToken)
|
||||
|
|
|
|||
|
|
@ -8,10 +8,9 @@ import com.tangem.blockchainsdk.utils.toBlockchain
|
|||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
import com.tangem.domain.common.DerivationStyleProvider
|
||||
import com.tangem.domain.common.extensions.canHandleToken
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -31,19 +30,18 @@ class NetworkFactory @Inject constructor(
|
|||
*
|
||||
* @param blockchain blockchain
|
||||
* @param extraDerivationPath extra derivation path
|
||||
* @param scanResponse scan response
|
||||
* @param userWallet user wallet
|
||||
*/
|
||||
fun create(blockchain: Blockchain, extraDerivationPath: String?, scanResponse: ScanResponse): Network? {
|
||||
fun create(blockchain: Blockchain, extraDerivationPath: String?, userWallet: UserWallet): Network? {
|
||||
return create(
|
||||
blockchain = blockchain,
|
||||
derivationPath = createDerivationPath(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
cardDerivationStyleProvider = scanResponse.derivationStyleProvider,
|
||||
cardDerivationStyleProvider = userWallet.derivationStyleProvider,
|
||||
),
|
||||
canHandleTokens = scanResponse.card.canHandleToken(
|
||||
canHandleTokens = userWallet.canHandleToken(
|
||||
blockchain = blockchain,
|
||||
cardTypesResolver = scanResponse.cardTypesResolver,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
),
|
||||
)
|
||||
|
|
@ -54,17 +52,16 @@ class NetworkFactory @Inject constructor(
|
|||
*
|
||||
* @param networkId network id
|
||||
* @param derivationPath derivation path
|
||||
* @param scanResponse scan response
|
||||
* @param userWallet user wallet
|
||||
*/
|
||||
fun create(networkId: Network.ID, derivationPath: Network.DerivationPath, scanResponse: ScanResponse): Network? {
|
||||
fun create(networkId: Network.ID, derivationPath: Network.DerivationPath, userWallet: UserWallet): Network? {
|
||||
val blockchain = networkId.toBlockchain()
|
||||
|
||||
return create(
|
||||
blockchain = blockchain,
|
||||
derivationPath = derivationPath,
|
||||
canHandleTokens = scanResponse.card.canHandleToken(
|
||||
canHandleTokens = userWallet.canHandleToken(
|
||||
blockchain = blockchain,
|
||||
cardTypesResolver = scanResponse.cardTypesResolver,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
val multiWallet = model.multiWallet
|
||||
|
||||
// Act
|
||||
val actual = factory.createDefaultCoinsForMultiCurrencyCard(scanResponse = multiWallet.scanResponse)
|
||||
val actual = factory.createDefaultCoinsForMultiCurrencyWallet(multiWallet)
|
||||
|
||||
// Assert
|
||||
val expected = model.expected
|
||||
|
|
@ -355,7 +355,7 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
|
||||
// Act
|
||||
val actual = runCatching {
|
||||
factory.createPrimaryCurrencyForSingleCurrencyCard(scanResponse = singleWallet.scanResponse)
|
||||
factory.createPrimaryCurrencyForSingleCurrencyCard(singleWallet)
|
||||
}
|
||||
|
||||
// Assert
|
||||
|
|
@ -405,7 +405,7 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
|
||||
// Act
|
||||
val actual = runCatching {
|
||||
factory.createCurrenciesForSingleCurrencyCardWithToken(scanResponse = userWallet.scanResponse)
|
||||
factory.createCurrenciesForSingleCurrencyCardWithToken(userWallet)
|
||||
}
|
||||
|
||||
// Assert
|
||||
|
|
@ -554,7 +554,7 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
sdkToken = userWallet.scanResponse.cardTypesResolver.getPrimaryToken()!!,
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)!!
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.common.test.domain.card.MockScanResponseFactory
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.common.test.domain.wallet.MockUserWalletFactory
|
||||
import com.tangem.common.test.utils.ProvideTestModels
|
||||
import com.tangem.domain.common.DerivationStyleProvider
|
||||
import com.tangem.domain.common.configs.GenericCardConfig
|
||||
|
|
@ -12,6 +13,7 @@ import com.tangem.domain.common.configs.MultiWalletCardConfig
|
|||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import org.junit.jupiter.api.Nested
|
||||
|
|
@ -43,7 +45,7 @@ class NetworkFactoryTest {
|
|||
val actual = networkFactory.create(
|
||||
blockchain = Blockchain.Ethereum,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = createMultiWalletScanResponse(),
|
||||
userWallet = createUserWallet(),
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -59,14 +61,14 @@ class NetworkFactoryTest {
|
|||
networkFactory.create(
|
||||
blockchain = model.blockchain,
|
||||
extraDerivationPath = model.extraDerivationPath,
|
||||
scanResponse = model.scanResponse,
|
||||
userWallet = model.userWallet,
|
||||
)
|
||||
}
|
||||
is CreateTestModel.Second -> {
|
||||
networkFactory.create(
|
||||
networkId = model.networkId,
|
||||
derivationPath = model.derivationPath,
|
||||
scanResponse = model.scanResponse,
|
||||
userWallet = model.userWallet,
|
||||
)
|
||||
}
|
||||
is CreateTestModel.Third -> {
|
||||
|
|
@ -89,27 +91,27 @@ class NetworkFactoryTest {
|
|||
CreateTestModel.First(
|
||||
blockchain = Blockchain.Unknown,
|
||||
extraDerivationPath = null, // never-mind
|
||||
scanResponse = createMultiWalletScanResponse(), // never-mind
|
||||
userWallet = createUserWallet(),
|
||||
expected = null,
|
||||
),
|
||||
createFirst(
|
||||
extraDerivationPath = null,
|
||||
scanResponse = createGenericScanResponse(), // default derivation path is null
|
||||
userWallet = createUserWallet(createGenericScanResponse()), // default derivation path is null
|
||||
expectedDerivationPath = Network.DerivationPath.None,
|
||||
),
|
||||
createFirst(
|
||||
extraDerivationPath = null,
|
||||
scanResponse = createMultiWalletScanResponse(),
|
||||
userWallet = createUserWallet(),
|
||||
expectedDerivationPath = Network.DerivationPath.Card(value = "m/44'/60'/0'/0/0"), // use default
|
||||
),
|
||||
createFirst(
|
||||
extraDerivationPath = "m/44'/60'/0'/0/0", // as default
|
||||
scanResponse = createMultiWalletScanResponse(),
|
||||
userWallet = createUserWallet(),
|
||||
expectedDerivationPath = Network.DerivationPath.Card(value = "m/44'/60'/0'/0/0"),
|
||||
),
|
||||
createFirst(
|
||||
extraDerivationPath = "m/84'/0'/0'/0/0",
|
||||
scanResponse = createMultiWalletScanResponse(),
|
||||
userWallet = createUserWallet(),
|
||||
expectedDerivationPath = Network.DerivationPath.Custom(value = "m/84'/0'/0'/0/0"),
|
||||
),
|
||||
// endregion
|
||||
|
|
@ -118,23 +120,23 @@ class NetworkFactoryTest {
|
|||
CreateTestModel.Second(
|
||||
networkId = Network.ID(value = "1", derivationPath = Network.DerivationPath.None),
|
||||
derivationPath = Network.DerivationPath.None, // never-mind
|
||||
scanResponse = createMultiWalletScanResponse(), // never-mind
|
||||
userWallet = createUserWallet(), // never-mind
|
||||
expected = null,
|
||||
),
|
||||
createSecond(
|
||||
scanResponse = createGenericScanResponse(), // default derivation path is null
|
||||
userWallet = createUserWallet(createGenericScanResponse()), // default derivation path is null
|
||||
derivationPath = Network.DerivationPath.None,
|
||||
),
|
||||
createSecond(
|
||||
scanResponse = createMultiWalletScanResponse(),
|
||||
userWallet = createUserWallet(),
|
||||
derivationPath = Network.DerivationPath.None,
|
||||
),
|
||||
createSecond(
|
||||
scanResponse = createMultiWalletScanResponse(),
|
||||
userWallet = createUserWallet(),
|
||||
derivationPath = Network.DerivationPath.Card(value = "m/44'/60'/0'/0/0"),
|
||||
),
|
||||
createSecond(
|
||||
scanResponse = createMultiWalletScanResponse(),
|
||||
userWallet = createUserWallet(),
|
||||
derivationPath = Network.DerivationPath.Custom(value = "m/84'/0'/0'/0/0"),
|
||||
),
|
||||
// endregion
|
||||
|
|
@ -176,13 +178,13 @@ class NetworkFactoryTest {
|
|||
|
||||
private fun createFirst(
|
||||
extraDerivationPath: String?,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
expectedDerivationPath: Network.DerivationPath,
|
||||
): CreateTestModel.First {
|
||||
return CreateTestModel.First(
|
||||
blockchain = Blockchain.Ethereum,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
expected = MockCryptoCurrencyFactory().ethereum.network.copy(
|
||||
id = Network.ID(
|
||||
value = Blockchain.Ethereum.id,
|
||||
|
|
@ -195,13 +197,13 @@ class NetworkFactoryTest {
|
|||
}
|
||||
|
||||
private fun createSecond(
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CreateTestModel.Second {
|
||||
return CreateTestModel.Second(
|
||||
networkId = Network.ID(value = Blockchain.Ethereum.id, derivationPath = derivationPath),
|
||||
derivationPath = derivationPath,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
expected = MockCryptoCurrencyFactory().ethereum.network.copy(
|
||||
id = Network.ID(
|
||||
value = Blockchain.Ethereum.id,
|
||||
|
|
@ -232,6 +234,10 @@ class NetworkFactoryTest {
|
|||
)
|
||||
}
|
||||
|
||||
private fun createUserWallet(scanResponse: ScanResponse = createMultiWalletScanResponse()): UserWallet.Cold {
|
||||
return MockUserWalletFactory.create(scanResponse)
|
||||
}
|
||||
|
||||
private fun createMultiWalletScanResponse(): ScanResponse {
|
||||
return MockScanResponseFactory.create(
|
||||
cardConfig = MultiWalletCardConfig,
|
||||
|
|
@ -254,14 +260,14 @@ class NetworkFactoryTest {
|
|||
data class First(
|
||||
val blockchain: Blockchain,
|
||||
val extraDerivationPath: String?,
|
||||
val scanResponse: ScanResponse,
|
||||
val userWallet: UserWallet,
|
||||
override val expected: Network?,
|
||||
) : CreateTestModel
|
||||
|
||||
data class Second(
|
||||
val networkId: Network.ID,
|
||||
val derivationPath: Network.DerivationPath,
|
||||
val scanResponse: ScanResponse,
|
||||
val userWallet: UserWallet,
|
||||
override val expected: Network?,
|
||||
) : CreateTestModel
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ internal class DefaultCustomTokensRepository(
|
|||
networkFactory.create(
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
),
|
||||
) {
|
||||
"Network [$networkId] not found while finding token"
|
||||
|
|
@ -106,8 +106,8 @@ internal class DefaultCustomTokensRepository(
|
|||
symbol = null,
|
||||
)
|
||||
|
||||
val supportedTokenNetworkIds = userWallet.scanResponse.card
|
||||
.supportedBlockchains(userWallet.scanResponse.cardTypesResolver, excludedBlockchains)
|
||||
val supportedTokenNetworkIds = userWallet
|
||||
.supportedBlockchains(excludedBlockchains = excludedBlockchains)
|
||||
.filter(Blockchain::canHandleTokens)
|
||||
.map(Blockchain::toNetworkId)
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ internal class DefaultCustomTokensRepository(
|
|||
networkFactory.create(
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
),
|
||||
) {
|
||||
"Network [$networkId] not found while creating coin"
|
||||
|
|
@ -188,7 +188,7 @@ internal class DefaultCustomTokensRepository(
|
|||
networkFactory.create(
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
),
|
||||
) {
|
||||
"Network [$networkId] not found while creating custom token"
|
||||
|
|
@ -261,7 +261,7 @@ internal class DefaultCustomTokensRepository(
|
|||
networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
|||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.pagination.BatchFetchResult
|
||||
import com.tangem.pagination.BatchListSource
|
||||
import com.tangem.pagination.fetcher.LimitOffsetBatchFetcher
|
||||
|
|
@ -142,13 +141,13 @@ internal class DefaultManageTokensRepository(
|
|||
managedCryptoCurrencyFactory.createWithCustomTokens(
|
||||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} else {
|
||||
managedCryptoCurrencyFactory.create(
|
||||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
scanResponse = userWallet?.requireColdWallet()?.scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +177,7 @@ internal class DefaultManageTokensRepository(
|
|||
testnetTokensConfig
|
||||
},
|
||||
tokensResponse = getSavedUserTokensResponseSync(userWallet.walletId),
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
|
||||
return BatchFetchResult.Success(
|
||||
|
|
@ -190,8 +189,8 @@ internal class DefaultManageTokensRepository(
|
|||
|
||||
private fun createDefaultUserTokensResponse(userWallet: UserWallet) =
|
||||
userTokensResponseFactory.createUserTokensResponse(
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(
|
||||
userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(
|
||||
userWallet = userWallet,
|
||||
),
|
||||
isGroupedByNetwork = false,
|
||||
isSortedByBalance = false,
|
||||
|
|
|
|||
|
|
@ -15,13 +15,12 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
|||
import com.tangem.datasource.local.config.testnet.models.TestnetTokensConfig
|
||||
import com.tangem.domain.common.DerivationStyleProvider
|
||||
import com.tangem.domain.common.extensions.canHandleToken
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
|
||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency.SourceNetwork
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import timber.log.Timber
|
||||
|
||||
internal class ManagedCryptoCurrencyFactory(
|
||||
|
|
@ -32,20 +31,20 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
fun create(
|
||||
coinsResponse: CoinsResponse,
|
||||
tokensResponse: UserTokensResponse?,
|
||||
scanResponse: ScanResponse?,
|
||||
userWallet: UserWallet?,
|
||||
): List<ManagedCryptoCurrency> {
|
||||
return coinsResponse.coins.mapNotNull { coin ->
|
||||
createToken(coin, tokensResponse, coinsResponse.imageHost, scanResponse)
|
||||
createToken(coin, tokensResponse, coinsResponse.imageHost, userWallet)
|
||||
}
|
||||
}
|
||||
|
||||
fun createWithCustomTokens(
|
||||
coinsResponse: CoinsResponse,
|
||||
tokensResponse: UserTokensResponse,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
): List<ManagedCryptoCurrency> {
|
||||
val customTokens = createCustomTokens(tokensResponse, scanResponse)
|
||||
val tokens = create(coinsResponse, tokensResponse, scanResponse)
|
||||
val customTokens = createCustomTokens(tokensResponse, userWallet)
|
||||
val tokens = create(coinsResponse, tokensResponse, userWallet)
|
||||
|
||||
return customTokens + tokens
|
||||
}
|
||||
|
|
@ -53,10 +52,10 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
fun createTestnetWithCustomTokens(
|
||||
testnetTokensConfig: TestnetTokensConfig,
|
||||
tokensResponse: UserTokensResponse?,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
): List<ManagedCryptoCurrency> {
|
||||
val customTokens = tokensResponse
|
||||
?.let { createCustomTokens(it, scanResponse) }
|
||||
?.let { createCustomTokens(it, userWallet) }
|
||||
?: emptyList()
|
||||
val testnetTokens = testnetTokensConfig.tokens.map { testnetToken ->
|
||||
ManagedCryptoCurrency.Token(
|
||||
|
|
@ -69,10 +68,10 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
networkId = network.id,
|
||||
contractAddress = network.address,
|
||||
decimals = network.decimalCount,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} ?: emptyList(),
|
||||
addedIn = findAddedInNetworks(testnetToken.id, tokensResponse, scanResponse),
|
||||
addedIn = findAddedInNetworks(testnetToken.id, tokensResponse, userWallet),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -81,28 +80,28 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
|
||||
private fun createCustomTokens(
|
||||
tokensResponse: UserTokensResponse,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
): List<ManagedCryptoCurrency> = tokensResponse.tokens
|
||||
.mapNotNull { token ->
|
||||
maybeCreateCustomToken(token, scanResponse)
|
||||
maybeCreateCustomToken(token, userWallet)
|
||||
}
|
||||
|
||||
private fun maybeCreateCustomToken(
|
||||
token: UserTokensResponse.Token,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
): ManagedCryptoCurrency? {
|
||||
val blockchain = Blockchain.fromNetworkId(token.networkId)
|
||||
?.takeUnless { it in excludedBlockchains }
|
||||
?: return null
|
||||
|
||||
if (!checkIsCustomToken(token, blockchain, scanResponse.derivationStyleProvider)) {
|
||||
if (!checkIsCustomToken(token, blockchain, userWallet.derivationStyleProvider)) {
|
||||
return null
|
||||
}
|
||||
|
||||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = token.derivationPath,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
val contractAddress = token.contractAddress
|
||||
|
||||
|
|
@ -135,7 +134,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
coinResponse: CoinsResponse.Coin,
|
||||
tokensResponse: UserTokensResponse?,
|
||||
imageHost: String?,
|
||||
scanResponse: ScanResponse?,
|
||||
userWallet: UserWallet?,
|
||||
): ManagedCryptoCurrency? {
|
||||
if (coinResponse.networks.isEmpty() || !coinResponse.active) return null
|
||||
|
||||
|
|
@ -146,7 +145,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
networkId = network.networkId,
|
||||
contractAddress = network.contractAddress,
|
||||
decimals = network.decimalCount?.toInt(),
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
.ifEmpty { return null }
|
||||
|
|
@ -157,7 +156,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
symbol = coinResponse.symbol,
|
||||
iconUrl = getIconUrl(coinResponse.id, imageHost),
|
||||
availableNetworks = availableNetworks,
|
||||
addedIn = findAddedInNetworks(coinResponse.id, tokensResponse, scanResponse),
|
||||
addedIn = findAddedInNetworks(coinResponse.id, tokensResponse, userWallet),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +164,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
networkId: String,
|
||||
contractAddress: String?,
|
||||
decimals: Int?,
|
||||
scanResponse: ScanResponse?,
|
||||
userWallet: UserWallet?,
|
||||
extraDerivationPath: String? = null,
|
||||
): SourceNetwork? {
|
||||
val blockchain = Blockchain.fromNetworkId(networkId)
|
||||
|
|
@ -175,10 +174,8 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
derivationStyleProvider = scanResponse?.derivationStyleProvider,
|
||||
canHandleTokens = scanResponse?.let {
|
||||
it.card.canHandleToken(blockchain, it.cardTypesResolver, excludedBlockchains)
|
||||
} ?: false, // use card specific check if available
|
||||
derivationStyleProvider = userWallet?.derivationStyleProvider,
|
||||
canHandleTokens = userWallet?.canHandleToken(blockchain, excludedBlockchains) ?: false,
|
||||
) ?: return null
|
||||
|
||||
return when {
|
||||
|
|
@ -207,7 +204,7 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
private fun findAddedInNetworks(
|
||||
currencyId: String,
|
||||
tokensResponse: UserTokensResponse?,
|
||||
scanResponse: ScanResponse?,
|
||||
userWallet: UserWallet?,
|
||||
): Set<Network> {
|
||||
if (tokensResponse == null) return emptySet()
|
||||
|
||||
|
|
@ -220,10 +217,8 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = token.derivationPath,
|
||||
derivationStyleProvider = scanResponse?.derivationStyleProvider,
|
||||
canHandleTokens = scanResponse?.let {
|
||||
it.card.canHandleToken(blockchain, it.cardTypesResolver, excludedBlockchains)
|
||||
} ?: true,
|
||||
derivationStyleProvider = userWallet?.derivationStyleProvider,
|
||||
canHandleTokens = userWallet?.canHandleToken(blockchain, excludedBlockchains) ?: true,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import com.tangem.domain.markets.*
|
|||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.pagination.*
|
||||
import com.tangem.pagination.fetcher.LimitOffsetBatchFetcher
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -259,13 +258,13 @@ internal class DefaultMarketsTokenRepository(
|
|||
cryptoCurrencyFactory.createCoin(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} else {
|
||||
val currencyNetwork = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
|
||||
cryptoCurrencyFactory.createToken(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.data.networks.store.NetworksStatusesStore
|
|||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.models.network.NetworkStatus
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusProducer
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
|
@ -48,7 +47,7 @@ internal class DefaultMultiNetworkStatusProducer @AssistedInject constructor(
|
|||
val network = networkFactory.create(
|
||||
networkId = status.id,
|
||||
derivationPath = status.id.derivationPath,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return@mapNotNullTo null
|
||||
|
||||
NetworkStatus(network = network, value = status.value)
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.first().id,
|
||||
derivationPath = simpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns statuses.first().network
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.last().id,
|
||||
derivationPath = simpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns statuses.last().network
|
||||
|
||||
|
|
@ -94,12 +94,12 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.first().id,
|
||||
derivationPath = simpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
networkFactory.create(
|
||||
networkId = simpleStatuses.last().id,
|
||||
derivationPath = simpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.first().id,
|
||||
derivationPath = simpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns statuses.first().network
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.last().id,
|
||||
derivationPath = simpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns statuses.last().network
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = updatedSimpleStatuses.first().id,
|
||||
derivationPath = updatedSimpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns updatedStatuses.first().network
|
||||
|
||||
|
|
@ -154,7 +154,7 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = updatedSimpleStatuses.last().id,
|
||||
derivationPath = updatedSimpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns updatedStatuses.last().network
|
||||
// endregion
|
||||
|
|
@ -177,12 +177,12 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.first().id,
|
||||
derivationPath = simpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
networkFactory.create(
|
||||
networkId = simpleStatuses.last().id,
|
||||
derivationPath = simpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -202,12 +202,12 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = updatedSimpleStatuses.first().id,
|
||||
derivationPath = updatedSimpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
networkFactory.create(
|
||||
networkId = updatedSimpleStatuses.last().id,
|
||||
derivationPath = updatedSimpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -232,7 +232,7 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.first().id,
|
||||
derivationPath = simpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns statuses.first().network
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.last().id,
|
||||
derivationPath = simpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns statuses.last().network
|
||||
// endregion
|
||||
|
|
@ -263,12 +263,12 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.first().id,
|
||||
derivationPath = simpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
networkFactory.create(
|
||||
networkId = simpleStatuses.last().id,
|
||||
derivationPath = simpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -312,14 +312,14 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.first().id,
|
||||
derivationPath = simpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns statuses.first().network
|
||||
every {
|
||||
networkFactory.create(
|
||||
networkId = simpleStatuses.last().id,
|
||||
derivationPath = simpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns statuses.last().network
|
||||
// endregion
|
||||
|
|
@ -336,7 +336,7 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
|
||||
verifyOrder(inverse = true) {
|
||||
userWalletsStore.getSyncOrNull(any())
|
||||
networkFactory.create(networkId = any(), derivationPath = any(), scanResponse = any())
|
||||
networkFactory.create(networkId = any(), derivationPath = any(), userWallet = any())
|
||||
}
|
||||
|
||||
// Act 2 (emit)
|
||||
|
|
@ -353,12 +353,12 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.first().id,
|
||||
derivationPath = simpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
networkFactory.create(
|
||||
networkId = simpleStatuses.last().id,
|
||||
derivationPath = simpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -410,12 +410,12 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
networkFactory.create(
|
||||
networkId = simpleStatuses.first().id,
|
||||
derivationPath = simpleStatuses.first().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
networkFactory.create(
|
||||
networkId = simpleStatuses.last().id,
|
||||
derivationPath = simpleStatuses.last().id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -429,10 +429,10 @@ internal class DefaultMultiNetworkStatusProducerTest {
|
|||
|
||||
val userWallet = MockUserWalletFactory.create(scanResponse = scanResponse)
|
||||
|
||||
val ethNetwork = MockCryptoCurrencyFactory(scanResponse = scanResponse).ethereum.network.copy(
|
||||
val ethNetwork = MockCryptoCurrencyFactory(userWallet = userWallet).ethereum.network.copy(
|
||||
canHandleTokens = true,
|
||||
)
|
||||
|
||||
val cardanoNetwork = MockCryptoCurrencyFactory(scanResponse = scanResponse).cardano.network
|
||||
val cardanoNetwork = MockCryptoCurrencyFactory(userWallet = userWallet).cardano.network
|
||||
}
|
||||
}
|
||||
|
|
@ -208,7 +208,7 @@ internal class DefaultNFTRepository @Inject constructor(
|
|||
networkFactory.create(
|
||||
blockchain = it,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
.filter { it.canHandleNFTs(userWalletId) }
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import com.tangem.domain.onramp.model.HotCryptoCurrency
|
|||
import com.tangem.domain.onramp.repositories.HotCryptoRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.runCatching
|
||||
|
|
@ -93,7 +92,7 @@ internal class DefaultHotCryptoRepository(
|
|||
?: error("UserWalletId [$userWalletId] not found")
|
||||
|
||||
HotCryptoCurrencyConverter(
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
imageHost = it.imageHost,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,22 +10,22 @@ import com.tangem.domain.models.StatusSource
|
|||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.onramp.model.HotCryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.utils.converter.Converter
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Converter from [HotCryptoResponse.Token] to [HotCryptoCurrency]
|
||||
*
|
||||
* @property scanResponse scan response
|
||||
* @property userWallet scan response
|
||||
* @property imageHost image host
|
||||
* @param excludedBlockchains excluded blockchains
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class HotCryptoCurrencyConverter(
|
||||
private val scanResponse: ScanResponse,
|
||||
private val userWallet: UserWallet,
|
||||
private val imageHost: String?,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
) : Converter<HotCryptoResponse.Token, HotCryptoCurrency?> {
|
||||
|
|
@ -81,7 +81,7 @@ internal class HotCryptoCurrencyConverter(
|
|||
return networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import com.tangem.domain.swap.models.SwapTransactionListModel
|
|||
import com.tangem.domain.swap.models.SwapTransactionModel
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.addOrReplace
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -119,7 +118,7 @@ internal class DefaultSwapTransactionRepository(
|
|||
currencyTxs?.mapNotNull {
|
||||
listConverter.convertBack(
|
||||
value = it,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
txStatuses = txStatuses,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package com.tangem.data.swap.converter.transaction
|
|||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.data.swap.models.SwapStatusDTO
|
||||
import com.tangem.data.swap.models.SwapTransactionDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.swap.models.SwapTransactionModel
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.utils.converter.TwoWayConverter
|
||||
|
||||
internal class SavedSwapTransactionConverter(
|
||||
|
|
@ -35,14 +35,14 @@ internal class SavedSwapTransactionConverter(
|
|||
|
||||
fun convertBack(
|
||||
value: SwapTransactionDTO,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
txStatuses: Map<String, SwapStatusDTO>,
|
||||
): SwapTransactionModel {
|
||||
val status = txStatuses[value.txId]
|
||||
val refundCurrency = status?.refundTokensResponse?.let { id ->
|
||||
responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = id,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
val statusWithRefundCurrency = status?.copy(refundCurrency = refundCurrency)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import com.tangem.data.swap.models.SwapStatusDTO
|
|||
import com.tangem.data.swap.models.SwapTransactionDTO
|
||||
import com.tangem.data.swap.models.SwapTransactionListDTO
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.swap.models.SwapTransactionListModel
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ internal class SavedSwapTransactionListConverter(
|
|||
|
||||
fun convertBack(
|
||||
value: SwapTransactionListDTO,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
txStatuses: Map<String, SwapStatusDTO>,
|
||||
): SwapTransactionListModel? {
|
||||
val fromToken = value.fromTokensResponse
|
||||
|
|
@ -45,16 +45,16 @@ internal class SavedSwapTransactionListConverter(
|
|||
} else {
|
||||
val fromCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = fromToken,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
val toCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = toToken,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
|
||||
return SwapTransactionListModel(
|
||||
transactions = value.transactions.map { tx ->
|
||||
savedSwapTransactionConverter.convertBack(tx, scanResponse, txStatuses)
|
||||
savedSwapTransactionConverter.convertBack(tx, userWallet, txStatuses)
|
||||
},
|
||||
userWalletId = value.userWalletId,
|
||||
fromCryptoCurrencyId = value.fromCryptoCurrencyId,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import com.tangem.datasource.local.token.UserTokensResponseStore
|
|||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.core.utils.catchOn
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher.Params
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -60,7 +59,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcher(
|
|||
if (!userWallet.isMultiCurrency) error("${this::class.simpleName} supports only multi-currency wallet")
|
||||
|
||||
val response = if (userWallet is UserWallet.Cold && userWallet.isDemoWalletWithoutSavedTokens()) {
|
||||
createDefaultUserTokensResponse(scanResponse = userWallet.scanResponse)
|
||||
createDefaultUserTokensResponse(userWallet = userWallet)
|
||||
} else {
|
||||
safeApiCall(
|
||||
call = {
|
||||
|
|
@ -99,7 +98,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcher(
|
|||
val userWalletId = userWallet.walletId
|
||||
|
||||
val response = userTokensResponseStore.getSyncOrNull(userWalletId = userWalletId)
|
||||
?: createDefaultUserTokensResponse(scanResponse = userWallet.requireColdWallet().scanResponse)
|
||||
?: createDefaultUserTokensResponse(userWallet = userWallet)
|
||||
|
||||
if (error is ApiResponseError.HttpException && error.code == ApiResponseError.HttpException.Code.NOT_FOUND) {
|
||||
Timber.w(error, "Requested currencies could not be found in the remote store for: $userWalletId")
|
||||
|
|
@ -121,9 +120,9 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcher(
|
|||
expressServiceLoader.update(userWallet = userWallet, userTokens = tokens)
|
||||
}
|
||||
|
||||
private fun createDefaultUserTokensResponse(scanResponse: ScanResponse): UserTokensResponse {
|
||||
private fun createDefaultUserTokensResponse(userWallet: UserWallet): UserTokensResponse {
|
||||
return userTokensResponseFactory.createUserTokensResponse(
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(scanResponse),
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(userWallet),
|
||||
isGroupedByNetwork = false,
|
||||
isSortedByBalance = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducer @AssistedInject constr
|
|||
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = response,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
).toSet()
|
||||
}
|
||||
.onEmpty { emit(fallback) }
|
||||
|
|
|
|||
|
|
@ -184,7 +184,8 @@ internal class DefaultCurrenciesRepository(
|
|||
)
|
||||
|
||||
val token = userTokensResponseFactory.createResponseToken(currency)
|
||||
val updatedResponse = savedCurrencies.copy(tokens = savedCurrencies.tokens.filterNot { it == token })
|
||||
val updatedResponse =
|
||||
savedCurrencies.copy(tokens = savedCurrencies.tokens.filterNot { it == token })
|
||||
userTokensSaver.storeAndPush(
|
||||
userWalletId = userWalletId,
|
||||
response = updatedResponse,
|
||||
|
|
@ -229,10 +230,11 @@ internal class DefaultCurrenciesRepository(
|
|||
): CryptoCurrency {
|
||||
return withContext(dispatchers.io) {
|
||||
val userWallet = userWalletsStore.getSyncStrict(userWalletId)
|
||||
userWallet.requireColdWallet()
|
||||
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false)
|
||||
|
||||
val currency = cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(
|
||||
userWallet.requireColdWallet().scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
|
||||
fetchExpressAssetsByNetworkIds(
|
||||
|
|
@ -254,11 +256,12 @@ internal class DefaultCurrenciesRepository(
|
|||
val scanResponse = userWallet.requireColdWallet().scanResponse
|
||||
|
||||
val currencies = if (scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(scanResponse = scanResponse)
|
||||
cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(userWallet = userWallet)
|
||||
} else {
|
||||
cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(scanResponse = scanResponse).run {
|
||||
listOf(this)
|
||||
}
|
||||
cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(userWallet = userWallet)
|
||||
.run {
|
||||
listOf(this)
|
||||
}
|
||||
}
|
||||
|
||||
fetchExpressAssetsByNetworkIds(
|
||||
|
|
@ -277,10 +280,11 @@ internal class DefaultCurrenciesRepository(
|
|||
): CryptoCurrency {
|
||||
return withContext(dispatchers.io) {
|
||||
val userWallet = userWalletsStore.getSyncStrict(userWalletId)
|
||||
userWallet.requireColdWallet()
|
||||
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false)
|
||||
|
||||
val currency = cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
.find { it.id == id }
|
||||
requireNotNull(currency) { "Unable to find currency with provided ID: $id" }
|
||||
|
|
@ -320,7 +324,10 @@ internal class DefaultCurrenciesRepository(
|
|||
},
|
||||
)
|
||||
|
||||
responseCryptoCurrenciesFactory.createCurrencies(storedTokens, userWallet.requireColdWallet().scanResponse)
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
storedTokens,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getMultiCurrencyWalletCachedCurrenciesSync(userWalletId: UserWalletId) =
|
||||
|
|
@ -335,7 +342,10 @@ internal class DefaultCurrenciesRepository(
|
|||
},
|
||||
)
|
||||
|
||||
responseCryptoCurrenciesFactory.createCurrencies(storedTokens, userWallet.requireColdWallet().scanResponse)
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
storedTokens,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getMultiCurrencyWalletCurrency(
|
||||
|
|
@ -360,7 +370,7 @@ internal class DefaultCurrenciesRepository(
|
|||
responseCryptoCurrenciesFactory.createCurrency(
|
||||
currencyId = id,
|
||||
response = response,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +404,7 @@ internal class DefaultCurrenciesRepository(
|
|||
|
||||
val coin = responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = storedCoin,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
|
||||
coin as? CryptoCurrency.Coin ?: error("Unable to create currency")
|
||||
|
|
@ -438,12 +448,15 @@ internal class DefaultCurrenciesRepository(
|
|||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
): Boolean {
|
||||
val blockchain = cryptoCurrencyStatus.currency.network.toBlockchain()
|
||||
val isBitcoinBlockchain = blockchain == Blockchain.Bitcoin || blockchain == Blockchain.BitcoinTestnet
|
||||
val isBitcoinBlockchain =
|
||||
blockchain == Blockchain.Bitcoin || blockchain == Blockchain.BitcoinTestnet
|
||||
return when {
|
||||
cryptoCurrencyStatus.currency is CryptoCurrency.Coin && isBitcoinBlockchain -> {
|
||||
val outgoingTransactions = cryptoCurrencyStatus.value.pendingTransactions.filter { it.isOutgoing }
|
||||
val outgoingTransactions =
|
||||
cryptoCurrencyStatus.value.pendingTransactions.filter { it.isOutgoing }
|
||||
outgoingTransactions.isNotEmpty()
|
||||
}
|
||||
|
||||
blockchain.isEvm() -> false
|
||||
blockchain == Blockchain.Tron || blockchain == Blockchain.TronTestnet -> false
|
||||
else -> {
|
||||
|
|
@ -481,6 +494,7 @@ internal class DefaultCurrenciesRepository(
|
|||
balance = balance,
|
||||
)
|
||||
}
|
||||
|
||||
is FeePaidSdkCurrency.FeeResource -> FeePaidCurrency.FeeResource(currency = feePaidCurrency.currency)
|
||||
}
|
||||
}
|
||||
|
|
@ -508,7 +522,8 @@ internal class DefaultCurrenciesRepository(
|
|||
.coins
|
||||
.firstOrNull()
|
||||
?: error("Token not found")
|
||||
val network = foundToken.networks.firstOrNull { it.networkId == networkId } ?: error("Network not found")
|
||||
val network = foundToken.networks.firstOrNull { it.networkId == networkId }
|
||||
?: error("Network not found")
|
||||
CryptoCurrencyFactory.Token(
|
||||
symbol = foundToken.symbol,
|
||||
name = foundToken.name,
|
||||
|
|
@ -521,7 +536,7 @@ internal class DefaultCurrenciesRepository(
|
|||
token = token,
|
||||
networkId = networkId,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
) ?: error("Unable to create token")
|
||||
}
|
||||
|
||||
|
|
@ -559,23 +574,25 @@ internal class DefaultCurrenciesRepository(
|
|||
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = storedTokens.copy(tokens = filterResponse),
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val currencies = if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
getSingleCurrencyWalletWithCardCurrencies(userWallet.walletId)
|
||||
} else {
|
||||
val currency =
|
||||
getSingleCurrencyWalletPrimaryCurrency(userWalletId = userWallet.walletId)
|
||||
|
||||
if (currency.id.rawCurrencyId == currencyRawId) {
|
||||
listOf(currency)
|
||||
else -> {
|
||||
val currencies =
|
||||
if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
getSingleCurrencyWalletWithCardCurrencies(userWallet.walletId)
|
||||
} else {
|
||||
emptyList()
|
||||
val currency =
|
||||
getSingleCurrencyWalletPrimaryCurrency(userWalletId = userWallet.walletId)
|
||||
|
||||
if (currency.id.rawCurrencyId == currencyRawId) {
|
||||
listOf(currency)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
flow {
|
||||
emit(currencies)
|
||||
}
|
||||
|
|
@ -603,14 +620,15 @@ internal class DefaultCurrenciesRepository(
|
|||
}
|
||||
|
||||
override fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver {
|
||||
return userWalletsStore.getSyncStrict(userWalletId).requireColdWallet().cardTypesResolver // TODO [REDACTED_TASK_KEY]
|
||||
return userWalletsStore.getSyncStrict(userWalletId)
|
||||
.requireColdWallet().cardTypesResolver // TODO [REDACTED_TASK_KEY]
|
||||
}
|
||||
|
||||
private fun getMultiCurrencyWalletCurrencies(userWallet: UserWallet): Flow<List<CryptoCurrency>> {
|
||||
return getSavedUserTokensResponse(userWallet.walletId).map { storedTokens ->
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = storedTokens,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -700,7 +718,10 @@ internal class DefaultCurrenciesRepository(
|
|||
?: createDefaultUserTokensResponse(userWallet = userWallet)
|
||||
|
||||
if (e is ApiResponseError.HttpException && e.code == ApiResponseError.HttpException.Code.NOT_FOUND) {
|
||||
Timber.w(e, "Requested currencies could not be found in the remote store for: $userWalletId")
|
||||
Timber.w(
|
||||
e,
|
||||
"Requested currencies could not be found in the remote store for: $userWalletId",
|
||||
)
|
||||
|
||||
userTokensSaver.push(userWalletId, response)
|
||||
} else {
|
||||
|
|
@ -712,8 +733,8 @@ internal class DefaultCurrenciesRepository(
|
|||
|
||||
private fun createDefaultUserTokensResponse(userWallet: UserWallet) =
|
||||
userTokensResponseFactory.createUserTokensResponse(
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(
|
||||
userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(
|
||||
userWallet = userWallet,
|
||||
),
|
||||
isGroupedByNetwork = false,
|
||||
isSortedByBalance = false,
|
||||
|
|
@ -732,9 +753,11 @@ internal class DefaultCurrenciesRepository(
|
|||
!userWallet.isMultiCurrency && isMultiCurrencyWalletExpected -> {
|
||||
"Multi currency wallet expected, but single currency wallet was found: $userWalletId"
|
||||
}
|
||||
|
||||
userWallet.isMultiCurrency && !isMultiCurrencyWalletExpected -> {
|
||||
"Single currency wallet expected, but multi currency wallet was found: $userWalletId"
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcherTest {
|
|||
every { userWalletsStore.getSyncStrict(params.userWalletId) } returns mockUserWallet
|
||||
coEvery { userTokensResponseStore.getSyncOrNull(userWalletId = params.userWalletId) } returns null
|
||||
every {
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(mockUserWallet.scanResponse)
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(mockUserWallet)
|
||||
} returns defaultCoins
|
||||
coEvery {
|
||||
customTokensMerger.mergeIfPresented(userWalletId = params.userWalletId, response = userTokensResponse)
|
||||
|
|
@ -141,7 +141,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcherTest {
|
|||
coVerifyOrder {
|
||||
userWalletsStore.getSyncStrict(key = params.userWalletId)
|
||||
userTokensResponseStore.getSyncOrNull(userWalletId = params.userWalletId)
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(scanResponse = mockUserWallet.scanResponse)
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(mockUserWallet)
|
||||
customTokensMerger.mergeIfPresented(userWalletId = params.userWalletId, response = userTokensResponse)
|
||||
userTokensSaver.store(userWalletId = params.userWalletId, response = userTokensResponse)
|
||||
expressServiceLoader.update(userWallet = mockUserWallet, userTokens = userTokensResponse.toLeastTokens())
|
||||
|
|
@ -187,7 +187,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcherTest {
|
|||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(scanResponse = any())
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcherTest {
|
|||
|
||||
coVerify(inverse = true) {
|
||||
userTokensResponseStore.getSyncOrNull(userWalletId = any())
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(scanResponse = any())
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,7 +267,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcherTest {
|
|||
coEvery { tangemTechApi.getUserTokens(userId = params.userWalletId.stringValue) } returns apiResponse
|
||||
coEvery { userTokensResponseStore.getSyncOrNull(userWalletId = userWalletId) } returns null
|
||||
coEvery {
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(mockUserWallet.scanResponse)
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(mockUserWallet)
|
||||
} returns defaultCoins
|
||||
coEvery {
|
||||
customTokensMerger.mergeIfPresented(userWalletId = params.userWalletId, response = userTokensResponse)
|
||||
|
|
@ -335,7 +335,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcherTest {
|
|||
|
||||
coVerify(inverse = true) {
|
||||
userTokensSaver.push(userWalletId = any(), response = any())
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(scanResponse = any())
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -377,7 +377,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcherTest {
|
|||
coEvery { tangemTechApi.getUserTokens(userId = params.userWalletId.stringValue) } returns apiResponse
|
||||
coEvery { userTokensResponseStore.getSyncOrNull(userWalletId = userWalletId) } returns null
|
||||
coEvery {
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(mockUserWallet.scanResponse)
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(mockUserWallet)
|
||||
} returns defaultCoins
|
||||
coEvery {
|
||||
customTokensMerger.mergeIfPresented(userWalletId = params.userWalletId, response = userTokensResponse)
|
||||
|
|
@ -394,7 +394,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcherTest {
|
|||
userWalletsStore.getSyncStrict(key = params.userWalletId)
|
||||
tangemTechApi.getUserTokens(userId = params.userWalletId.stringValue)
|
||||
userTokensResponseStore.getSyncOrNull(userWalletId = userWalletId)
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(mockUserWallet.scanResponse)
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(mockUserWallet)
|
||||
userTokensSaver.push(userWalletId = params.userWalletId, response = userTokensResponse)
|
||||
customTokensMerger.mergeIfPresented(userWalletId = params.userWalletId, response = userTokensResponse)
|
||||
userTokensSaver.store(userWalletId = params.userWalletId, response = userTokensResponse)
|
||||
|
|
@ -447,7 +447,7 @@ internal class DefaultMultiWalletCryptoCurrenciesFetcherTest {
|
|||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(scanResponse = any())
|
||||
cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
}
|
||||
|
||||
verify(inverse = true) {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(response = any(), scanResponse = any())
|
||||
responseCryptoCurrenciesFactory.createCurrencies(response = any(), userWallet = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,14 +114,14 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
every {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns cryptoCurrencies.toList()
|
||||
|
||||
every {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = updatedUserTokensResponse,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns updatedCryptoCurrencies.toList()
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
userTokensResponseStore.get(params.userWalletId)
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
verifyOrder {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = updatedUserTokensResponse,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -185,7 +185,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
every {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns cryptoCurrencies.toList()
|
||||
|
||||
|
|
@ -207,7 +207,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
userTokensResponseStore.get(params.userWalletId)
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +251,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
every {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} returns cryptoCurrencies.toList()
|
||||
|
||||
|
|
@ -282,7 +282,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
verifyOrder {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(
|
||||
response = userTokensResponse,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -307,7 +307,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
}
|
||||
|
||||
verify(inverse = true) {
|
||||
responseCryptoCurrenciesFactory.createCurrencies(response = any(), scanResponse = any())
|
||||
responseCryptoCurrenciesFactory.createCurrencies(response = any(), userWallet = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +335,7 @@ internal class DefaultMultiWalletCryptoCurrenciesProducerTest {
|
|||
|
||||
verify(inverse = true) {
|
||||
userTokensResponseStore.get(any())
|
||||
responseCryptoCurrenciesFactory.createCurrencies(response = any(), scanResponse = any())
|
||||
responseCryptoCurrenciesFactory.createCurrencies(response = any(), userWallet = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import com.tangem.data.walletconnect.model.CAIP2
|
|||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
|
||||
internal interface WcNamespaceConverter {
|
||||
|
||||
|
|
@ -27,7 +26,7 @@ internal interface WcNamespaceConverter {
|
|||
return NetworkFactory(excludedBlockchains).create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = wallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = wallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -23,4 +23,8 @@ internal class TangemDerivationStyleProvider(
|
|||
private fun firstBatchesOfWallet1(card: CardDTO): Boolean {
|
||||
return card.batchId == "AC01" || card.batchId == "AC02" || card.batchId == "CB95"
|
||||
}
|
||||
}
|
||||
|
||||
internal class TangemHotDerivationStyleProvider : DerivationStyleProvider {
|
||||
override fun getDerivationStyle(): DerivationStyle? = DerivationStyle.V3
|
||||
}
|
||||
|
|
@ -7,7 +7,9 @@ import com.tangem.common.card.FirmwareVersion
|
|||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
||||
import com.tangem.domain.common.configs.CardConfig
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
// TODO: refactor [REDACTED_JIRA]
|
||||
|
||||
|
|
@ -17,6 +19,20 @@ import com.tangem.domain.models.scan.CardDTO
|
|||
val FirmwareVersion.Companion.SolanaTokensAvailable
|
||||
get() = FirmwareVersion(4, 52)
|
||||
|
||||
fun UserWallet.supportedBlockchains(excludedBlockchains: ExcludedBlockchains): List<Blockchain> {
|
||||
return when (this) {
|
||||
is UserWallet.Cold -> {
|
||||
scanResponse.card.supportedBlockchains(
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
cardTypesResolver = this.cardTypesResolver,
|
||||
)
|
||||
}
|
||||
is UserWallet.Hot -> {
|
||||
Blockchain.entries.filter { it !in excludedBlockchains }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun CardDTO.supportedBlockchains(
|
||||
cardTypesResolver: CardTypesResolver,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
|
|
@ -55,6 +71,33 @@ fun CardDTO.supportedTokens(
|
|||
return tokensSupportedByCard.filter { isTestCard == it.isTestnet() }
|
||||
}
|
||||
|
||||
fun UserWallet.canHandleToken(supportedTokens: List<Blockchain>, blockchain: Blockchain): Boolean {
|
||||
return when (this) {
|
||||
is UserWallet.Cold -> {
|
||||
scanResponse.card.canHandleToken(
|
||||
supportedTokens = supportedTokens,
|
||||
blockchain = blockchain,
|
||||
cardTypesResolver = scanResponse.cardTypesResolver,
|
||||
)
|
||||
}
|
||||
is UserWallet.Hot -> blockchain in supportedTokens
|
||||
}
|
||||
}
|
||||
|
||||
fun UserWallet.canHandleToken(blockchain: Blockchain, excludedBlockchains: ExcludedBlockchains): Boolean {
|
||||
return when (this) {
|
||||
is UserWallet.Cold -> {
|
||||
scanResponse.card.canHandleToken(
|
||||
blockchain = blockchain,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
cardTypesResolver = scanResponse.cardTypesResolver,
|
||||
)
|
||||
}
|
||||
|
||||
is UserWallet.Hot -> blockchain !in excludedBlockchains
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The same as [CardDTO.supportedTokens] but with supportedTokens input, if previously calculated
|
||||
*/
|
||||
|
|
@ -101,7 +144,8 @@ fun CardDTO.canHandleBlockchain(
|
|||
): Boolean {
|
||||
val cardConfig = CardConfig.createConfig(this)
|
||||
val primaryCurveForBlockchain = cardConfig.primaryCurve(blockchain)
|
||||
val isContainsBlockchain = blockchain in supportedBlockchains(cardTypesResolver, excludedBlockchains)
|
||||
val isContainsBlockchain =
|
||||
blockchain in supportedBlockchains(cardTypesResolver, excludedBlockchains)
|
||||
val isWalletForCurveExists = wallets.any { it.curve == primaryCurveForBlockchain }
|
||||
// fixme: check for first wallets with 1 curve and remove condition
|
||||
return if (cardTypesResolver.isTangemWallet() || cardTypesResolver.isWallet2()) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.domain.common.CardTypesResolver
|
|||
import com.tangem.domain.common.DerivationStyleProvider
|
||||
import com.tangem.domain.common.TangemCardTypesResolver
|
||||
import com.tangem.domain.common.TangemDerivationStyleProvider
|
||||
import com.tangem.domain.common.TangemHotDerivationStyleProvider
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
||||
import com.tangem.domain.common.configs.CardConfig
|
||||
|
|
@ -23,6 +24,12 @@ val ScanResponse.cardTypesResolver: CardTypesResolver
|
|||
walletData = walletData,
|
||||
)
|
||||
|
||||
val UserWallet.derivationStyleProvider: DerivationStyleProvider
|
||||
get() = when (this) {
|
||||
is UserWallet.Cold -> this.scanResponse.derivationStyleProvider
|
||||
is UserWallet.Hot -> TangemHotDerivationStyleProvider()
|
||||
}
|
||||
|
||||
val ScanResponse.derivationStyleProvider: DerivationStyleProvider
|
||||
get() = card.derivationStyleProvider
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import kotlinx.serialization.Serializable
|
|||
|
||||
@Serializable(with = MobileWalletAsStringSerializer::class)
|
||||
@JsonClass(generateAdapter = true)
|
||||
class MobileWallet(
|
||||
data class MobileWallet(
|
||||
@Json(name = "publicKey")
|
||||
val publicKey: ByteArray,
|
||||
@Json(name = "chainCode")
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
|||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
|
|
@ -44,11 +44,10 @@ class GetNetworkCoinStatusUseCase(
|
|||
derivationPath: Network.DerivationPath,
|
||||
): Either<CurrencyStatusError, CryptoCurrencyStatus> {
|
||||
val userWalletId = userWallet.walletId
|
||||
val cardTypesResolver = userWallet.requireColdWallet().cardTypesResolver // TODO [REDACTED_TASK_KEY]
|
||||
|
||||
val maybeCurrency = if (userWallet.isMultiCurrency) {
|
||||
currencyStatusOperations.getNetworkCoinSync(userWalletId, networkId, derivationPath)
|
||||
} else if (cardTypesResolver.isSingleWalletWithToken()) {
|
||||
} else if (userWallet is UserWallet.Cold && userWallet.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
currencyStatusOperations.getNetworkCoinForSingleWalletWithTokenSync(userWalletId, networkId)
|
||||
} else {
|
||||
currencyStatusOperations.getPrimaryCurrencyStatusSync(userWalletId)
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ sealed interface UserWallet {
|
|||
override val walletId: UserWalletId,
|
||||
val hotWalletId: HotWalletId,
|
||||
val wallets: List<MobileWallet>?,
|
||||
val backedUp: Boolean,
|
||||
) : UserWallet {
|
||||
|
||||
val isLocked: Boolean get() = wallets == null
|
||||
|
|
|
|||
|
|
@ -11,29 +11,31 @@ import com.tangem.hot.sdk.model.DeriveWalletRequest
|
|||
import com.tangem.hot.sdk.model.HotAuth
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.hot.sdk.model.UnlockHotWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class HotUserWalletBuilder @AssistedInject constructor(
|
||||
@Assisted private val hotWalletId: HotWalletId,
|
||||
private val hotSdk: TangemHotSdk,
|
||||
private val generateWalletNameUseCase: GenerateWalletNameUseCase,
|
||||
private val dispatcherProvider: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
suspend fun build(): UserWallet.Hot {
|
||||
suspend fun build(): UserWallet.Hot = withContext(dispatcherProvider.default) {
|
||||
val allNetworks = Blockchain.entries // TODO use HotDerivationsRepository to get supported networks
|
||||
val requests = allNetworks.map {
|
||||
val curves = it.getSupportedCurves()
|
||||
val derivationPath = it.derivationPath(DerivationStyle.V3)
|
||||
val curves = allNetworks.map { it.getSupportedCurves() }.flatten().toSet()
|
||||
val requests = curves.sortedBy { it.ordinal }.map { curve ->
|
||||
val derivationPaths = allNetworks.filter { curve in it.getSupportedCurves() }
|
||||
.mapNotNull { it.derivationPath(DerivationStyle.V3) }
|
||||
|
||||
curves.map {
|
||||
DeriveWalletRequest.Request(
|
||||
curve = it,
|
||||
paths = listOfNotNull(derivationPath),
|
||||
)
|
||||
}
|
||||
}.flatten()
|
||||
DeriveWalletRequest.Request(
|
||||
curve = curve,
|
||||
paths = derivationPaths,
|
||||
)
|
||||
}
|
||||
|
||||
val derivationResult = hotSdk.derivePublicKey(
|
||||
unlockHotWallet = UnlockHotWallet(
|
||||
|
|
@ -54,11 +56,12 @@ class HotUserWalletBuilder @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
return UserWallet.Hot(
|
||||
UserWallet.Hot(
|
||||
name = generateWalletNameUseCase.invokeForHot(),
|
||||
walletId = UserWalletId(wallets.first().publicKey),
|
||||
hotWalletId = hotWalletId,
|
||||
wallets = wallets,
|
||||
backedUp = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class GenerateWalletNameUseCase(
|
|||
}
|
||||
|
||||
fun invokeForHot(): String {
|
||||
val defaultName = "Mobile Wallet"
|
||||
val defaultName = "Wallet"
|
||||
val existingNames = userWalletsListManager.userWalletsSync.map { it.name }.toSet()
|
||||
return suggestedWalletName(defaultName, existingNames)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
|
|
@ -49,6 +50,8 @@ internal class CreateMobileWalletModel @Inject constructor(
|
|||
)
|
||||
router.push(AppRoute.Wallet)
|
||||
}.onFailure {
|
||||
Timber.e(it)
|
||||
|
||||
uiState.update {
|
||||
it.copy(createButtonLoading = false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,30 +7,18 @@ import com.tangem.features.hotwallet.createmobilewallet.DefaultCreateMobileWalle
|
|||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ActivityComponent
|
||||
import dagger.hilt.android.scopes.ActivityScoped
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object CreateMobileWalletModule
|
||||
|
||||
@Module
|
||||
@InstallIn(ActivityComponent::class)
|
||||
internal interface CreateMobileWalletModuleActivityBinds {
|
||||
internal interface CreateMobileWalletModuleBinds {
|
||||
|
||||
@Binds
|
||||
@ActivityScoped
|
||||
fun bindCreateMobileWalletComponentFactory(
|
||||
impl: DefaultCreateMobileWalletComponent.Factory,
|
||||
): CreateMobileWalletComponent.Factory
|
||||
}
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface CreateMobileWalletModuleBinds {
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
|
|
@ -11,7 +11,6 @@ import com.tangem.datasource.api.tangemTech.models.StartReferralBody
|
|||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.referral.converters.ReferralConverter
|
||||
import com.tangem.feature.referral.domain.ReferralRepository
|
||||
import com.tangem.feature.referral.domain.models.ReferralData
|
||||
|
|
@ -97,13 +96,13 @@ internal class ReferralRepositoryImpl @Inject constructor(
|
|||
sdkToken = sdkToken,
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
} else {
|
||||
cryptoCurrencyFactory.createCoin(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import com.tangem.domain.walletmanager.WalletManagersFacade
|
|||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.swap.converters.*
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
import com.tangem.feature.swap.domain.models.ExpressDataError
|
||||
|
|
@ -404,12 +403,7 @@ internal class DefaultSwapRepository(
|
|||
cryptoCurrencyFactory.createCoin(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = requireNotNull(
|
||||
userWalletsListManager
|
||||
.selectedUserWalletSync
|
||||
?.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
?.scanResponse,
|
||||
),
|
||||
userWallet = requireNotNull(userWalletsListManager.selectedUserWalletSync),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import com.tangem.datasource.local.preferences.utils.getObjectMap
|
|||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.swap.converters.SavedSwapTransactionListConverter
|
||||
import com.tangem.feature.swap.domain.SwapTransactionRepository
|
||||
import com.tangem.feature.swap.domain.models.domain.*
|
||||
|
|
@ -104,7 +103,7 @@ internal class DefaultSwapTransactionRepository(
|
|||
currencyTxs?.mapNotNull {
|
||||
converter.convertBack(
|
||||
value = it,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
userWallet = userWallet,
|
||||
txStatuses = txStatuses,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.feature.swap.converters
|
|||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.data.common.currency.UserTokensResponseFactory
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.swap.domain.models.domain.ExchangeStatusModel
|
||||
import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionListModel
|
||||
|
|
@ -32,7 +32,7 @@ internal class SavedSwapTransactionListConverter(
|
|||
|
||||
fun convertBack(
|
||||
value: SavedSwapTransactionListModelInner,
|
||||
scanResponse: ScanResponse,
|
||||
userWallet: UserWallet,
|
||||
txStatuses: Map<String, ExchangeStatusModel>,
|
||||
): SavedSwapTransactionListModel? {
|
||||
val fromToken = value.fromTokensResponse
|
||||
|
|
@ -42,11 +42,11 @@ internal class SavedSwapTransactionListConverter(
|
|||
} else {
|
||||
val fromCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = fromToken,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
val toCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = toToken,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
) ?: return null
|
||||
|
||||
return SavedSwapTransactionListModel(
|
||||
|
|
@ -55,7 +55,7 @@ internal class SavedSwapTransactionListConverter(
|
|||
val refundCurrency = status?.refundTokensResponse?.let { id ->
|
||||
responseCryptoCurrenciesFactory.createCurrency(
|
||||
responseToken = id,
|
||||
scanResponse = scanResponse,
|
||||
userWallet = userWallet,
|
||||
)
|
||||
}
|
||||
val statusWithRefundCurrency = status?.copy(refundCurrency = refundCurrency)
|
||||
|
|
|
|||
|
|
@ -39,10 +39,22 @@ internal object WalletAdditionalInfoFactory {
|
|||
wallet.resolveSingleCurrencyInfo(currencyAmount)
|
||||
}
|
||||
}
|
||||
is UserWallet.Hot -> TODO("[REDACTED_TASK_KEY]")
|
||||
is UserWallet.Hot -> wallet.resolveAdditionalInfo()
|
||||
}
|
||||
}
|
||||
|
||||
private fun UserWallet.Hot.resolveAdditionalInfo(): WalletAdditionalInfo {
|
||||
return WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = TextReference.Res(R.string.hw_mobile_wallet) +
|
||||
when {
|
||||
isLocked -> DIVIDER + TextReference.Res(R.string.common_locked)
|
||||
backedUp.not() -> DIVIDER + TextReference.Res(R.string.hw_backup_no_backup)
|
||||
else -> TextReference.Str("")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun UserWallet.Cold.resolveMultiCurrencyInfo(): WalletAdditionalInfo {
|
||||
return if (isLocked) {
|
||||
WalletAdditionalInfo(
|
||||
|
|
|
|||
|
|
@ -24,7 +24,11 @@ internal class WalletImageResolver @Inject constructor(
|
|||
/** Get a specified wallet [userWallet] image */
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
@DrawableRes
|
||||
fun resolve(userWallet: UserWallet.Cold): Int? {
|
||||
fun resolve(userWallet: UserWallet): Int? {
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return null
|
||||
}
|
||||
|
||||
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
|
||||
|
||||
val cobrandImage = Wallet2CobrandImage.entries.firstOrNull {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ internal class WalletContentLoaderFactory @Inject constructor(
|
|||
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isVisaWallet() -> {
|
||||
visaWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
|
||||
}
|
||||
!userWallet.isMultiCurrency -> {
|
||||
userWallet is UserWallet.Cold && !userWallet.isMultiCurrency -> {
|
||||
singleWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
|
||||
}
|
||||
else -> null
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletContentLoader(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val isRefresh: Boolean,
|
||||
private val stateHolder: WalletStateController,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ internal class SingleWalletContentLoaderFactory @Inject constructor(
|
|||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
return SingleWalletContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletWithTokenContentLoader(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
|
|||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): SingleWalletWithTokenContentLoader {
|
||||
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents): SingleWalletWithTokenContentLoader {
|
||||
return SingleWalletWithTokenContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletSubscribe
|
|||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
|
||||
internal class VisaWalletContentLoader(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val isRefresh: Boolean,
|
||||
private val stateController: WalletStateController,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ internal class VisaWalletContentLoaderFactory @Inject constructor(
|
|||
private val getVisaTxHistoryUseCase: GetVisaTxHistoryUseCase,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
return VisaWalletContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.isLocked
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
|
|
@ -55,8 +54,6 @@ internal class InitializeWalletsTransformer(
|
|||
}
|
||||
|
||||
private fun createLockedState(userWallet: UserWallet): WalletState {
|
||||
userWallet.requireColdWallet()
|
||||
|
||||
return userWallet.createStateByWalletType(
|
||||
multiCurrencyCreator = {
|
||||
WalletState.MultiCurrency.Locked(
|
||||
|
|
@ -87,7 +84,7 @@ internal class InitializeWalletsTransformer(
|
|||
)
|
||||
}
|
||||
|
||||
private fun UserWallet.Cold.toLockedWalletCardState(): WalletCardState {
|
||||
private fun UserWallet.toLockedWalletCardState(): WalletCardState {
|
||||
return WalletCardState.LockedContent(
|
||||
id = walletId,
|
||||
title = name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
|||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
|
|
@ -57,8 +56,6 @@ internal class SetTokenListErrorTransformer(
|
|||
}
|
||||
|
||||
private fun WalletCardState.toLoadedState(): WalletCardState {
|
||||
selectedWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
|
||||
return WalletCardState.Content(
|
||||
id = id,
|
||||
title = title,
|
||||
|
|
@ -68,7 +65,10 @@ internal class SetTokenListErrorTransformer(
|
|||
balance = BigDecimal.ZERO.format {
|
||||
fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol)
|
||||
},
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
cardCount = when (selectedWallet) {
|
||||
is UserWallet.Cold -> selectedWallet.getCardsCount()
|
||||
is UserWallet.Hot -> null
|
||||
},
|
||||
isZeroBalance = true,
|
||||
isBalanceFlickering = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.visa.exception.RefreshTokenExpiredException
|
||||
import com.tangem.domain.visa.model.VisaCurrency
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.BalancesAndLimitsBlockState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAdditionalInfo
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
|
|
@ -27,7 +26,7 @@ import org.joda.time.DateTime
|
|||
import org.joda.time.Days
|
||||
|
||||
internal class SetVisaInfoTransformer(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val maybeVisaCurrency: Either<Throwable, VisaCurrency>,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) : TypedWalletStateTransformer<WalletState.Visa.Content>(
|
||||
|
|
@ -76,8 +75,6 @@ internal class SetVisaInfoTransformer(
|
|||
}
|
||||
|
||||
private fun getContentWalletCardState(prevState: WalletCardState, visaCurrency: VisaCurrency): WalletCardState {
|
||||
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
|
||||
return with(prevState) {
|
||||
WalletCardState.Content(
|
||||
id = id,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import com.tangem.domain.common.util.getCardsCount
|
|||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
|
@ -48,8 +47,6 @@ internal class MultiWalletCardStateConverter(
|
|||
}
|
||||
|
||||
private fun WalletCardState.toWalletCardState(fiatBalance: TotalFiatBalance.Loaded): WalletCardState {
|
||||
selectedWallet.requireColdWallet()
|
||||
|
||||
return WalletCardState.Content(
|
||||
id = id,
|
||||
title = title,
|
||||
|
|
@ -60,7 +57,10 @@ internal class MultiWalletCardStateConverter(
|
|||
fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol)
|
||||
},
|
||||
isZeroBalance = fiatBalance.amount.isZero(),
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
cardCount = when (selectedWallet) {
|
||||
is UserWallet.Cold -> selectedWallet.getCardsCount()
|
||||
is UserWallet.Hot -> null
|
||||
},
|
||||
isBalanceFlickering = fiatBalance.source == StatusSource.CACHE,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import com.tangem.domain.common.util.getCardsCount
|
|||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
|
|
@ -64,7 +63,10 @@ internal class SingleWalletCardStateConverter(
|
|||
imageResId = imageResId,
|
||||
dropDownItems = dropDownItems,
|
||||
balance = formatFiatAmount(status = status, appCurrency = appCurrency),
|
||||
cardCount = selectedWallet.requireColdWallet().getCardsCount(), // TODO [REDACTED_TASK_KEY]
|
||||
cardCount = when (selectedWallet) {
|
||||
is UserWallet.Cold -> selectedWallet.getCardsCount()
|
||||
is UserWallet.Hot -> null
|
||||
},
|
||||
isZeroBalance = status.fiatAmount?.isZero(),
|
||||
isBalanceFlickering = (status as? CryptoCurrencyStatus.Loaded)?.sources?.total == StatusSource.CACHE,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,14 +4,17 @@ import com.tangem.domain.common.util.cardTypesResolver
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
|
||||
internal inline fun UserWallet.Cold.createStateByWalletType(
|
||||
internal inline fun UserWallet.createStateByWalletType(
|
||||
multiCurrencyCreator: () -> WalletState.MultiCurrency,
|
||||
singleCurrencyCreator: () -> WalletState.SingleCurrency,
|
||||
visaWalletCreator: () -> WalletState.Visa,
|
||||
): WalletState = when {
|
||||
isVisaWallet() -> visaWalletCreator()
|
||||
isWalletWithTokens() -> multiCurrencyCreator()
|
||||
else -> singleCurrencyCreator()
|
||||
): WalletState = when (this) {
|
||||
is UserWallet.Cold -> when {
|
||||
isVisaWallet() -> visaWalletCreator()
|
||||
isWalletWithTokens() -> multiCurrencyCreator()
|
||||
else -> singleCurrencyCreator()
|
||||
}
|
||||
is UserWallet.Hot -> multiCurrencyCreator()
|
||||
}
|
||||
|
||||
private fun UserWallet.Cold.isWalletWithTokens(): Boolean {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletWithTokenListSubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
stateHolder: WalletStateController,
|
||||
clickIntents: WalletClickIntents,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.txhistory.models.TxHistoryStateError
|
|||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.collectLatest
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
|
|
@ -32,7 +31,7 @@ typealias MaybeTxHistoryItems = Either<TxHistoryListError, Flow<PagingData<TxInf
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class TxHistorySubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val isRefresh: Boolean,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
|
|
@ -97,7 +96,7 @@ internal class TxHistorySubscriber(
|
|||
)
|
||||
},
|
||||
ifRight = { itemsFlow ->
|
||||
val blockchain = userWallet.requireColdWallet().scanResponse.cardTypesResolver.getBlockchain()
|
||||
val blockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain()
|
||||
val itemConverter = TxHistoryItemStateConverter(
|
||||
symbol = blockchain.currency,
|
||||
decimals = blockchain.decimals(),
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.map
|
|||
import timber.log.Timber
|
||||
|
||||
internal class VisaWalletSubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val stateController: WalletStateController,
|
||||
private val isRefresh: Boolean,
|
||||
private val getVisaCurrencyUseCase: GetVisaCurrencyUseCase,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import com.tangem.domain.tokens.model.TotalFiatBalance
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
|
@ -88,8 +87,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
private fun loadArtworks(wallets: List<UserWallet>): Flow<HashMap<UserWalletId, ArtworkModel>> {
|
||||
return flow {
|
||||
emit(hashMapOf()) // emits right away so the transform doesn't wait for the images' loading to finish
|
||||
wallets.forEach { wallet ->
|
||||
wallet.requireColdWallet()
|
||||
wallets.filterIsInstance<UserWallet.Cold>().forEach { wallet ->
|
||||
val artwork = getCardImageUseCase(
|
||||
cardId = wallet.cardId,
|
||||
manufacturerName = wallet.scanResponse.card.manufacturer.name,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue