Updated on 2026-08-14
This commit is contained in:
parent
ca03f18d81
commit
cfdc1ea05c
19 changed files with 211 additions and 38 deletions
|
|
@ -2,7 +2,7 @@ package com.tangem.tap.common.redux.legacy
|
|||
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.redux.LegacyAction
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
@ -37,8 +37,7 @@ internal object LegacyMiddleware {
|
|||
)
|
||||
store.dispatchWithMain(
|
||||
DetailsAction.PrepareScreen(
|
||||
// TODO [REDACTED_TASK_KEY]
|
||||
scanResponse = selectedUserWallet.requireColdWallet().scanResponse,
|
||||
scanResponse = (selectedUserWallet as? UserWallet.Cold)?.scanResponse,
|
||||
initializedAppSettingsState = initializedAppSettingsStateContent,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.domain.transaction.FeeRepository
|
|||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.usecase.*
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.tap.domain.hot.TangemHotSigner
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -43,6 +44,7 @@ internal object TransactionDomainModule {
|
|||
transactionRepository: TransactionRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
tangemHotSignerFactory: TangemHotSigner.Factory,
|
||||
): SendTransactionUseCase {
|
||||
return SendTransactionUseCase(
|
||||
demoConfig = DemoConfig(),
|
||||
|
|
@ -50,6 +52,7 @@ internal object TransactionDomainModule {
|
|||
transactionRepository = transactionRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
|
||||
getHotSigner = tangemHotSignerFactory::create,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.tap.di.hot
|
||||
|
||||
import com.tangem.hot.sdk.TangemHotSdk
|
||||
import com.tangem.tap.domain.hot.HotWalletPasswordRequester
|
||||
import com.tangem.tap.features.hot.DefaultHotWalletPasswordRequester
|
||||
import com.tangem.tap.features.hot.TangemHotSDKProxy
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
|
@ -15,4 +17,8 @@ internal interface TangemHotSdkModule {
|
|||
@Binds
|
||||
@Singleton
|
||||
fun bindTangemHotSdk(proxy: TangemHotSDKProxy): TangemHotSdk
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindHotWalletPasswordRequester(impl: DefaultHotWalletPasswordRequester): HotWalletPasswordRequester
|
||||
}
|
||||
|
|
@ -61,7 +61,11 @@ internal class DefaultDerivationsRepository(
|
|||
userWalletsStore.getSyncOrNull(userWalletId) ?: error("User wallet not found")
|
||||
}
|
||||
|
||||
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
if (userWallet is UserWallet.Hot) {
|
||||
return
|
||||
}
|
||||
|
||||
userWallet.requireColdWallet()
|
||||
|
||||
if (!userWallet.scanResponse.card.settings.isHDWalletAllowed) {
|
||||
Timber.d("Nothing to derive")
|
||||
|
|
@ -84,8 +88,12 @@ internal class DefaultDerivationsRepository(
|
|||
): Boolean {
|
||||
val userWallet = userWalletsStore.getSyncOrNull(userWalletId) ?: error("User wallet not found")
|
||||
|
||||
if (userWallet is UserWallet.Hot) {
|
||||
return false
|
||||
}
|
||||
|
||||
val derivations =
|
||||
MissedDerivationsFinder(scanResponse = userWallet.requireColdWallet().scanResponse) // TODO [REDACTED_TASK_KEY]
|
||||
MissedDerivationsFinder(scanResponse = userWallet.requireColdWallet().scanResponse)
|
||||
.findByNetworks(
|
||||
networksWithDerivationPath.mapNotNull { (backendId, extraDerivationPath) ->
|
||||
networkFactory.create(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
package com.tangem.tap.domain.hot
|
||||
|
||||
import com.tangem.hot.sdk.TangemHotSdk
|
||||
import com.tangem.hot.sdk.model.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class HotWalletAccessor @Inject constructor(
|
||||
private val tangemHotSdk: TangemHotSdk,
|
||||
private val hotWalletPasswordRequester: HotWalletPasswordRequester,
|
||||
) {
|
||||
|
||||
suspend fun signHashes(hotWalletId: HotWalletId, dataToSign: List<DataToSign>): List<SignedData> {
|
||||
val auth = when (hotWalletId.authType) {
|
||||
HotWalletId.AuthType.NoPassword -> HotAuth.NoAuth
|
||||
HotWalletId.AuthType.Password -> {
|
||||
hotWalletPasswordRequester.requestPassword(hotWalletId)
|
||||
}
|
||||
HotWalletId.AuthType.Biometry -> HotAuth.Biometry
|
||||
}
|
||||
|
||||
return runCatching {
|
||||
tangemHotSdk.signHashes(
|
||||
unlockHotWallet = UnlockHotWallet(
|
||||
walletId = hotWalletId,
|
||||
auth = auth,
|
||||
),
|
||||
dataToSign = dataToSign,
|
||||
)
|
||||
}.getOrElse {
|
||||
if (hotWalletId.authType == HotWalletId.AuthType.Biometry) {
|
||||
val passwordAuth = hotWalletPasswordRequester.requestPassword(hotWalletId)
|
||||
tangemHotSdk.signHashes(
|
||||
unlockHotWallet = UnlockHotWallet(
|
||||
walletId = hotWalletId,
|
||||
auth = passwordAuth,
|
||||
),
|
||||
dataToSign = dataToSign,
|
||||
)
|
||||
} else {
|
||||
throw it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.tap.domain.hot
|
||||
|
||||
import com.tangem.hot.sdk.model.HotAuth
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
|
||||
interface HotWalletPasswordRequester {
|
||||
|
||||
suspend fun requestPassword(hotWalletId: HotWalletId): HotAuth.Password
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package com.tangem.tap.domain.hot
|
||||
|
||||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.map
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.hot.sdk.model.DataToSign
|
||||
import com.tangem.operations.sign.SignData
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
class TangemHotSigner @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet.Hot,
|
||||
private val hotWalletAccessor: HotWalletAccessor,
|
||||
) : TransactionSigner {
|
||||
|
||||
override suspend fun sign(hash: ByteArray, publicKey: Wallet.PublicKey): CompletionResult<ByteArray> {
|
||||
return sign(listOf(hash), publicKey).map { it.first() }
|
||||
}
|
||||
|
||||
override suspend fun sign(
|
||||
hashes: List<ByteArray>,
|
||||
publicKey: Wallet.PublicKey,
|
||||
): CompletionResult<List<ByteArray>> {
|
||||
val wallet = userWallet.wallets.orEmpty().firstOrNull { it.publicKey == publicKey.seedKey }
|
||||
?: return CompletionResult.Failure(
|
||||
TangemSdkError.ExceptionError(IllegalStateException("wallet is locked")),
|
||||
)
|
||||
|
||||
val result = hotWalletAccessor.signHashes(
|
||||
hotWalletId = userWallet.hotWalletId,
|
||||
dataToSign = listOf(
|
||||
DataToSign(
|
||||
curve = wallet.curve,
|
||||
hashes = hashes,
|
||||
derivationPath = publicKey.derivationPath,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
return CompletionResult.Success(result.map { it.signatures }.flatten())
|
||||
}
|
||||
|
||||
override suspend fun multiSign(
|
||||
dataToSign: List<SignData>,
|
||||
publicKey: Wallet.PublicKey,
|
||||
): CompletionResult<Map<ByteArray, ByteArray>> {
|
||||
val result = hotWalletAccessor.signHashes(
|
||||
hotWalletId = userWallet.hotWalletId,
|
||||
dataToSign = dataToSign.map { signData ->
|
||||
val wallet = userWallet.wallets.orEmpty().firstOrNull { it.publicKey == signData.publicKey }
|
||||
?: return CompletionResult.Failure(
|
||||
TangemSdkError.ExceptionError(IllegalStateException("wallet is locked")),
|
||||
)
|
||||
|
||||
DataToSign(
|
||||
curve = wallet.curve,
|
||||
hashes = listOf(signData.hash),
|
||||
derivationPath = signData.derivationPath,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
return CompletionResult.Success(
|
||||
result.mapIndexed { index, data ->
|
||||
dataToSign[index].publicKey to data.signatures.first()
|
||||
}.toMap(),
|
||||
)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(@Assisted userWallet: UserWallet.Hot): TangemHotSigner
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import org.rekotlin.Action
|
|||
sealed class DetailsAction : Action {
|
||||
|
||||
data class PrepareScreen(
|
||||
val scanResponse: ScanResponse,
|
||||
val scanResponse: ScanResponse?,
|
||||
val initializedAppSettingsState: AppSettingsState,
|
||||
) : DetailsAction()
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.core.decompose.model.getOrCreateModel
|
|||
import com.tangem.core.ui.components.SystemBarsIconsDisposable
|
||||
import com.tangem.core.ui.utils.ChangeRootBackgroundColorEffect
|
||||
import com.tangem.core.ui.utils.findActivity
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.home.api.HomeComponent
|
||||
import com.tangem.tap.features.home.compose.StoriesScreen
|
||||
|
|
@ -29,6 +30,7 @@ import org.rekotlin.StoreSubscriber
|
|||
internal class DefaultHomeComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted params: Unit,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) : HomeComponent, AppComponentContext by appComponentContext, StoreSubscriber<HomeState> {
|
||||
|
||||
private val model: HomeModel = getOrCreateModel()
|
||||
|
|
@ -58,7 +60,7 @@ internal class DefaultHomeComponent @AssistedInject constructor(
|
|||
val activity = LocalContext.current.findActivity()
|
||||
BackHandler(onBack = activity::finish)
|
||||
SystemBarsIconsDisposable(darkIcons = false)
|
||||
if (homeState.value.isV2StoriesEnabled) {
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
StoriesScreenV2(
|
||||
homeState = homeState,
|
||||
onCreateNewWalletButtonClick = model::onCreateNewWalletScreen,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import org.rekotlin.StateType
|
|||
// todo refactor [REDACTED_TASK_KEY]
|
||||
data class HomeState(
|
||||
val scanInProgress: Boolean = false,
|
||||
val isV2StoriesEnabled: Boolean = false,
|
||||
val stories: ImmutableList<Stories> = getRestrictedStories().toImmutableList(),
|
||||
) : StateType {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.tap.features.hot
|
||||
|
||||
import com.tangem.hot.sdk.model.HotAuth
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.tap.domain.hot.HotWalletPasswordRequester
|
||||
import javax.inject.Inject
|
||||
|
||||
class DefaultHotWalletPasswordRequester @Inject constructor() : HotWalletPasswordRequester {
|
||||
|
||||
override suspend fun requestPassword(hotWalletId: HotWalletId): HotAuth.Password {
|
||||
return HotAuth.Password("TODO [REDACTED_TASK_KEY]".toCharArray()) // TODO [REDACTED_TASK_KEY]
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,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.isLocked
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
/**
|
||||
|
|
@ -57,13 +56,19 @@ class UserWalletItemUMConverter(
|
|||
}
|
||||
|
||||
private fun getInfo(userWallet: UserWallet): UserWalletItemUM.Information.Loaded {
|
||||
userWallet.requireColdWallet()
|
||||
val cardCount = userWallet.getCardsCount() ?: 1
|
||||
val text = TextReference.PluralRes(
|
||||
id = R.plurals.card_label_card_count,
|
||||
count = cardCount,
|
||||
formatArgs = wrappedList(cardCount),
|
||||
)
|
||||
val text = when (userWallet) {
|
||||
is UserWallet.Cold -> {
|
||||
val cardCount = userWallet.getCardsCount() ?: 1
|
||||
TextReference.PluralRes(
|
||||
id = R.plurals.card_label_card_count,
|
||||
count = cardCount,
|
||||
formatArgs = wrappedList(cardCount),
|
||||
)
|
||||
}
|
||||
is UserWallet.Hot -> {
|
||||
TextReference.Res(R.string.hw_mobile_wallet)
|
||||
}
|
||||
}
|
||||
return UserWalletItemUM.Information.Loaded(text)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,5 +46,9 @@
|
|||
{
|
||||
"name": "WALLET_BALANCE_FETCHER_ENABLED",
|
||||
"version": "5.27.0"
|
||||
},
|
||||
{
|
||||
"name": "HOT_WALLET_ENABLED",
|
||||
"version": "undefined"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -564,7 +564,6 @@ internal class DefaultCurrenciesRepository(
|
|||
userWallet: UserWallet,
|
||||
currencyRawId: CryptoCurrency.RawID,
|
||||
): Flow<List<CryptoCurrency>> {
|
||||
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
return when {
|
||||
userWallet.isMultiCurrency -> {
|
||||
getSavedUserTokensResponse(userWallet.walletId).map { storedTokens ->
|
||||
|
|
@ -581,7 +580,7 @@ internal class DefaultCurrenciesRepository(
|
|||
|
||||
else -> {
|
||||
val currencies =
|
||||
if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
if (userWallet.requireColdWallet().scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
getSingleCurrencyWalletWithCardCurrencies(userWallet.walletId)
|
||||
} else {
|
||||
val currency =
|
||||
|
|
@ -619,9 +618,8 @@ internal class DefaultCurrenciesRepository(
|
|||
)
|
||||
}
|
||||
|
||||
override fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver {
|
||||
return userWalletsStore.getSyncStrict(userWalletId)
|
||||
.requireColdWallet().cardTypesResolver // TODO [REDACTED_TASK_KEY]
|
||||
override fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver? {
|
||||
return (userWalletsStore.getSyncStrict(userWalletId) as? UserWallet.Cold)?.cardTypesResolver
|
||||
}
|
||||
|
||||
private fun getMultiCurrencyWalletCurrencies(userWallet: UserWallet): Flow<List<CryptoCurrency>> {
|
||||
|
|
|
|||
|
|
@ -265,5 +265,5 @@ interface CurrenciesRepository {
|
|||
suspend fun syncTokens(userWalletId: UserWalletId)
|
||||
|
||||
@Throws
|
||||
fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver
|
||||
fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver?
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ class WalletBalanceFetcher internal constructor(
|
|||
val cardTypesResolver = currenciesRepository.getCardTypesResolver(userWalletId = userWalletId)
|
||||
|
||||
val fetcher = when {
|
||||
cardTypesResolver.isMultiwalletAllowed() -> multiWalletBalanceFetcher
|
||||
cardTypesResolver == null || cardTypesResolver.isMultiwalletAllowed() -> multiWalletBalanceFetcher
|
||||
cardTypesResolver.isSingleWalletWithToken() -> singleWalletWithTokenBalanceFetcher
|
||||
cardTypesResolver.isSingleWallet() -> singleWalletBalanceFetcher
|
||||
else -> error("Unknown type of wallet: $userWalletId")
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import com.tangem.domain.transaction.error.SendTransactionError
|
|||
import com.tangem.domain.transaction.error.parseWrappedError
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
|
||||
class SendTransactionUseCase(
|
||||
private val demoConfig: DemoConfig,
|
||||
|
|
@ -33,6 +32,7 @@ class SendTransactionUseCase(
|
|||
private val transactionRepository: TransactionRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
private val getHotSigner: (UserWallet.Hot) -> TransactionSigner,
|
||||
) {
|
||||
suspend operator fun invoke(
|
||||
txsData: List<TransactionData>,
|
||||
|
|
@ -40,22 +40,30 @@ class SendTransactionUseCase(
|
|||
network: Network,
|
||||
sendMode: TransactionSender.MultipleTransactionSendMode,
|
||||
): Either<SendTransactionError, List<String>> {
|
||||
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
val signer = when (userWallet) {
|
||||
is UserWallet.Cold -> {
|
||||
val card = userWallet.scanResponse.card
|
||||
val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins
|
||||
|
||||
val card = userWallet.scanResponse.card
|
||||
val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins
|
||||
val coldSigner = cardSdkConfigRepository.getCommonSigner(
|
||||
cardId = card.cardId.takeIf { isCardNotBackedUp },
|
||||
twinKey = TwinKey.getOrNull(scanResponse = userWallet.scanResponse),
|
||||
)
|
||||
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(
|
||||
cardId = card.cardId.takeIf { isCardNotBackedUp },
|
||||
twinKey = TwinKey.getOrNull(scanResponse = userWallet.scanResponse),
|
||||
)
|
||||
coldSigner
|
||||
}
|
||||
is UserWallet.Hot -> {
|
||||
getHotSigner(userWallet)
|
||||
}
|
||||
}
|
||||
|
||||
val linkedTerminal = cardSdkConfigRepository.isLinkedTerminal()
|
||||
if (userWallet.scanResponse.card.isStart2Coin) {
|
||||
if (userWallet is UserWallet.Cold && userWallet.scanResponse.card.isStart2Coin) {
|
||||
cardSdkConfigRepository.setLinkedTerminal(false)
|
||||
}
|
||||
|
||||
val sendResult = try {
|
||||
if (demoConfig.isDemoCardId(cardId = userWallet.cardId)) {
|
||||
if (userWallet is UserWallet.Cold && demoConfig.isDemoCardId(cardId = userWallet.cardId)) {
|
||||
sendDemo(
|
||||
userWallet = userWallet,
|
||||
network = network,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.blockchain.common.derivation.DerivationStyle
|
||||
import com.tangem.domain.models.MobileWallet
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
|
||||
import com.tangem.hot.sdk.TangemHotSdk
|
||||
import com.tangem.hot.sdk.model.DeriveWalletRequest
|
||||
|
|
@ -58,7 +57,7 @@ class HotUserWalletBuilder @AssistedInject constructor(
|
|||
|
||||
UserWallet.Hot(
|
||||
name = generateWalletNameUseCase.invokeForHot(),
|
||||
walletId = UserWalletId(wallets.first().publicKey),
|
||||
walletId = UserWalletIdBuilder.walletPublicKey(wallets.first().publicKey),
|
||||
hotWalletId = hotWalletId,
|
||||
wallets = wallets,
|
||||
backedUp = false,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ 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.isMultiCurrency
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.features.markets.impl.R
|
||||
|
|
@ -194,8 +193,7 @@ internal class MarketsPortfolioModel @Inject constructor(
|
|||
private fun loadArtworks(wallets: List<UserWallet>) {
|
||||
modelScope.launch {
|
||||
loadArtworksMutex.withLock {
|
||||
wallets.forEach { wallet ->
|
||||
wallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
wallets.filterIsInstance<UserWallet.Cold>().forEach { wallet ->
|
||||
if (!loadedArtworks.containsKey(wallet.walletId)) {
|
||||
val artwork = getCardImageUseCase(
|
||||
cardId = wallet.cardId,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue