Updated on 2026-08-14
This commit is contained in:
parent
5bca4d6107
commit
ac1a08f7f9
9 changed files with 155 additions and 87 deletions
|
|
@ -52,31 +52,6 @@ class DerivationManagerImpl(
|
|||
AddCryptoCurrenciesUseCase(currenciesRepository, networksRepository)
|
||||
}
|
||||
|
||||
override suspend fun deriveMissingBlockchains(currency: Currency) = suspendCoroutine { continuation ->
|
||||
val blockchain = Blockchain.fromNetworkId(currency.networkId)
|
||||
val card = appStateHolder.getActualCard()
|
||||
if (blockchain != null && card != null) {
|
||||
val appToken = getAppToken(currency)
|
||||
val scanResponse = appStateHolder.scanResponse
|
||||
if (scanResponse != null) {
|
||||
val blockchainNetwork = BlockchainNetwork(blockchain, scanResponse.derivationStyleProvider)
|
||||
val appCurrency = com.tangem.tap.domain.model.Currency.fromBlockchainNetwork(
|
||||
blockchainNetwork,
|
||||
appToken,
|
||||
)
|
||||
deriveMissingBlockchains(
|
||||
scanResponse = scanResponse,
|
||||
currencyList = listOf(appCurrency),
|
||||
onSuccess = { continuation.resumeWith(Result.success(true)) },
|
||||
) {
|
||||
continuation.resumeWith(Result.failure(it))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continuation.resumeWith(Result.failure(IllegalStateException("no blockchain or card found")))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun deriveAndAddTokens(currency: Currency) = suspendCoroutine { continuation ->
|
||||
val selectedUserWallet = requireNotNull(
|
||||
userWalletsListManager.selectedUserWalletSync,
|
||||
|
|
@ -136,27 +111,6 @@ class DerivationManagerImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getDerivationPathForBlockchain(networkId: String): String? {
|
||||
val scanResponse = appStateHolder.scanResponse
|
||||
val blockchain = Blockchain.fromNetworkId(networkId)
|
||||
if (scanResponse != null && blockchain != null) {
|
||||
return blockchain.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle())?.rawPath
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun hasDerivation(networkId: String, derivationPath: String): Boolean {
|
||||
val scanResponse = appStateHolder.scanResponse
|
||||
val blockchain = Blockchain.fromNetworkId(networkId)
|
||||
if (scanResponse != null && blockchain != null) {
|
||||
return scanResponse.hasDerivation(
|
||||
blockchain,
|
||||
derivationPath,
|
||||
)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private suspend fun addToken(
|
||||
userWalletId: UserWalletId,
|
||||
blockchain: Blockchain,
|
||||
|
|
|
|||
|
|
@ -8,14 +8,22 @@ plugins {
|
|||
|
||||
dependencies {
|
||||
|
||||
/** Project*/
|
||||
implementation(project(":core:datasource"))
|
||||
implementation(project(":core:utils"))
|
||||
implementation(project(":features:referral:domain"))
|
||||
|
||||
/** Project */
|
||||
implementation(projects.core.datasource)
|
||||
implementation(projects.core.utils)
|
||||
|
||||
/** Data modules */
|
||||
implementation(projects.data.tokens)
|
||||
|
||||
/** Domain modules */
|
||||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.features.referral.domain)
|
||||
|
||||
/** Libs */
|
||||
implementation(project(":libs:auth"))
|
||||
implementation(projects.libs.auth)
|
||||
|
||||
/** Time */
|
||||
implementation(deps.jodatime)
|
||||
|
|
@ -23,4 +31,7 @@ dependencies {
|
|||
/** DI */
|
||||
implementation(deps.hilt.android)
|
||||
kapt(deps.hilt.kapt)
|
||||
|
||||
/** Tangem deps */
|
||||
implementation(deps.tangem.blockchain)
|
||||
}
|
||||
|
|
@ -1,11 +1,20 @@
|
|||
package com.tangem.feature.referral.data
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.data.tokens.utils.CryptoCurrencyFactory
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.StartReferralBody
|
||||
import com.tangem.datasource.demo.DemoModeDatasource
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.common.extensions.fromNetworkId
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.referral.converters.ReferralConverter
|
||||
import com.tangem.feature.referral.domain.ReferralRepository
|
||||
import com.tangem.feature.referral.domain.models.ReferralData
|
||||
import com.tangem.feature.referral.domain.models.TokenData
|
||||
import com.tangem.lib.auth.AuthProvider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -17,6 +26,7 @@ internal class ReferralRepositoryImpl @Inject constructor(
|
|||
private val coroutineDispatcher: CoroutineDispatcherProvider,
|
||||
private val demoModeDatasource: DemoModeDatasource,
|
||||
private val authProvider: AuthProvider,
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
) : ReferralRepository {
|
||||
|
||||
override val isDemoMode: Boolean
|
||||
|
|
@ -55,4 +65,38 @@ internal class ReferralRepositoryImpl @Inject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getCryptoCurrency(userWalletId: UserWalletId, tokenData: TokenData): CryptoCurrency? {
|
||||
val userWallet = userWalletsStore.getSyncOrNull(userWalletId) ?: error("Wallet $userWalletId not found")
|
||||
val derivationStyleProvider = userWallet.scanResponse.derivationStyleProvider
|
||||
|
||||
val blockchain = Blockchain.fromNetworkId(tokenData.networkId)
|
||||
?: error("Blockchain ${tokenData.networkId} not found")
|
||||
|
||||
val cryptoCurrencyFactory = CryptoCurrencyFactory()
|
||||
|
||||
val contractAddress = tokenData.contractAddress
|
||||
val decimalCount = tokenData.decimalCount
|
||||
return if (contractAddress != null && decimalCount != null) {
|
||||
val sdkToken = Token(
|
||||
name = tokenData.name,
|
||||
symbol = tokenData.symbol,
|
||||
contractAddress = contractAddress,
|
||||
decimals = decimalCount,
|
||||
id = tokenData.id,
|
||||
)
|
||||
cryptoCurrencyFactory.createToken(
|
||||
sdkToken = sdkToken,
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
)
|
||||
} else {
|
||||
cryptoCurrencyFactory.createCoin(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.referral.di
|
|||
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.demo.DemoModeDatasource
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.feature.referral.converters.ReferralConverter
|
||||
import com.tangem.feature.referral.data.ReferralRepositoryImpl
|
||||
import com.tangem.feature.referral.domain.ReferralRepository
|
||||
|
|
@ -25,6 +26,7 @@ class ReferralRepositoryModule {
|
|||
coroutineDispatcherProvider: CoroutineDispatcherProvider,
|
||||
demoModeDatasource: DemoModeDatasource,
|
||||
authProvider: AuthProvider,
|
||||
userWalletsStore: UserWalletsStore,
|
||||
): ReferralRepository {
|
||||
return ReferralRepositoryImpl(
|
||||
referralApi = tangemTechApi,
|
||||
|
|
@ -32,6 +34,7 @@ class ReferralRepositoryModule {
|
|||
coroutineDispatcher = coroutineDispatcherProvider,
|
||||
demoModeDatasource = demoModeDatasource,
|
||||
authProvider = authProvider,
|
||||
userWalletsStore = userWalletsStore,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -17,13 +17,23 @@ dependencies {
|
|||
/** Core modules */
|
||||
implementation(projects.libs.crypto)
|
||||
|
||||
/** Domain modules */
|
||||
implementation(projects.domain.card)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets)
|
||||
implementation(projects.domain.wallets.models)
|
||||
|
||||
/** Feature Apis */
|
||||
implementation(projects.features.tester.api)
|
||||
implementation(projects.features.wallet.api)
|
||||
|
||||
/** Dependencies */
|
||||
implementation(deps.arrow.core)
|
||||
implementation(deps.jodatime)
|
||||
implementation(deps.timber)
|
||||
|
||||
/** DI */
|
||||
implementation(deps.hilt.core)
|
||||
implementation(deps.hilt.android)
|
||||
kapt(deps.hilt.kapt)
|
||||
}
|
||||
|
|
@ -1,16 +1,27 @@
|
|||
package com.tangem.feature.referral.domain
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.domain.card.DerivePublicKeysUseCase
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.feature.referral.domain.converter.TokensConverter
|
||||
import com.tangem.feature.referral.domain.models.ReferralData
|
||||
import com.tangem.feature.referral.domain.models.TokenData
|
||||
import com.tangem.features.tester.api.TesterFeatureToggles
|
||||
import com.tangem.lib.crypto.DerivationManager
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class ReferralInteractorImpl(
|
||||
private val repository: ReferralRepository,
|
||||
private val derivationManager: DerivationManager,
|
||||
private val userWalletManager: UserWalletManager,
|
||||
private val tokensConverter: TokensConverter,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val testerFeatureToggles: TesterFeatureToggles,
|
||||
) : ReferralInteractor {
|
||||
|
||||
private val tokensForReferral = mutableListOf<TokenData>()
|
||||
|
|
@ -27,21 +38,59 @@ internal class ReferralInteractorImpl(
|
|||
}
|
||||
|
||||
override suspend fun startReferral(): ReferralData {
|
||||
if (tokensForReferral.isNotEmpty()) {
|
||||
val currency = tokensConverter.convert(tokensForReferral.first())
|
||||
val derivationPath = derivationManager.deriveAndAddTokens(currency)
|
||||
val publicAddress = userWalletManager.getWalletAddress(currency.networkId, derivationPath)
|
||||
return repository.startReferral(
|
||||
walletId = userWalletManager.getWalletId(),
|
||||
networkId = currency.networkId,
|
||||
tokenId = currency.id,
|
||||
address = publicAddress,
|
||||
)
|
||||
return if (tokensForReferral.isNotEmpty()) {
|
||||
if (testerFeatureToggles.isDerivePublicKeysRefactoringEnabled) {
|
||||
startReferralNew(tokenData = tokensForReferral.first())
|
||||
} else {
|
||||
// TODO: delete [REDACTED_JIRA]
|
||||
startReferralLegacy(tokenData = tokensForReferral.first())
|
||||
}
|
||||
} else {
|
||||
error("Tokens for ref is empty")
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun startReferralNew(tokenData: TokenData): ReferralData {
|
||||
val userWallet = getSelectedWalletSyncUseCase().getOrElse {
|
||||
error("Failed to get selected wallet: $it")
|
||||
}
|
||||
|
||||
val cryptoCurrency = repository.getCryptoCurrency(userWalletId = userWallet.walletId, tokenData = tokenData)
|
||||
derivePublicKeysUseCase(userWallet.walletId, listOfNotNull(cryptoCurrency)).getOrElse {
|
||||
Timber.e("Failed to derive public keys: $it")
|
||||
throw it
|
||||
}
|
||||
|
||||
addCryptoCurrenciesUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
currencies = listOfNotNull(cryptoCurrency),
|
||||
)
|
||||
|
||||
val publicAddress = userWalletManager.getWalletAddress(
|
||||
networkId = tokenData.networkId,
|
||||
derivationPath = cryptoCurrency?.network?.derivationPath?.value,
|
||||
)
|
||||
|
||||
return repository.startReferral(
|
||||
walletId = userWalletManager.getWalletId(),
|
||||
networkId = tokenData.networkId,
|
||||
tokenId = tokenData.id,
|
||||
address = publicAddress,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun startReferralLegacy(tokenData: TokenData): ReferralData {
|
||||
val currency = tokensConverter.convert(tokenData)
|
||||
val derivationPath = derivationManager.deriveAndAddTokens(currency)
|
||||
val publicAddress = userWalletManager.getWalletAddress(currency.networkId, derivationPath)
|
||||
return repository.startReferral(
|
||||
walletId = userWalletManager.getWalletId(),
|
||||
networkId = currency.networkId,
|
||||
tokenId = currency.id,
|
||||
address = publicAddress,
|
||||
)
|
||||
}
|
||||
|
||||
private fun saveReferralTokens(tokens: List<TokenData>) {
|
||||
tokensForReferral.clear()
|
||||
tokensForReferral.addAll(tokens)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package com.tangem.feature.referral.domain
|
||||
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.referral.domain.models.ReferralData
|
||||
import com.tangem.feature.referral.domain.models.TokenData
|
||||
|
||||
interface ReferralRepository {
|
||||
|
||||
|
|
@ -11,4 +14,6 @@ interface ReferralRepository {
|
|||
|
||||
/** Starts user referral program */
|
||||
suspend fun startReferral(walletId: String, networkId: String, tokenId: String, address: String): ReferralData
|
||||
|
||||
suspend fun getCryptoCurrency(userWalletId: UserWalletId, tokenData: TokenData): CryptoCurrency?
|
||||
}
|
||||
|
|
@ -1,34 +1,46 @@
|
|||
package com.tangem.feature.referral.domain.di
|
||||
|
||||
import com.tangem.domain.card.DerivePublicKeysUseCase
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.feature.referral.domain.ReferralInteractor
|
||||
import com.tangem.feature.referral.domain.ReferralInteractorImpl
|
||||
import com.tangem.feature.referral.domain.ReferralRepository
|
||||
import com.tangem.feature.referral.domain.converter.TokensConverter
|
||||
import com.tangem.features.tester.api.TesterFeatureToggles
|
||||
import com.tangem.lib.crypto.DerivationManager
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
import dagger.hilt.android.components.ViewModelComponent
|
||||
import dagger.hilt.android.scopes.ViewModelScoped
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@InstallIn(ViewModelComponent::class)
|
||||
class ReferralDomainModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@ViewModelScoped
|
||||
fun provideReferralInteractor(
|
||||
referralRepository: ReferralRepository,
|
||||
derivationManager: DerivationManager,
|
||||
userWalletManager: UserWalletManager,
|
||||
tokensConverter: TokensConverter,
|
||||
derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
testerFeatureToggles: TesterFeatureToggles,
|
||||
): ReferralInteractor {
|
||||
return ReferralInteractorImpl(
|
||||
repository = referralRepository,
|
||||
derivationManager = derivationManager,
|
||||
userWalletManager = userWalletManager,
|
||||
tokensConverter = tokensConverter,
|
||||
derivePublicKeysUseCase = derivePublicKeysUseCase,
|
||||
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
|
||||
addCryptoCurrenciesUseCase = addCryptoCurrenciesUseCase,
|
||||
testerFeatureToggles = testerFeatureToggles,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,29 +2,9 @@ package com.tangem.lib.crypto
|
|||
|
||||
import com.tangem.lib.crypto.models.Currency
|
||||
|
||||
// FIXME: Migration [REDACTED_JIRA]
|
||||
@Deprecated(message = "Use DerivePublicKeysUseCase instead")
|
||||
interface DerivationManager {
|
||||
|
||||
/**
|
||||
* Derives missing blockchain and returns flag true if did it successfully
|
||||
*
|
||||
* @param currency to derive (Native token or not)
|
||||
*/
|
||||
suspend fun deriveMissingBlockchains(currency: Currency): Boolean
|
||||
|
||||
/**
|
||||
* Returns derivationPath or null for blockchain with given networkId
|
||||
*
|
||||
* @param networkId
|
||||
*/
|
||||
fun getDerivationPathForBlockchain(networkId: String): String?
|
||||
|
||||
/**
|
||||
* Checks that given [networkId] has derivations for [derivationPath]
|
||||
*/
|
||||
fun hasDerivation(networkId: String, derivationPath: String): Boolean
|
||||
|
||||
/**
|
||||
* Makes derivation for [Currency] if it is missing and adds token to wallet
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue