Updated on 2026-08-14
This commit is contained in:
parent
26b3c3d576
commit
95f66c8798
18 changed files with 89 additions and 64 deletions
|
|
@ -8,7 +8,7 @@ import java.util.UUID
|
|||
|
||||
class ExpressAuthProviderImpl(
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
private val configManager: ConfigManager
|
||||
private val configManager: ConfigManager,
|
||||
) : ExpressAuthProvider, ExpressSessionIdGenerator {
|
||||
|
||||
private var uuid = UUID.randomUUID()
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class AuthModule {
|
|||
): ExpressAuthProvider {
|
||||
return ExpressAuthProviderImpl(
|
||||
userWalletsStore = userWalletsStore,
|
||||
configManager = configManager
|
||||
configManager = configManager,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,6 @@ import com.tangem.datasource.api.express.models.request.PairsRequestBody
|
|||
import com.tangem.datasource.api.express.models.response.*
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Query
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -15,12 +14,10 @@ import java.math.BigDecimal
|
|||
* Interface of Tangem Express API (new swap mechanism)
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
interface ExpressApi {
|
||||
|
||||
interface TangemExpressApi {
|
||||
|
||||
@POST("assets")
|
||||
suspend fun getAssets(
|
||||
@Body body: AssetsRequestBody,
|
||||
): ApiResponse<List<Asset>>
|
||||
suspend fun getAssets(@Body body: AssetsRequestBody): ApiResponse<List<Asset>>
|
||||
|
||||
@POST("pairs")
|
||||
suspend fun getPairs(@Body body: PairsRequestBody): ApiResponse<List<SwapPair>>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.tangem.datasource.api.express.models
|
||||
|
||||
object TangemExpressValues {
|
||||
const val EMPTY_CONTRACT_ADDRESS_VALUE = "0"
|
||||
}
|
||||
|
|
@ -3,5 +3,6 @@ package com.tangem.datasource.api.express.models.request
|
|||
import com.squareup.moshi.Json
|
||||
|
||||
data class AssetsRequestBody(
|
||||
@Json(name = "filter") val filter: List<LeastTokenInfo>?,
|
||||
@Json(name = "tokensList") val tokensList: List<LeastTokenInfo>?,
|
||||
@Json(name = "onlyActive") val onlyActive: Boolean,
|
||||
)
|
||||
|
|
@ -106,7 +106,7 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
|
|||
swapReferrerAccount = configValues.swapReferrerAccount,
|
||||
walletConnectProjectId = configValues.walletConnectProjectId,
|
||||
tangemComAuthorization = configValues.tangemComAuthorization,
|
||||
tangemExpressApiKey = configValues.tangemExpressApiKey
|
||||
tangemExpressApiKey = configValues.tangemExpressApiKey,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -19,5 +19,5 @@ data class Config(
|
|||
val swapReferrerAccount: SwapReferrerAccount? = null,
|
||||
val walletConnectProjectId: String = "",
|
||||
val tangemComAuthorization: String? = null,
|
||||
val tangemExpressApiKey: String = ""
|
||||
val tangemExpressApiKey: String = "",
|
||||
)
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.datasource.di
|
||||
|
||||
import com.tangem.datasource.local.datastore.RuntimeDataStore
|
||||
import com.tangem.datasource.local.token.DefaultUserMarketCoinsStore
|
||||
import com.tangem.datasource.local.token.UserMarketCoinsStore
|
||||
import com.tangem.datasource.local.token.DefaultAssetsStore
|
||||
import com.tangem.datasource.local.token.AssetsStore
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -11,11 +11,11 @@ import javax.inject.Singleton
|
|||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object MarketCoinsStoreModule {
|
||||
internal object AssetsStoreModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUserMarketCoinsStore(): UserMarketCoinsStore {
|
||||
return DefaultUserMarketCoinsStore(dataStore = RuntimeDataStore())
|
||||
fun provideAssetsStore(): AssetsStore {
|
||||
return DefaultAssetsStore(dataStore = RuntimeDataStore())
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,9 @@ package com.tangem.datasource.di
|
|||
import android.content.Context
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.datasource.api.common.response.ApiResponseCallAdapterFactory
|
||||
import com.tangem.datasource.api.express.ExpressApi
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.promotion.PromotionApi
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.utils.RequestHeader
|
||||
import com.tangem.datasource.utils.RequestHeader.*
|
||||
import com.tangem.datasource.utils.addHeaders
|
||||
import com.tangem.datasource.utils.addLoggers
|
||||
|
|
@ -33,8 +32,7 @@ class NetworkModule {
|
|||
@NetworkMoshi moshi: Moshi,
|
||||
@ApplicationContext context: Context,
|
||||
expressAuthProvider: ExpressAuthProvider,
|
||||
): ExpressApi {
|
||||
|
||||
): TangemExpressApi {
|
||||
return Retrofit.Builder()
|
||||
.addConverterFactory(MoshiConverterFactory.create(moshi))
|
||||
.addCallAdapterFactory(ApiResponseCallAdapterFactory.create())
|
||||
|
|
@ -46,7 +44,7 @@ class NetworkModule {
|
|||
.build(),
|
||||
)
|
||||
.build()
|
||||
.create(ExpressApi::class.java)
|
||||
.create(TangemExpressApi::class.java)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.datasource.local.token
|
||||
|
||||
import com.tangem.datasource.api.express.models.response.Asset
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
interface AssetsStore {
|
||||
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId): List<Asset>?
|
||||
|
||||
suspend fun store(userWalletId: UserWalletId, item: List<Asset>)
|
||||
}
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
package com.tangem.datasource.local.token
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
|
||||
import com.tangem.datasource.api.express.models.response.Asset
|
||||
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
internal class DefaultUserMarketCoinsStore(
|
||||
private val dataStore: StringKeyDataStore<CoinsResponse>,
|
||||
) : UserMarketCoinsStore {
|
||||
internal class DefaultAssetsStore(
|
||||
private val dataStore: StringKeyDataStore<List<Asset>>,
|
||||
) : AssetsStore {
|
||||
|
||||
override suspend fun getSyncOrNull(userWalletId: UserWalletId): CoinsResponse? {
|
||||
override suspend fun getSyncOrNull(userWalletId: UserWalletId): List<Asset>? {
|
||||
return dataStore.getSyncOrNull(userWalletId.stringValue)
|
||||
}
|
||||
|
||||
override suspend fun store(userWalletId: UserWalletId, item: CoinsResponse) {
|
||||
override suspend fun store(userWalletId: UserWalletId, item: List<Asset>) {
|
||||
dataStore.store(userWalletId.stringValue, item)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package com.tangem.datasource.local.token
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
interface UserMarketCoinsStore {
|
||||
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId): CoinsResponse?
|
||||
|
||||
suspend fun store(userWalletId: UserWalletId, item: CoinsResponse)
|
||||
}
|
||||
|
|
@ -20,9 +20,9 @@ sealed class RequestHeader(vararg pairs: Pair<String, () -> String>) {
|
|||
"card_public_key" to { authProvider.getCardPublicKey() },
|
||||
)
|
||||
|
||||
class Express(expressAuthProvider: ExpressAuthProvider): RequestHeader(
|
||||
class Express(expressAuthProvider: ExpressAuthProvider) : RequestHeader(
|
||||
"api-key" to { expressAuthProvider.getApiKey() },
|
||||
"user-id" to { expressAuthProvider.getUserId() },
|
||||
"session-id" to { expressAuthProvider.getSessionId() }
|
||||
"session-id" to { expressAuthProvider.getSessionId() },
|
||||
)
|
||||
}
|
||||
|
|
@ -5,11 +5,12 @@ import com.tangem.data.tokens.repository.DefaultCurrenciesRepository
|
|||
import com.tangem.data.tokens.repository.DefaultMarketCryptoCurrencyRepository
|
||||
import com.tangem.data.tokens.repository.DefaultNetworksRepository
|
||||
import com.tangem.data.tokens.repository.DefaultQuotesRepository
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.appcurrency.SelectedAppCurrencyStore
|
||||
import com.tangem.datasource.local.network.NetworksStatusesStore
|
||||
import com.tangem.datasource.local.quote.QuotesStore
|
||||
import com.tangem.datasource.local.token.UserMarketCoinsStore
|
||||
import com.tangem.datasource.local.token.AssetsStore
|
||||
import com.tangem.datasource.local.token.UserTokensStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
|
|
@ -32,17 +33,19 @@ internal object TokensDataModule {
|
|||
@Singleton
|
||||
fun provideCurrenciesRepository(
|
||||
tangemTechApi: TangemTechApi,
|
||||
tangemExpressApi: TangemExpressApi,
|
||||
userTokensStore: UserTokensStore,
|
||||
userWalletsStore: UserWalletsStore,
|
||||
userMarketCoinsStore: UserMarketCoinsStore,
|
||||
assetsStore: AssetsStore,
|
||||
cacheRegistry: CacheRegistry,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): CurrenciesRepository {
|
||||
return DefaultCurrenciesRepository(
|
||||
tangemTechApi = tangemTechApi,
|
||||
tangemExpressApi = tangemExpressApi,
|
||||
userTokensStore = userTokensStore,
|
||||
userWalletsStore = userWalletsStore,
|
||||
userMarketCoinsStore = userMarketCoinsStore,
|
||||
assetsStore = assetsStore,
|
||||
cacheRegistry = cacheRegistry,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
|
|
@ -88,9 +91,7 @@ internal object TokensDataModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDefaultMarketCoinsRepository(
|
||||
userMarketCoinsStore: UserMarketCoinsStore,
|
||||
): MarketCryptoCurrencyRepository {
|
||||
return DefaultMarketCryptoCurrencyRepository(userMarketCoinsStore)
|
||||
fun provideDefaultMarketCoinsRepository(assetsStore: AssetsStore): MarketCryptoCurrencyRepository {
|
||||
return DefaultMarketCryptoCurrencyRepository(assetsStore)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,9 +5,14 @@ import com.tangem.data.common.api.safeApiCall
|
|||
import com.tangem.data.common.cache.CacheRegistry
|
||||
import com.tangem.data.tokens.utils.*
|
||||
import com.tangem.datasource.api.common.response.ApiResponseError
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.express.models.TangemExpressValues.EMPTY_CONTRACT_ADDRESS_VALUE
|
||||
import com.tangem.datasource.api.express.models.request.AssetsRequestBody
|
||||
import com.tangem.datasource.api.express.models.request.LeastTokenInfo
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.local.token.UserMarketCoinsStore
|
||||
import com.tangem.datasource.local.token.AssetsStore
|
||||
import com.tangem.datasource.local.token.UserTokensStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.common.extensions.toCoinId
|
||||
|
|
@ -27,12 +32,13 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("LargeClass")
|
||||
@Suppress("LargeClass", "LongParameterList")
|
||||
internal class DefaultCurrenciesRepository(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val tangemExpressApi: TangemExpressApi,
|
||||
private val userTokensStore: UserTokensStore,
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
private val userMarketCoinsStore: UserMarketCoinsStore,
|
||||
private val assetsStore: AssetsStore,
|
||||
private val cacheRegistry: CacheRegistry,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : CurrenciesRepository {
|
||||
|
|
@ -341,14 +347,25 @@ internal class DefaultCurrenciesRepository(
|
|||
userTokens: UserTokensResponse,
|
||||
) {
|
||||
try {
|
||||
val networkIds = userTokens.tokens
|
||||
val tokensList = userTokens.tokens
|
||||
.distinctBy { it.networkId }
|
||||
.joinToString(separator = ",") { it.networkId }
|
||||
val response = tangemTechApi.getCoins(networkIds = networkIds, exchangeable = true)
|
||||
.map {
|
||||
LeastTokenInfo(
|
||||
contractAddress = it.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE,
|
||||
network = it.networkId,
|
||||
)
|
||||
}
|
||||
|
||||
userMarketCoinsStore.store(userWalletId, response)
|
||||
val response = tangemExpressApi.getAssets(
|
||||
AssetsRequestBody(
|
||||
tokensList = tokensList,
|
||||
onlyActive = true,
|
||||
),
|
||||
)
|
||||
|
||||
assetsStore.store(userWalletId, response.getOrThrow())
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "Unable to fetch user market coins for: ${userWalletId.stringValue}")
|
||||
Timber.e(e, "Unable to fetch assets for: ${userWalletId.stringValue}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,28 @@
|
|||
package com.tangem.data.tokens.repository
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.datasource.local.token.UserMarketCoinsStore
|
||||
import com.tangem.datasource.api.express.models.TangemExpressValues.EMPTY_CONTRACT_ADDRESS_VALUE
|
||||
import com.tangem.datasource.local.token.AssetsStore
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.repository.MarketCryptoCurrencyRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
class DefaultMarketCryptoCurrencyRepository(
|
||||
private val userMarketCoinsStore: UserMarketCoinsStore,
|
||||
private val assetsStore: AssetsStore,
|
||||
) : MarketCryptoCurrencyRepository {
|
||||
|
||||
override suspend fun isExchangeable(userWalletId: UserWalletId, cryptoCurrencyId: CryptoCurrency.ID): Boolean {
|
||||
override suspend fun isExchangeable(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean {
|
||||
val cryptoCurrencyId = cryptoCurrency.id
|
||||
val blockchain = Blockchain.fromId(cryptoCurrencyId.rawNetworkId)
|
||||
val apiNetworkId = blockchain.toNetworkId()
|
||||
return userMarketCoinsStore.getSyncOrNull(userWalletId)?.coins
|
||||
?.firstOrNull { it.id == cryptoCurrencyId.rawCurrencyId }
|
||||
?.networks
|
||||
?.firstOrNull { it.networkId == apiNetworkId }?.exchangeable ?: false
|
||||
val contractAddress = (cryptoCurrency as? CryptoCurrency.Token)?.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE
|
||||
|
||||
return assetsStore.getSyncOrNull(userWalletId)?.find {
|
||||
it.network == apiNetworkId &&
|
||||
it.token == cryptoCurrencyId.rawCurrencyId &&
|
||||
it.contractAddress == contractAddress &&
|
||||
it.isActive
|
||||
}?.exchangeAvailable ?: false
|
||||
}
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ class GetCryptoCurrencyActionsUseCase(
|
|||
activeList.add(TokenActionsState.ActionState.Receive(true))
|
||||
|
||||
// swap
|
||||
if (marketCryptoCurrencyRepository.isExchangeable(userWalletId, cryptoCurrency.id)) {
|
||||
if (marketCryptoCurrencyRepository.isExchangeable(userWalletId, cryptoCurrency)) {
|
||||
activeList.add(TokenActionsState.ActionState.Swap(true))
|
||||
} else {
|
||||
disabledList.add(TokenActionsState.ActionState.Swap(false))
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
*/
|
||||
interface MarketCryptoCurrencyRepository {
|
||||
|
||||
suspend fun isExchangeable(userWalletId: UserWalletId, cryptoCurrencyId: CryptoCurrency.ID): Boolean
|
||||
suspend fun isExchangeable(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue