Updated on 2026-08-14

This commit is contained in:
Tangem 2024-02-15 12:28:34 +05:00
parent 50c9368ce3
commit 3e7825b2e3
9 changed files with 66 additions and 59 deletions

View file

@ -2,6 +2,7 @@ package com.tangem.datasource.local.txhistory
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
import com.tangem.datasource.local.datastore.core.StringKeyDataStoreDecorator
import com.tangem.domain.txhistory.models.Page
import com.tangem.domain.txhistory.models.PaginationWrapper
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.utils.extensions.addOrReplace
@ -13,28 +14,16 @@ internal class DefaultTxHistoryItemsStore(
override fun provideStringKey(key: TxHistoryItemsStore.Key): String = key.toString()
override suspend fun getNextPageSyncOrNull(key: TxHistoryItemsStore.Key): Int? {
val storedValue = getSyncOrNull(key) ?: return null
val lastWrappedItems = storedValue.maxBy(PaginationWrapper<*>::page)
val lastPage = lastWrappedItems.page
return if (lastPage <= lastWrappedItems.totalPages) {
lastPage
} else {
null
}
}
override suspend fun getSyncOrNull(key: TxHistoryItemsStore.Key, page: Int): PaginationWrapper<TxHistoryItem>? {
override suspend fun getSyncOrNull(key: TxHistoryItemsStore.Key, page: Page): PaginationWrapper<TxHistoryItem>? {
val storedValue = getSyncOrNull(key)
return storedValue?.firstOrNull { it.page == page }
return storedValue?.firstOrNull { it.currentPage == page }
}
override suspend fun store(key: TxHistoryItemsStore.Key, value: PaginationWrapper<TxHistoryItem>) {
val oldValue = getSyncOrNull(key).orEmpty()
val newValue = oldValue.addOrReplace(value) {
it.page == value.page
it.currentPage == value.currentPage
}
store(key, newValue)

View file

@ -1,15 +1,14 @@
package com.tangem.datasource.local.txhistory
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.txhistory.models.Page
import com.tangem.domain.txhistory.models.PaginationWrapper
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.wallets.models.UserWalletId
interface TxHistoryItemsStore {
suspend fun getNextPageSyncOrNull(key: Key): Int?
suspend fun getSyncOrNull(key: Key, page: Int): PaginationWrapper<TxHistoryItem>?
suspend fun getSyncOrNull(key: Key, page: Page): PaginationWrapper<TxHistoryItem>?
suspend fun remove(key: Key)

View file

@ -7,9 +7,11 @@ import com.tangem.data.common.cache.CacheRegistry
import com.tangem.datasource.local.txhistory.TxHistoryItemsStore
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.txhistory.models.Page
import com.tangem.domain.txhistory.models.PaginationWrapper
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.walletmanager.utils.SdkPageConverter
import com.tangem.domain.wallets.models.UserWalletId
import timber.log.Timber
@ -18,21 +20,19 @@ internal class TxHistoryPagingSource(
private val txHistoryItemsStore: TxHistoryItemsStore,
private val walletManagersFacade: WalletManagersFacade,
private val cacheRegistry: CacheRegistry,
) : PagingSource<Int, TxHistoryItem>() {
) : PagingSource<Page, TxHistoryItem>() {
private val storeKey = TxHistoryItemsStore.Key(sourceParams.userWalletId, sourceParams.currency)
private val sdkPageConverter by lazy { SdkPageConverter() }
override val keyReuseSupported: Boolean get() = true
override fun getRefreshKey(state: PagingState<Int, TxHistoryItem>): Int? {
return state.anchorPosition?.let { anchorPosition ->
val anchorPage = state.closestPageToPosition(anchorPosition)
anchorPage?.prevKey?.inc() ?: anchorPage?.nextKey?.dec()
}
override fun getRefreshKey(state: PagingState<Page, TxHistoryItem>): Page? {
return null
}
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, TxHistoryItem> {
val pageToLoad = params.key ?: INITIAL_PAGE
override suspend fun load(params: LoadParams<Page>): LoadResult<Page, TxHistoryItem> {
val pageToLoad = params.key ?: Page.Initial
return try {
val wrappedItems = loadItems(
@ -40,20 +40,11 @@ internal class TxHistoryPagingSource(
pageSize = sourceParams.pageSize,
refresh = sourceParams.refresh && params is LoadParams.Refresh,
)
val items = wrappedItems.items
val prevPage = when {
items.isEmpty() -> null
pageToLoad > INITIAL_PAGE -> pageToLoad.dec()
else -> null
val nextKey = when (wrappedItems.nextPage) {
Page.LastPage -> null
Page.Initial, is Page.Next -> wrappedItems.nextPage
}
val nextPage = when {
items.isEmpty() -> INITIAL_PAGE
pageToLoad < wrappedItems.totalPages -> pageToLoad.inc()
else -> null
}
LoadResult.Page(items, prevKey = prevPage, nextKey = nextPage)
LoadResult.Page(wrappedItems.items, prevKey = null, nextKey = nextKey)
} catch (e: Throwable) {
Timber.e(e, "Unable to load the transaction history for the requested page: $pageToLoad")
@ -61,7 +52,7 @@ internal class TxHistoryPagingSource(
}
}
private suspend fun loadItems(pageToLoad: Int, pageSize: Int, refresh: Boolean): PaginationWrapper<TxHistoryItem> {
private suspend fun loadItems(pageToLoad: Page, pageSize: Int, refresh: Boolean): PaginationWrapper<TxHistoryItem> {
cacheRegistry.invokeOnExpire(
key = getTxHistoryPageKey(pageToLoad),
skipCache = refresh,
@ -71,23 +62,23 @@ internal class TxHistoryPagingSource(
return txHistoryItemsStore.getSync(pageToLoad)
}
private suspend fun fetch(pageToLoad: Int, pageSize: Int) {
private suspend fun fetch(pageToLoad: Page, pageSize: Int) {
val wrappedItems = walletManagersFacade.getTxHistoryItems(
userWalletId = sourceParams.userWalletId,
currency = sourceParams.currency,
page = pageToLoad,
page = sdkPageConverter.convertBack(pageToLoad),
pageSize = pageSize,
)
txHistoryItemsStore.store(key = storeKey, value = wrappedItems)
}
private suspend fun TxHistoryItemsStore.getSync(pageToLoad: Int): PaginationWrapper<TxHistoryItem> {
private suspend fun TxHistoryItemsStore.getSync(pageToLoad: Page): PaginationWrapper<TxHistoryItem> {
val storedItems = requireNotNull(getSyncOrNull(storeKey, pageToLoad)) {
"The transaction history page #$pageToLoad could not be retrieved"
}
return if (pageToLoad == 1) storedItems.addRecentTransactions() else storedItems
return if (pageToLoad is Page.Initial) storedItems.addRecentTransactions() else storedItems
}
private suspend fun PaginationWrapper<TxHistoryItem>.addRecentTransactions(): PaginationWrapper<TxHistoryItem> {
@ -131,7 +122,7 @@ internal class TxHistoryPagingSource(
return filter { item -> apiItems.none { it.txHash == item.txHash } }
}
private fun getTxHistoryPageKey(page: Int): String {
private fun getTxHistoryPageKey(page: Page): String {
return "tx_history_page_${sourceParams.currency}_${sourceParams.userWalletId}_$page"
}
@ -141,8 +132,4 @@ internal class TxHistoryPagingSource(
val pageSize: Int,
val refresh: Boolean,
)
private companion object {
private const val INITIAL_PAGE = 1
}
}

View file

@ -11,6 +11,7 @@ import com.tangem.blockchain.common.address.Address
import com.tangem.blockchain.common.address.AddressType
import com.tangem.blockchain.common.address.EstimationFeeAddressFactory
import com.tangem.blockchain.common.datastorage.BlockchainDataStorage
import com.tangem.blockchain.common.pagination.Page
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.blockchain.common.txhistory.TransactionHistoryRequest
@ -59,6 +60,7 @@ class DefaultWalletManagersFacade(
private val sdkTokenConverter by lazy { SdkTokenConverter() }
private val txHistoryStateConverter by lazy { SdkTransactionHistoryStateConverter() }
private val txHistoryItemConverter by lazy { SdkTransactionHistoryItemConverter(assetReader, moshi) }
private val sdkPageConverter by lazy { SdkPageConverter() }
private val estimationFeeAddressFactory by lazy { EstimationFeeAddressFactory(mnemonic) }
override suspend fun update(
@ -187,7 +189,7 @@ class DefaultWalletManagersFacade(
override suspend fun getTxHistoryItems(
userWalletId: UserWalletId,
currency: CryptoCurrency,
page: Int,
page: Page,
pageSize: Int,
): PaginationWrapper<TxHistoryItem> {
val walletManager = getOrCreateWalletManager(
@ -203,7 +205,8 @@ class DefaultWalletManagersFacade(
request = TransactionHistoryRequest(
address = walletManager.wallet.address,
decimals = currency.decimals,
page = TransactionHistoryRequest.Page(number = page, size = pageSize),
page = page,
pageSize = pageSize,
filterType = when (currency) {
is CryptoCurrency.Coin -> TransactionHistoryRequest.FilterType.Coin
is CryptoCurrency.Token -> TransactionHistoryRequest.FilterType.Contract(currency.contractAddress)
@ -213,9 +216,8 @@ class DefaultWalletManagersFacade(
return when (itemsResult) {
is Result.Success -> PaginationWrapper(
page = itemsResult.data.page,
totalPages = itemsResult.data.totalPages,
itemsOnPage = itemsResult.data.itemsOnPage,
currentPage = sdkPageConverter.convert(page),
nextPage = sdkPageConverter.convert(itemsResult.data.nextPage),
items = txHistoryItemConverter.convertList(itemsResult.data.items),
)
is Result.Failure -> error(itemsResult.error.message ?: itemsResult.error.customMessage)

View file

@ -5,6 +5,7 @@ import com.tangem.blockchain.blockchains.solana.RentProvider
import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.address.Address
import com.tangem.blockchain.common.address.AddressType
import com.tangem.blockchain.common.pagination.Page
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.blockchain.extensions.Result
@ -97,7 +98,7 @@ interface WalletManagersFacade {
suspend fun getTxHistoryItems(
userWalletId: UserWalletId,
currency: CryptoCurrency,
page: Int,
page: Page,
pageSize: Int,
): PaginationWrapper<TxHistoryItem>

View file

@ -0,0 +1,23 @@
package com.tangem.domain.walletmanager.utils
import com.tangem.domain.txhistory.models.Page
import com.tangem.utils.converter.TwoWayConverter
import com.tangem.blockchain.common.pagination.Page as SdkPage
class SdkPageConverter : TwoWayConverter<SdkPage, Page> {
override fun convert(value: SdkPage): Page {
return when (value) {
is SdkPage.Initial -> Page.Initial
is SdkPage.LastPage -> Page.LastPage
is SdkPage.Next -> Page.Next(value = value.value)
}
}
override fun convertBack(value: Page): SdkPage {
return when (value) {
is Page.Initial -> SdkPage.Initial
is Page.LastPage -> SdkPage.LastPage
is Page.Next -> SdkPage.Next(value = value.value)
}
}
}

View file

@ -0,0 +1,7 @@
package com.tangem.domain.txhistory.models
sealed class Page {
object Initial : Page()
data class Next(val value: String) : Page()
object LastPage : Page()
}

View file

@ -1,8 +1,7 @@
package com.tangem.domain.txhistory.models
data class PaginationWrapper<T>(
val page: Int,
val totalPages: Int,
val itemsOnPage: Int,
val currentPage: Page,
val nextPage: Page,
val items: List<T>,
)

View file

@ -85,7 +85,7 @@ web3j = "4.10.1"
# endregion Other libraries
# region Tangem
tangemBlockchainSdk = "develop-487"
tangemBlockchainSdk = "develop-488"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "develop-324"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^