Updated on 2026-08-14

This commit is contained in:
Tangem 2024-10-25 12:16:14 +04:00
parent 5ae666646f
commit 7834cc5a87
8 changed files with 79 additions and 27 deletions

View file

@ -8,9 +8,9 @@ import com.tangem.core.analytics.filter.OneTimeEventFilter
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
import com.tangem.core.navigation.share.ShareManager
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.datasource.asset.loader.AssetLoader
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
@ -51,7 +51,7 @@ interface ApplicationEntryPoint {
fun getAppStateHolder(): AppStateHolder
fun getAssetLoader(): AssetLoader
fun getIssuersConfigStorage(): IssuersConfigStorage
fun getFeatureTogglesManager(): FeatureTogglesManager

View file

@ -20,10 +20,10 @@ import com.tangem.core.analytics.models.Basic.TransactionSent.WalletForm
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
import com.tangem.datasource.api.common.MoshiConverter
import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
import com.tangem.datasource.asset.loader.AssetLoader
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
@ -86,8 +86,8 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
private val environmentConfigStorage: EnvironmentConfigStorage
get() = entryPoint.getEnvironmentConfigStorage()
private val assetLoader: AssetLoader
get() = entryPoint.getAssetLoader()
private val issuersConfigStorage: IssuersConfigStorage
get() = entryPoint.getIssuersConfigStorage()
private val featureTogglesManager: FeatureTogglesManager
get() = entryPoint.getFeatureTogglesManager()
@ -269,7 +269,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
saveBlockchainErrorUseCase = saveBlockchainErrorUseCase,
sendFeedbackEmailUseCase = sendFeedbackEmailUseCase,
getCardInfoUseCase = getCardInfoUseCase,
assetLoader = assetLoader,
issuersConfigStorage = issuersConfigStorage,
urlOpener = urlOpener,
shareManager = shareManager,
appRouter = appRouter,

View file

@ -13,17 +13,19 @@ import com.tangem.tap.common.extensions.inject
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.store
import com.tangem.tap.tangemSdkManager
import kotlinx.coroutines.flow.MutableStateFlow
class TwinCardsManager(card: CardDTO) {
private val issuersConfigStorage by lazy(mode = LazyThreadSafetyMode.NONE) {
store.inject(DaggerGraphState::issuersConfigStorage)
}
private val firstCardId: String = card.cardId
private val publicKey: String = card.issuer.publicKey.toHexString()
private var currentCardPublicKey: String? = null
private var secondCardPublicKey: String? = null
private val issuerKeyPairFlow = MutableStateFlow<KeyPair?>(value = null)
suspend fun createFirstWallet(message: Message): CompletionResult<CreateWalletResponse> {
val response = tangemSdkManager.createFirstTwinWallet(cardId = firstCardId, initialMessage = message)
@ -70,23 +72,11 @@ class TwinCardsManager(card: CardDTO) {
}
private suspend fun getIssuerKeys(): KeyPair {
issuerKeyPairFlow.value?.let { return it }
val assetLoader = store.inject(DaggerGraphState::assetLoader)
val issuer = assetLoader.loadList<Issuer>(fileName = ISSUERS_FILE_NAME)
.first { it.publicKey == publicKey }
val issuer = issuersConfigStorage.getConfig().first { it.publicKey == publicKey }
return KeyPair(
publicKey = issuer.publicKey.hexToBytes(),
privateKey = issuer.privateKey.hexToBytes(),
).also {
issuerKeyPairFlow.value = it
}
)
}
private companion object {
const val ISSUERS_FILE_NAME = "tangem-app-config/issuers"
}
}
private class Issuer(val privateKey: String, val publicKey: String)
}

View file

@ -7,8 +7,8 @@ import com.tangem.common.routing.AppRouter
import com.tangem.core.navigation.email.EmailSender
import com.tangem.core.navigation.share.ShareManager
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.datasource.asset.loader.AssetLoader
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
@ -79,7 +79,7 @@ data class DaggerGraphState(
val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase? = null,
val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase? = null,
val getCardInfoUseCase: GetCardInfoUseCase? = null,
val assetLoader: AssetLoader? = null,
val issuersConfigStorage: IssuersConfigStorage? = null,
val stakingRouter: StakingRouter? = null,
val urlOpener: UrlOpener? = null,
val shareManager: ShareManager? = null,

View file

@ -4,6 +4,8 @@ import com.tangem.datasource.asset.loader.AssetLoader
import com.tangem.datasource.local.config.environment.DefaultEnvironmentConfigStorage
import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
import com.tangem.datasource.local.config.issuers.DefaultIssuersConfigStorage
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
import com.tangem.datasource.local.config.providers.BlockchainProvidersStorage
import com.tangem.datasource.local.config.providers.DefaultBlockchainProvidersStorage
import com.tangem.datasource.local.config.testnet.DefaultTestnetTokensStorage
@ -30,7 +32,7 @@ internal object ConfigModule {
@Provides
@Singleton
fun providesTestnetTokensStorage(assetLoader: AssetLoader): TestnetTokensStorage {
fun provideTestnetTokensStorage(assetLoader: AssetLoader): TestnetTokensStorage {
return DefaultTestnetTokensStorage(assetLoader)
}
@ -42,4 +44,13 @@ internal object ConfigModule {
runtimeStateStore = RuntimeStateStore(defaultValue = emptyMap()),
)
}
@Provides
@Singleton
fun provideIssuersConfigStorage(assetLoader: AssetLoader): IssuersConfigStorage {
return DefaultIssuersConfigStorage(
assetLoader = assetLoader,
runtimeStateStore = RuntimeStateStore(defaultValue = emptyList()),
)
}
}

View file

@ -0,0 +1,27 @@
package com.tangem.datasource.local.config.issuers
import com.tangem.datasource.asset.loader.AssetLoader
import com.tangem.datasource.local.config.issuers.models.Issuer
import com.tangem.datasource.local.datastore.RuntimeStateStore
internal class DefaultIssuersConfigStorage(
private val assetLoader: AssetLoader,
private val runtimeStateStore: RuntimeStateStore<List<Issuer>>,
) : IssuersConfigStorage {
override suspend fun getConfig(): List<Issuer> {
val cachedData = runtimeStateStore.get().value
if (cachedData.isNotEmpty()) return cachedData
val issuers = assetLoader.loadList<Issuer>(fileName = ISSUERS_FILE_NAME)
runtimeStateStore.store(value = issuers)
return issuers
}
private companion object {
const val ISSUERS_FILE_NAME = "tangem-app-config/issuers"
}
}

View file

@ -0,0 +1,14 @@
package com.tangem.datasource.local.config.issuers
import com.tangem.datasource.local.config.issuers.models.Issuer
/**
* Storage for list of Twins [Issuer]
*
[REDACTED_AUTHOR]
*/
interface IssuersConfigStorage {
/** Get config */
suspend fun getConfig(): List<Issuer>
}

View file

@ -0,0 +1,10 @@
package com.tangem.datasource.local.config.issuers.models
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Issuer(
@Json(name = "privateKey") val privateKey: String,
@Json(name = "publicKey") val publicKey: String,
)