diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index 960857e2eb..f38de6e571 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -20,11 +20,7 @@ import com.tangem.domain.staking.single.SingleYieldBalanceSupplier import com.tangem.domain.tokens.* import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations import com.tangem.domain.tokens.operations.CachedCurrenciesStatusesOperations -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.CurrencyChecksRepository -import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository -import com.tangem.domain.tokens.repository.TokenReceiveWarningsViewedRepository -import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository +import com.tangem.domain.tokens.repository.* import com.tangem.domain.tokens.wallet.WalletBalanceFetcher import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.tap.domain.tokens.DefaultTokensFeatureToggles @@ -60,24 +56,6 @@ internal object TokensDomainModule { ) } - @Provides - @Singleton - fun provideFetchTokenListUseCase( - currenciesRepository: CurrenciesRepository, - multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - multiYieldBalanceFetcher: MultiYieldBalanceFetcher, - stakingIdFactory: StakingIdFactory, - ): FetchTokenListUseCase { - return FetchTokenListUseCase( - currenciesRepository = currenciesRepository, - multiNetworkStatusFetcher = multiNetworkStatusFetcher, - multiQuoteStatusFetcher = multiQuoteStatusFetcher, - multiYieldBalanceFetcher = multiYieldBalanceFetcher, - stakingIdFactory = stakingIdFactory, - ) - } - @Provides @Singleton fun provideFetchPendingTransactionsUseCase( @@ -184,24 +162,6 @@ internal object TokensDomainModule { ) } - @Provides - @Singleton - fun provideFetchCardTokenListUseCase( - currenciesRepository: CurrenciesRepository, - multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - multiYieldBalanceFetcher: MultiYieldBalanceFetcher, - stakingIdFactory: StakingIdFactory, - ): FetchCardTokenListUseCase { - return FetchCardTokenListUseCase( - currenciesRepository = currenciesRepository, - multiNetworkStatusFetcher = multiNetworkStatusFetcher, - multiQuoteStatusFetcher = multiQuoteStatusFetcher, - multiYieldBalanceFetcher = multiYieldBalanceFetcher, - stakingIdFactory = stakingIdFactory, - ) - } - @Provides @Singleton fun provideGetCryptoCurrencyUseCase( diff --git a/data/account/build.gradle.kts b/data/account/build.gradle.kts index a818b24ccb..3123fadcd8 100644 --- a/data/account/build.gradle.kts +++ b/data/account/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { api(projects.domain.common) api(projects.domain.models) api(projects.domain.tokens) + api(projects.domain.wallets) // endregion // region Project - Data diff --git a/data/account/src/main/kotlin/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcher.kt b/data/account/src/main/kotlin/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcher.kt index 200e133dbd..cc6937f19c 100644 --- a/data/account/src/main/kotlin/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcher.kt +++ b/data/account/src/main/kotlin/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcher.kt @@ -51,18 +51,25 @@ internal class DefaultWalletAccountsFetcher @Inject constructor( private val dispatchers: CoroutineDispatcherProvider, ) : WalletAccountsFetcher, WalletAccountsSaver { - override suspend fun fetch(userWalletId: UserWalletId) { + override suspend fun fetch(userWalletId: UserWalletId): GetWalletAccountsResponse { val savedAccountsResponse = getAccountsResponseStore(userWalletId = userWalletId).getSyncOrNull() val accountsResponse = fetchWalletAccounts(userWalletId, savedAccountsResponse) - ?: return - if (accountsResponse.accounts.isEmpty()) { - initializeAccounts(userWalletId, accountsResponse) - } else if (accountsResponse.unassignedTokens.isNotEmpty()) { - assignTokens(userWalletId, accountsResponse) + return when { + accountsResponse.accounts.isEmpty() -> { + initializeAccounts(userWalletId, accountsResponse) + } + accountsResponse.unassignedTokens.isNotEmpty() -> { + assignTokens(userWalletId, accountsResponse) + } + else -> accountsResponse } } + override suspend fun getSaved(userWalletId: UserWalletId): GetWalletAccountsResponse? { + return getAccountsResponseStore(userWalletId = userWalletId).getSyncOrNull() + } + override suspend fun store(userWalletId: UserWalletId, response: GetWalletAccountsResponse) { val store = getAccountsResponseStore(userWalletId = userWalletId) @@ -115,7 +122,7 @@ internal class DefaultWalletAccountsFetcher @Inject constructor( private suspend fun fetchWalletAccounts( userWalletId: UserWalletId, savedAccountsResponse: GetWalletAccountsResponse?, - ): GetWalletAccountsResponse? { + ): GetWalletAccountsResponse { return safeApiCall( call = { val apiResponse = withContext(dispatchers.io) { @@ -145,7 +152,10 @@ internal class DefaultWalletAccountsFetcher @Inject constructor( ) } - private suspend fun initializeAccounts(userWalletId: UserWalletId, accountsResponse: GetWalletAccountsResponse) { + private suspend fun initializeAccounts( + userWalletId: UserWalletId, + accountsResponse: GetWalletAccountsResponse, + ): GetWalletAccountsResponse { val response = defaultWalletAccountsResponseFactory.create( userWalletId = userWalletId, userTokensResponse = UserTokensResponse( @@ -156,14 +166,17 @@ internal class DefaultWalletAccountsFetcher @Inject constructor( ) userTokensSaver.push(userWalletId = userWalletId, response = response.toUserTokensResponse()) - val syncedResponse = push(userWalletId = userWalletId, accounts = response.accounts) + val syncedResponse = push(userWalletId = userWalletId, accounts = response.accounts) ?: response - if (syncedResponse != null) { - store(userWalletId = userWalletId, response = syncedResponse) - } + store(userWalletId = userWalletId, response = syncedResponse) + + return syncedResponse } - private suspend fun assignTokens(userWalletId: UserWalletId, accountsResponse: GetWalletAccountsResponse) { + private suspend fun assignTokens( + userWalletId: UserWalletId, + accountsResponse: GetWalletAccountsResponse, + ): GetWalletAccountsResponse { val accountsResponseWithTokens = accountsResponse.assignTokens(userWalletId) store(userWalletId = userWalletId, response = accountsResponseWithTokens) @@ -172,6 +185,8 @@ internal class DefaultWalletAccountsFetcher @Inject constructor( userWalletId = userWalletId, response = accountsResponseWithTokens.toUserTokensResponse(), ) + + return accountsResponseWithTokens } private suspend fun getETag(userWalletId: UserWalletId): String? { diff --git a/data/account/src/main/kotlin/com/tangem/data/account/fetcher/FetchWalletAccountsErrorHandler.kt b/data/account/src/main/kotlin/com/tangem/data/account/fetcher/FetchWalletAccountsErrorHandler.kt index 0d9ea8c585..9ebc9c6707 100644 --- a/data/account/src/main/kotlin/com/tangem/data/account/fetcher/FetchWalletAccountsErrorHandler.kt +++ b/data/account/src/main/kotlin/com/tangem/data/account/fetcher/FetchWalletAccountsErrorHandler.kt @@ -49,11 +49,13 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor( savedAccountsResponse: GetWalletAccountsResponse?, pushWalletAccounts: suspend (UserWalletId, List) -> GetWalletAccountsResponse?, storeWalletAccounts: suspend (UserWalletId, GetWalletAccountsResponse) -> Unit, - ): GetWalletAccountsResponse? { + ): GetWalletAccountsResponse { val isResponseUpToDate = error.isNetworkError(code = Code.NOT_MODIFIED) if (isResponseUpToDate) { Timber.e("ETag is up to date, no need to update accounts for wallet: $userWalletId") - return savedAccountsResponse + return requireNotNull(savedAccountsResponse) { + "Saved accounts response is null for wallet: $userWalletId" + } } var response = savedAccountsResponse ?: createDefaultResponse(userWalletId) diff --git a/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultSingleAccountListFetcherTest.kt b/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultSingleAccountListFetcherTest.kt index a7d7628c9f..0211b1753b 100644 --- a/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultSingleAccountListFetcherTest.kt +++ b/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultSingleAccountListFetcherTest.kt @@ -29,6 +29,8 @@ class DefaultSingleAccountListFetcherTest { // Arrange val params = SingleAccountListFetcher.Params(userWalletId = userWalletId) + coEvery { walletAccountsFetcher.fetch(userWalletId) } returns mockk() + // Act val actual = fetcher.invoke(params) diff --git a/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcherTest.kt b/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcherTest.kt index 55be8a64db..e3ffe9e2a0 100644 --- a/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcherTest.kt +++ b/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcherTest.kt @@ -199,7 +199,7 @@ class DefaultWalletAccountsFetcherTest { @Test fun `fetch should call error handler when getWalletAccounts returns error`() = runTest { // Arrange - val savedAccountsResponse = null + val savedAccountsResponse = createGetWalletAccountsResponse(userWalletId) val apiError = ApiResponse.Error(ApiResponseError.NetworkException()) accountsResponseStoreFlow.value = savedAccountsResponse @@ -212,7 +212,7 @@ class DefaultWalletAccountsFetcherTest { fetchWalletAccountsErrorHandler.handle( error = apiError.cause, userWalletId = userWalletId, - savedAccountsResponse = null, + savedAccountsResponse = savedAccountsResponse, pushWalletAccounts = any(), storeWalletAccounts = any(), ) @@ -231,7 +231,7 @@ class DefaultWalletAccountsFetcherTest { fetchWalletAccountsErrorHandler.handle( error = apiError.cause, userWalletId = userWalletId, - savedAccountsResponse = null, + savedAccountsResponse = savedAccountsResponse, pushWalletAccounts = any(), storeWalletAccounts = any(), ) diff --git a/data/account/src/test/java/com/tangem/data/account/fetcher/FetchWalletAccountsErrorHandlerTest.kt b/data/account/src/test/java/com/tangem/data/account/fetcher/FetchWalletAccountsErrorHandlerTest.kt index 6500556de8..a8671e5542 100644 --- a/data/account/src/test/java/com/tangem/data/account/fetcher/FetchWalletAccountsErrorHandlerTest.kt +++ b/data/account/src/test/java/com/tangem/data/account/fetcher/FetchWalletAccountsErrorHandlerTest.kt @@ -53,6 +53,8 @@ class FetchWalletAccountsErrorHandlerTest { @Test fun `does not update accounts when response is up to date`() = runTest { // Arrange + val response = createGetWalletAccountsResponse(userWalletId) + val error = ApiResponseError.HttpException( code = Code.NOT_MODIFIED, message = "Not Modified", @@ -63,7 +65,7 @@ class FetchWalletAccountsErrorHandlerTest { handler.handle( error = error, userWalletId = userWalletId, - savedAccountsResponse = null, + savedAccountsResponse = response, pushWalletAccounts = pushWalletAccounts, storeWalletAccounts = storeWalletAccounts, ) diff --git a/data/common/src/main/kotlin/com/tangem/data/common/account/WalletAccountsFetcher.kt b/data/common/src/main/kotlin/com/tangem/data/common/account/WalletAccountsFetcher.kt index ba81c5db5a..4004ed3fcf 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/account/WalletAccountsFetcher.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/account/WalletAccountsFetcher.kt @@ -1,5 +1,6 @@ package com.tangem.data.common.account +import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse import com.tangem.domain.models.wallet.UserWalletId /** @@ -11,5 +12,8 @@ interface WalletAccountsFetcher { /** Fetch wallet accounts by [userWalletId] */ @Throws - suspend fun fetch(userWalletId: UserWalletId) + suspend fun fetch(userWalletId: UserWalletId): GetWalletAccountsResponse + + /** Get saved wallet accounts by [userWalletId] */ + suspend fun getSaved(userWalletId: UserWalletId): GetWalletAccountsResponse? } \ No newline at end of file diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcher.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcher.kt index 5c8f9d9f23..b73d076ad2 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcher.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcher.kt @@ -1,6 +1,7 @@ package com.tangem.data.tokens import arrow.core.Either +import arrow.core.right import com.tangem.data.common.account.WalletAccountsFetcher import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.core.utils.catchOn @@ -25,11 +26,15 @@ internal class AccountListCryptoCurrenciesFetcher( private val dispatchers: CoroutineDispatcherProvider, ) : MultiWalletCryptoCurrenciesFetcher { - override suspend fun invoke(params: Params) = Either.catchOn(dispatchers.default) { - val userWallet = userWalletsStore.getSyncStrict(key = params.userWalletId) + override suspend fun invoke(params: Params): Either { + return Either.catchOn(dispatchers.default) { + val userWallet = userWalletsStore.getSyncStrict(key = params.userWalletId) - if (!userWallet.isMultiCurrency) error("${this::class.simpleName} supports only multi-currency wallet") + if (!userWallet.isMultiCurrency) error("${this::class.simpleName} supports only multi-currency wallet") - walletAccountsFetcher.fetch(userWalletId = params.userWalletId) + walletAccountsFetcher.fetch(userWalletId = params.userWalletId) + + Unit.right() + } } } \ No newline at end of file diff --git a/data/tokens/src/test/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcherTest.kt b/data/tokens/src/test/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcherTest.kt index 79bcd8e6f8..fa168458d8 100644 --- a/data/tokens/src/test/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcherTest.kt +++ b/data/tokens/src/test/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcherTest.kt @@ -61,6 +61,7 @@ internal class AccountListCryptoCurrenciesFetcherTest { val mockUserWallet = mockk { every { isMultiCurrency } returns true } every { userWalletsStore.getSyncStrict(key = params.userWalletId) } returns mockUserWallet + coEvery { walletAccountsFetcher.fetch(userWalletId = params.userWalletId) } returns mockk() // Act val actual = fetcher(params) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt deleted file mode 100644 index 2c491ffdee..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt +++ /dev/null @@ -1,96 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import arrow.core.raise.Raise -import arrow.core.raise.catch -import arrow.core.raise.either -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher -import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher -import com.tangem.domain.staking.StakingIdFactory -import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher -import com.tangem.domain.tokens.error.TokenListError -import com.tangem.domain.tokens.repository.CurrenciesRepository -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope - -class FetchCardTokenListUseCase( - private val currenciesRepository: CurrenciesRepository, - private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher, - private val stakingIdFactory: StakingIdFactory, -) { - - suspend operator fun invoke(userWalletId: UserWalletId, refresh: Boolean = false): Either { - return either { - val currencies = fetchCurrencies(userWalletId = userWalletId, refresh = refresh) - - coroutineScope { - val fetchStatuses = async { - fetchNetworksStatuses( - userWalletId = userWalletId, - networks = currencies.mapTo(destination = hashSetOf(), transform = CryptoCurrency::network), - ) - } - val fetchQuotes = async { - fetchQuotes( - currenciesIds = currencies.mapNotNullTo(destination = hashSetOf()) { it.id.rawCurrencyId }, - ) - } - val yieldBalances = async { - fetchYieldBalances( - userWalletId = userWalletId, - currencies = currencies, - ) - } - awaitAll(fetchStatuses, fetchQuotes, yieldBalances) - } - } - } - - private suspend fun Raise.fetchCurrencies( - userWalletId: UserWalletId, - refresh: Boolean = false, - ): List { - return catch( - block = { - currenciesRepository.getSingleCurrencyWalletWithCardCurrencies( - userWalletId = userWalletId, - refresh = refresh, - ) - }, - catch = { raise(TokenListError.DataError(it)) }, - ) - } - - private suspend fun Raise.fetchNetworksStatuses( - userWalletId: UserWalletId, - networks: Set, - ) { - multiNetworkStatusFetcher( - MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks), - ) - .mapLeft(TokenListError::DataError) - .bind() - } - - private suspend fun fetchQuotes(currenciesIds: Set) { - multiQuoteStatusFetcher( - params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null), - ) - } - - private suspend fun fetchYieldBalances(userWalletId: UserWalletId, currencies: List) { - val stakingIds = currencies.mapNotNullTo(hashSetOf()) { - stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull() - } - - multiYieldBalanceFetcher( - params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds), - ) - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt deleted file mode 100644 index d4df6acfcd..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt +++ /dev/null @@ -1,117 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import arrow.core.raise.Raise -import arrow.core.raise.catch -import arrow.core.raise.either -import arrow.core.raise.ensureNotNull -import arrow.core.toNonEmptyListOrNull -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher -import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher -import com.tangem.domain.staking.StakingIdFactory -import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher -import com.tangem.domain.tokens.error.TokenListError -import com.tangem.domain.tokens.repository.CurrenciesRepository -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope - -/** - * Use case responsible for fetching token list information, including currency data, - * network statuses, and quotes for tokens associated with a user's wallet. - * - * @param currenciesRepository The repository for retrieving currency-related data. - */ -class FetchTokenListUseCase( - private val currenciesRepository: CurrenciesRepository, - private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher, - private val stakingIdFactory: StakingIdFactory, -) { - - /** - * Fetches the token list information for a user's wallet, including currency data, - * network statuses, and quotes for associated tokens. - * - * @param userWalletId The ID of the user's wallet. - * @return An [Either] representing success (Right) or an error (Left) in fetching the token list. - */ - suspend operator fun invoke(userWalletId: UserWalletId): Either = either { - val currencies = fetchCurrencies(userWalletId) - - invoke(userWalletId = userWalletId, currencies = currencies) - } - - suspend operator fun invoke( - userWalletId: UserWalletId, - currencies: List, - ): Either = either { - coroutineScope { - val fetchStatuses = async { - fetchNetworksStatuses( - userWalletId = userWalletId, - networks = currencies.mapTo(hashSetOf()) { it.network }, - ) - } - val fetchQuotes = async { - fetchQuotes( - currenciesIds = currencies.mapTo(hashSetOf()) { it.id }, - ) - } - - val yieldBalances = async { - fetchYieldBalances(userWalletId = userWalletId, currencies = currencies) - } - - awaitAll(fetchStatuses, fetchQuotes, yieldBalances) - } - } - - private suspend fun Raise.fetchCurrencies(userWalletId: UserWalletId): List { - val currencies = catch( - block = { currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId, true) }, - ) { - raise(TokenListError.DataError(it)) - } - - return ensureNotNull(currencies.toNonEmptyListOrNull()) { - TokenListError.EmptyTokens - } - } - - private suspend fun Raise.fetchNetworksStatuses( - userWalletId: UserWalletId, - networks: Set, - ) { - multiNetworkStatusFetcher( - params = MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks), - ) - .mapLeft(TokenListError::DataError) - .bind() - } - - private suspend fun Raise.fetchQuotes(currenciesIds: Set) { - multiQuoteStatusFetcher( - params = MultiQuoteStatusFetcher.Params( - currenciesIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet(), - appCurrencyId = null, - ), - ) - .mapLeft(TokenListError::DataError) - .bind() - } - - private suspend fun fetchYieldBalances(userWalletId: UserWalletId, currencies: List) { - val stakingIds = currencies.mapNotNullTo(hashSetOf()) { - stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull() - } - - multiYieldBalanceFetcher( - params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds), - ) - } -} \ No newline at end of file