Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import androidx.compose.runtime.remember
import androidx.navigation3.runtime.NavBackStack
import androidx.navigation3.runtime.NavKey
import com.gemwallet.android.features.asset_select.presents.navigation.AssetsManageRoute
import com.gemwallet.android.features.asset_select.presents.navigation.AssetsSearchRoute
import com.gemwallet.android.ui.navigation.routes.AssetsResultsRoute
import com.gemwallet.android.ui.navigation.routes.WalletSearchRoute
import com.gemwallet.android.features.create_wallet.navigation.CreateWalletAlertRoute
import com.gemwallet.android.features.create_wallet.navigation.CreateWalletRoute
import com.gemwallet.android.features.import_wallet.navigation.ImportChainWalletRoute
Expand Down Expand Up @@ -74,6 +75,7 @@ import com.gemwallet.android.ui.navigation.routes.WalletSecurityReminderRoute
import com.gemwallet.android.ui.navigation.routes.WalletsRoute
import com.gemwallet.android.ext.toIdentifier
import com.wallet.core.primitives.AssetId
import com.wallet.core.primitives.AssetTag
import com.wallet.core.primitives.NFTAssetId
import com.wallet.core.primitives.TransactionId
import com.wallet.core.primitives.WalletId
Expand Down Expand Up @@ -170,7 +172,8 @@ class WalletNavigator(
fun openWallets() = push(WalletsRoute)
fun openAcceptTerms(destination: AcceptTermsDestination) = push(AcceptTermsRoute(destination))
fun openAssetsManage() = push(AssetsManageRoute)
fun openAssetsSearch() = push(AssetsSearchRoute)
fun openAssetsSearch() = push(WalletSearchRoute)
fun openAssetsResults(query: String, tag: AssetTag?) = push(AssetsResultsRoute(query, tag))
fun openCreateWalletRules() = push(CreateWalletAlertRoute)
fun openCreateWallet() = push(CreateWalletRoute)
fun openImportWallet() = push(ImportSelectTypeRoute)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.gemwallet.android.ui.models.actions.AmountTransactionAction
import com.gemwallet.android.ui.models.actions.ConfirmTransactionAction
import com.gemwallet.android.features.activities.presents.details.TransactionDetailsAction
import com.gemwallet.android.features.asset_select.presents.navigation.assetsManageScreen
import com.gemwallet.android.features.assets.views.WalletSearchAction
import com.gemwallet.android.features.create_wallet.navigation.createWalletScreen
import com.gemwallet.android.features.import_wallet.navigation.importWalletScreen
import com.gemwallet.android.features.onboarding.OnboardingRoute
Expand Down Expand Up @@ -51,6 +52,7 @@ import com.gemwallet.android.ui.navigation.routes.swap
import com.gemwallet.android.ui.navigation.routes.swapSelect
import com.gemwallet.android.ui.navigation.routes.transactionDetailsScreen
import com.gemwallet.android.ui.navigation.routes.walletScreen
import com.gemwallet.android.ui.navigation.routes.walletSearchScreen
import com.gemwallet.android.ui.navigation.routes.walletsScreen
import com.wallet.core.primitives.WalletId

Expand Down Expand Up @@ -86,6 +88,19 @@ fun WalletNavGraph(
onCancel = onCancel,
)

walletSearchScreen(
onAction = { action ->
when (action) {
WalletSearchAction.AddAsset -> navigator.openAddAsset()
WalletSearchAction.Cancel -> onCancel()
WalletSearchAction.OpenPerpetuals -> navigator.openPerpetuals()
is WalletSearchAction.OpenAsset -> navigator.openAsset(action.assetId)
is WalletSearchAction.OpenPerpetual -> navigator.openPerpetualDetails(action.assetId)
is WalletSearchAction.ShowAllAssets -> navigator.openAssetsResults(action.query, action.tag)
}
},
)

assetScreen(
onCancel = onCancel,
onTransfer = navigator::openRecipient,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.gemwallet.android.ui.navigation.routes

import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import com.gemwallet.android.features.assets.views.AssetsResultsScreen
import com.gemwallet.android.features.assets.views.WalletSearchAction
import com.gemwallet.android.features.assets.views.WalletSearchScreen
import com.gemwallet.android.ui.models.navigation.RouteArgument
import com.gemwallet.android.ui.navigation.routeArguments
import com.wallet.core.primitives.AssetTag
import kotlinx.serialization.Serializable

@Serializable
data object WalletSearchRoute : NavKey

@Serializable
data class AssetsResultsRoute(val query: String, val tag: AssetTag?) : NavKey

fun EntryProviderScope<NavKey>.walletSearchScreen(
onAction: (WalletSearchAction) -> Unit,
) {
entry<WalletSearchRoute> {
WalletSearchScreen(onAction = onAction)
}

entry<AssetsResultsRoute>(
metadata = { key ->
routeArguments(
RouteArgument.Query to key.query,
RouteArgument.Tag to key.tag?.string,
)
},
) {
AssetsResultsScreen(onAction = onAction)
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
package com.gemwallet.android.data.coordinators.asset

import com.gemwallet.android.application.assets.coordinators.GemSearch
import com.gemwallet.android.application.assets.coordinators.SearchAssets
import com.gemwallet.android.data.services.gemapi.GemApiClient
import com.wallet.core.primitives.AssetBasic
import com.wallet.core.primitives.AssetId
import com.wallet.core.primitives.AssetTag
import com.wallet.core.primitives.Chain
import com.wallet.core.primitives.SearchResponse

class SearchAssetsImpl(
private val gemApiClient: GemApiClient,
) : SearchAssets {
) : SearchAssets, GemSearch {

override suspend fun search(
query: String,
chains: List<Chain>,
tags: List<AssetTag>,
): List<AssetBasic> {
): SearchResponse {
return gemApiClient.search(
query = query,
chains = chains.joinToString(",") { it.string },
tags = tags.joinToString(",") { it.string },
)
}

override suspend fun searchAssets(
query: String,
chains: List<Chain>,
tags: List<AssetTag>,
): List<AssetBasic> {
return gemApiClient.searchAssets(
query = query,
chains = chains.joinToString(",") { it.string },
tags = tags.joinToString(",") { it.string },
)
}

override suspend fun getAssets(assetIds: List<AssetId>): List<AssetBasic> {
return gemApiClient.getAssets(assetIds)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.gemwallet.android.data.coordinators.di

import com.gemwallet.android.application.assets.coordinators.EnableAsset
import com.gemwallet.android.application.assets.coordinators.GemSearch
import com.gemwallet.android.application.assets.coordinators.GetActiveAssetsInfo
import com.gemwallet.android.application.assets.coordinators.GetAssetById
import com.gemwallet.android.application.assets.coordinators.GetAssetChartData
Expand Down Expand Up @@ -64,12 +65,20 @@ import javax.inject.Singleton
object AssetModule {
@Provides
@Singleton
fun provideSearchAssets(
fun provideSearchAssetsImpl(
gemApiClient: GemApiClient,
): SearchAssets = SearchAssetsImpl(
): SearchAssetsImpl = SearchAssetsImpl(
gemApiClient = gemApiClient,
)

@Provides
@Singleton
fun provideSearchAssets(impl: SearchAssetsImpl): SearchAssets = impl

@Provides
@Singleton
fun provideGemSearch(impl: SearchAssetsImpl): GemSearch = impl

@Provides
@Singleton
fun provideGetActiveAssetsInfo(assetsRepository: AssetsRepository): GetActiveAssetsInfo =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.gemwallet.android.data.services.gemapi.GemApiClient
import com.gemwallet.android.testkit.mockAssetBasic
import com.wallet.core.primitives.AssetTag
import com.wallet.core.primitives.Chain
import com.wallet.core.primitives.SearchResponse
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
Expand All @@ -22,21 +23,22 @@ class SearchAssetsImplTest {
@Test
fun search_formatsChainsAndTagsForGemApi() = runTest {
val asset = mockAssetBasic()
val response = SearchResponse(assets = listOf(asset), perpetuals = emptyList(), nfts = emptyList())
coEvery {
gemApiClient.search(
query = "usd",
chains = "bitcoin,ethereum",
tags = "trending,stablecoins",
)
} returns listOf(asset)
} returns response

val result = subject.search(
query = "usd",
chains = listOf(Chain.Bitcoin, Chain.Ethereum),
tags = listOf(AssetTag.Trending, AssetTag.Stablecoins),
)

assertEquals(listOf(asset), result)
assertEquals(response, result)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ package com.gemwallet.android.data.repositories.assets
import com.gemwallet.android.data.repositories.session.SessionRepository
import com.gemwallet.android.data.repositories.tokens.toPriorityQuery
import com.gemwallet.android.data.service.store.database.AssetsDao
import com.gemwallet.android.data.service.store.database.AssetsPriorityDao
import com.gemwallet.android.data.service.store.database.SearchPriorityDao
import com.gemwallet.android.data.service.store.database.entities.toAssetInfoModel
import com.gemwallet.android.ext.toIdentifier
import com.gemwallet.android.model.AssetInfo
import com.wallet.core.primitives.AssetId
import com.wallet.core.primitives.AssetTag
import com.wallet.core.primitives.Chain
import com.wallet.core.primitives.SearchItemType
import com.wallet.core.primitives.Wallet
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import javax.inject.Inject
Expand All @@ -22,14 +24,14 @@ import javax.inject.Singleton
@Singleton
class AssetsSearchService @Inject constructor(
private val assetsDao: AssetsDao,
private val assetsPriorityDao: AssetsPriorityDao,
private val searchPriorityDao: SearchPriorityDao,
private val sessionRepository: SessionRepository,
) {

fun search(query: String, tags: List<AssetTag>, byAllWallets: Boolean): Flow<List<AssetInfo>> {
val query = tags.toPriorityQuery(query)
return sessionRepository.currentWalletId().flatMapLatest { walletId ->
assetsPriorityDao.hasPriorities(query).map { it > 0 }.flatMapLatest { hasPriority ->
searchPriorityDao.hasPriorities(query, SearchItemType.Asset.string).map { it > 0 }.distinctUntilChanged().flatMapLatest { hasPriority ->
when {
byAllWallets && hasPriority -> assetsDao.searchByAllWalletsWithPriority(walletId, query)
byAllWallets -> assetsDao.searchByAllWallets(walletId, query)
Expand All @@ -46,7 +48,7 @@ class AssetsSearchService @Inject constructor(
val walletChains = wallet.accounts.map { it.chain }
val includeChains = byChains.filter { walletChains.contains(it) }
val includeAssetIds = byAssets.filter { walletChains.contains(it.chain) }
return assetsPriorityDao.hasPriorities(query).map { it > 0 }.flatMapLatest { hasPriority ->
return searchPriorityDao.hasPriorities(query, SearchItemType.Asset.string).map { it > 0 }.distinctUntilChanged().flatMapLatest { hasPriority ->
if (hasPriority) {
assetsDao.swapSearchWithPriority(wallet.id.id, query, includeChains, includeAssetIds.map { it.toIdentifier() })
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.gemwallet.android.data.repositories.config

import com.gemwallet.android.ext.hasPerpetualsSupport
import com.gemwallet.android.model.Session
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine

fun UserConfig.showPerpetuals(session: Flow<Session?>): Flow<Boolean> =
combine(session, isPerpetualEnabled()) { current, enabled ->
enabled && current?.wallet?.hasPerpetualsSupport == true
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.gemwallet.android.data.service.store.database.AssetsDao
import com.gemwallet.android.data.service.store.database.BalancesDao
import com.gemwallet.android.data.service.store.database.PerpetualDao
import com.gemwallet.android.data.service.store.database.PerpetualPositionDao
import com.gemwallet.android.data.service.store.database.SearchPriorityDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -23,12 +24,14 @@ object PerpetualModule {
perpetualPositionDao: PerpetualPositionDao,
assetsDao: AssetsDao,
balancesDao: BalancesDao,
searchPriorityDao: SearchPriorityDao,
): PerpetualRepository {
return PerpetualRepositoryImpl(
perpetualDao = perpetualDao,
perpetualPositionDao = perpetualPositionDao,
assetsDao = assetsDao,
balancesDao = balancesDao,
searchPriorityDao = searchPriorityDao,
)
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.gemwallet.android.data.repositories.di

import com.gemwallet.android.application.assets.coordinators.GemSearch
import com.gemwallet.android.application.assets.coordinators.SearchAssets
import com.gemwallet.android.blockchain.services.TokenService
import com.gemwallet.android.cases.tokens.SearchTokensCase
import com.gemwallet.android.cases.tokens.SyncAssetPrices
import com.gemwallet.android.data.repositories.perpetual.PerpetualRepository
import com.gemwallet.android.data.repositories.tokens.TokensRepository
import com.gemwallet.android.data.repositories.tokens.WalletSearch
import com.gemwallet.android.data.repositories.tokens.WalletSearchTokens
import com.gemwallet.android.data.service.store.database.AssetsDao
import com.gemwallet.android.data.service.store.database.AssetsPriorityDao
import com.gemwallet.android.data.service.store.database.PricesDao
import com.gemwallet.android.data.service.store.database.SearchPriorityDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -23,13 +27,13 @@ object TokensModule {
fun provideTokensRepository(
assetsDao: AssetsDao,
pricesDao: PricesDao,
assetsPriorityDao: AssetsPriorityDao,
searchPriorityDao: SearchPriorityDao,
gateway: GemGateway,
searchAssets: SearchAssets,
): TokensRepository = TokensRepository(
assetsDao = assetsDao,
pricesDao = pricesDao,
assetsPriorityDao = assetsPriorityDao,
searchPriorityDao = searchPriorityDao,
searchAssets = searchAssets,
tokenService = TokenService(
gateway = gateway,
Expand All @@ -40,6 +44,16 @@ object TokensModule {
@Singleton
fun provideSearchTokensCase(tokensRepository: TokensRepository): SearchTokensCase = tokensRepository

@Provides
@Singleton
@WalletSearch
fun provideWalletSearchTokensCase(
tokensRepository: TokensRepository,
gemSearch: GemSearch,
perpetualRepository: PerpetualRepository,
searchPriorityDao: SearchPriorityDao,
): SearchTokensCase = WalletSearchTokens(tokensRepository, gemSearch, perpetualRepository, searchPriorityDao)

@Provides
@Singleton
fun provideSyncAssetPrices(tokensRepository: TokensRepository): SyncAssetPrices = tokensRepository
Expand Down
Loading