Updated on 2026-08-14
This commit is contained in:
parent
74fa237c0d
commit
3b269e6f6a
13 changed files with 158 additions and 11 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.domain.onramp.repositories.LegacyTopUpRepository
|
||||
import com.tangem.domain.onramp.*
|
||||
import com.tangem.domain.onramp.repositories.HotCryptoRepository
|
||||
import com.tangem.domain.onramp.repositories.OnrampErrorResolver
|
||||
|
|
@ -242,4 +243,10 @@ internal object OnrampDomainModule {
|
|||
fun provideFetchHotCryptoUseCase(hotCryptoRepository: HotCryptoRepository): FetchHotCryptoUseCase {
|
||||
return FetchHotCryptoUseCase(hotCryptoRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetLegacyTopUpUrlUseCase(legacyTopUpRepository: LegacyTopUpRepository): GetLegacyTopUpUrlUseCase {
|
||||
return GetLegacyTopUpUrlUseCase(legacyTopUpRepository)
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ import java.math.BigDecimal
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Deprecated("Remove when navigation refactoring will be implemented")
|
||||
class OnboardingManager(var scanResponse: ScanResponse) {
|
||||
|
||||
private val cardRepository: CardRepository by lazy { store.inject(DaggerGraphState::cardRepository) }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.common.extensions.calculateSha512
|
|||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.common.services.Result
|
||||
import com.tangem.common.services.performRequest
|
||||
import com.tangem.data.onramp.legacy.mercuryoNetwork
|
||||
import com.tangem.domain.core.utils.lceContent
|
||||
import com.tangem.domain.core.utils.lceError
|
||||
import com.tangem.domain.core.utils.lceLoading
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import com.tangem.data.onramp.DefaultOnrampErrorResolver
|
|||
import com.tangem.data.onramp.DefaultOnrampRepository
|
||||
import com.tangem.data.onramp.DefaultOnrampTransactionRepository
|
||||
import com.tangem.data.onramp.converters.error.OnrampErrorConverter
|
||||
import com.tangem.domain.onramp.repositories.LegacyTopUpRepository
|
||||
import com.tangem.data.onramp.legacy.MercuryoTopUpRepository
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.express.models.response.ExpressErrorResponse
|
||||
import com.tangem.datasource.api.onramp.OnrampApi
|
||||
|
|
@ -15,6 +17,7 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi
|
|||
import com.tangem.datasource.crypto.DataSignatureVerifier
|
||||
import com.tangem.datasource.di.NetworkMoshi
|
||||
import com.tangem.datasource.exchangeservice.hotcrypto.HotCryptoResponseStore
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.datasource.local.onramp.countries.OnrampCountriesStore
|
||||
import com.tangem.datasource.local.onramp.currencies.OnrampCurrenciesStore
|
||||
import com.tangem.datasource.local.onramp.pairs.OnrampPairsStore
|
||||
|
|
@ -112,4 +115,16 @@ internal object OnrampDataModule {
|
|||
analyticsEventHandler = analyticsEventHandler,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMercuryoRepository(
|
||||
environmentConfigStorage: EnvironmentConfigStorage,
|
||||
dispatchersProvider: CoroutineDispatcherProvider,
|
||||
): LegacyTopUpRepository {
|
||||
return MercuryoTopUpRepository(
|
||||
environmentConfigStorage = environmentConfigStorage,
|
||||
dispatchersProvider = dispatchersProvider,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
package com.tangem.tap.network.exchangeServices.mercuryo
|
||||
package com.tangem.data.onramp.legacy
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
|
||||
/**
|
||||
* Legacy onboarding note/twins to get top up URL from mercuryo
|
||||
* Map [Blockchain] to ids from [link](https://api.mercuryo.io/v1.6/lib/currencies) [crypto_currencies]
|
||||
*/
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
internal val Blockchain.mercuryoNetwork: String?
|
||||
public val Blockchain.mercuryoNetwork: String?
|
||||
get() {
|
||||
return when (this) {
|
||||
Blockchain.Algorand -> "ALGORAND"
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.tangem.data.onramp.legacy
|
||||
|
||||
import android.net.Uri
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.extensions.calculateSha512
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfig
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.domain.onramp.repositories.LegacyTopUpRepository
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class MercuryoTopUpRepository @Inject constructor(
|
||||
private val environmentConfigStorage: EnvironmentConfigStorage,
|
||||
private val dispatchersProvider: CoroutineDispatcherProvider,
|
||||
) : LegacyTopUpRepository {
|
||||
|
||||
override suspend fun getTopUpUrl(cryptoCurrency: CryptoCurrency, walletAddress: String): String =
|
||||
withContext(dispatchersProvider.default) {
|
||||
val blockchain = Blockchain.fromId(cryptoCurrency.network.id.value)
|
||||
val environmentConfig = environmentConfigStorage.getConfigSync()
|
||||
|
||||
val builder = Uri.Builder()
|
||||
.scheme(LegacyTopUpRepository.SCHEME)
|
||||
.authority("exchange.mercuryo.io")
|
||||
.appendQueryParameter("widget_id", environmentConfig.mercuryoWidgetId)
|
||||
.appendQueryParameter("type", "buy")
|
||||
.appendQueryParameter("currency", cryptoCurrency.symbol)
|
||||
.appendQueryParameter("address", walletAddress)
|
||||
.appendQueryParameter("signature", environmentConfig.signature(walletAddress))
|
||||
.appendQueryParameter("fix_currency", "true")
|
||||
.appendQueryParameter("redirect_url", LegacyTopUpRepository.SUCCESS_URL)
|
||||
|
||||
blockchain.mercuryoNetwork?.let {
|
||||
builder.appendQueryParameter("network", it)
|
||||
}
|
||||
|
||||
builder.build().toString()
|
||||
}
|
||||
|
||||
private fun EnvironmentConfig.signature(address: String) = (address + mercuryoSecret)
|
||||
.calculateSha512()
|
||||
.toHexString()
|
||||
.lowercase()
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.domain.onramp
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.domain.onramp.repositories.LegacyTopUpRepository
|
||||
import com.tangem.domain.onramp.model.error.OnrampError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
|
||||
class GetLegacyTopUpUrlUseCase(
|
||||
private val legacyTopUpRepository: LegacyTopUpRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(cryptoCurrencyStatus: CryptoCurrencyStatus): Either<OnrampError.DomainError, String> =
|
||||
either {
|
||||
val walletAddress = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
|
||||
?: raise(OnrampError.DomainError("Wallet address is null"))
|
||||
legacyTopUpRepository.getTopUpUrl(
|
||||
cryptoCurrency = cryptoCurrencyStatus.currency,
|
||||
walletAddress = walletAddress,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.domain.onramp.repositories
|
||||
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
||||
/**
|
||||
* Support legacy onboarding note/twins to get top up URL from mercuryo
|
||||
*
|
||||
*/
|
||||
interface LegacyTopUpRepository {
|
||||
|
||||
/**
|
||||
* Get top up URL from mercuryo
|
||||
*
|
||||
* @property cryptoCurrency crypto currency
|
||||
* @property walletAddress address of wallet
|
||||
*/
|
||||
suspend fun getTopUpUrl(cryptoCurrency: CryptoCurrency, walletAddress: String): String
|
||||
|
||||
companion object {
|
||||
const val SCHEME = "https"
|
||||
const val SUCCESS_URL = "https://tangem.com/success"
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ dependencies {
|
|||
implementation(projects.domain.visa)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.onramp)
|
||||
|
||||
/** Tangem libraries */
|
||||
implementation(projects.libs.tangemSdkApi)
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ import com.tangem.core.analytics.Analytics
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.onramp.GetLegacyTopUpUrlUseCase
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
|
|
@ -20,7 +22,7 @@ import kotlinx.coroutines.flow.*
|
|||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class OnboardingNoteTopUpModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
|
|
@ -28,9 +30,12 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val userWalletBuilderFactory: UserWalletBuilder.Factory,
|
||||
private val getLegacyTopUpUrlUseCase: GetLegacyTopUpUrlUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<OnboardingNoteTopUpComponent.Params>()
|
||||
private val commonState = params.childParams.commonState
|
||||
private val scanResponse = params.childParams.commonState.value.scanResponse
|
||||
private var userWallet: UserWallet? = null
|
||||
|
||||
|
|
@ -68,7 +73,12 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onBuyCryptoClick() {
|
||||
// TODO [REDACTED_TASK_KEY]
|
||||
val cryptoCurrencyStatus = params.childParams.commonState.value.cryptoCurrencyStatus ?: return
|
||||
modelScope.launch {
|
||||
getLegacyTopUpUrlUseCase(cryptoCurrencyStatus).onRight {
|
||||
urlOpener.openUrl(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onShowWalletAddressClick() {
|
||||
|
|
@ -100,6 +110,9 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun applyCryptoCurrencyStatusToState(status: CryptoCurrencyStatus) {
|
||||
commonState.update {
|
||||
it.copy(cryptoCurrencyStatus = status)
|
||||
}
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
amountToCreateAccount = (status.value as? CryptoCurrencyStatus.NoAccount)
|
||||
|
|
@ -112,12 +125,15 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
)
|
||||
},
|
||||
),
|
||||
balance = (status.value as? CryptoCurrencyStatus.Loaded)?.amount?.format({
|
||||
crypto(
|
||||
symbol = status.currency.symbol,
|
||||
decimals = status.currency.decimals,
|
||||
)
|
||||
},),
|
||||
balance = (status.value as? CryptoCurrencyStatus.Loaded)?.amount?.format(
|
||||
{
|
||||
crypto(
|
||||
symbol = status.currency.symbol,
|
||||
decimals = status.currency.decimals,
|
||||
)
|
||||
},
|
||||
),
|
||||
isTopUpDataLoading = status.value.networkAddress == null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.onboarding.v2.note.impl.child.topup.ui
|
|||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -26,6 +27,7 @@ fun OnboardingNoteTopUp(state: OnboardingNoteTopUpUM, modifier: Modifier = Modif
|
|||
.fillMaxSize()
|
||||
.navigationBarsPadding(),
|
||||
verticalArrangement = Arrangement.Bottom,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
OnboardingNoteTopUpHeader(
|
||||
balance = state.balance,
|
||||
|
|
@ -64,7 +66,15 @@ fun OnboardingNoteTopUp(state: OnboardingNoteTopUpUM, modifier: Modifier = Modif
|
|||
)
|
||||
}
|
||||
|
||||
BottomButtons(state)
|
||||
if (state.isTopUpDataLoading) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.padding(all = 32.dp)
|
||||
.size(36.dp),
|
||||
)
|
||||
} else {
|
||||
BottomButtons(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ data class OnboardingNoteTopUpUM(
|
|||
val availableForBuy: Boolean = true,
|
||||
val balance: String? = null,
|
||||
val isRefreshing: Boolean = false,
|
||||
val isTopUpDataLoading: Boolean = true,
|
||||
val amountToCreateAccount: String? = null,
|
||||
val onBuyCryptoClick: () -> Unit = {},
|
||||
val onShowWalletAddressClick: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package com.tangem.features.onboarding.v2.note.impl.model
|
||||
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
internal data class OnboardingNoteCommonState(
|
||||
val scanResponse: ScanResponse,
|
||||
val cardArtworkUrl: String? = null,
|
||||
val userWallet: UserWallet? = null,
|
||||
val cryptoCurrencyStatus: CryptoCurrencyStatus? = null,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue