Updated on 2026-08-14
This commit is contained in:
parent
50c9368ce3
commit
3e7825b2e3
9 changed files with 66 additions and 59 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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>,
|
||||
)
|
||||
|
|
@ -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 ^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue