From c1ca73561df76d875a7be0a18b3c1b80bcbf84bd Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 17 Oct 2025 23:45:25 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/utils/TangemBlogUrlBuilder.kt | 2 + ...dShowYieldSupplyDepositedWarningUseCase.kt | 11 +- ...wYieldSupplyDepositedWarningUseCaseTest.kt | 107 ------------------ .../supply/impl/common/YieldSupplyTrigger.kt | 39 +++++++ .../impl/di/YieldSupplyFeatureModule.kt | 17 +++ .../impl/main/model/YieldSupplyModel.kt | 24 ++++ .../impl/promo/model/YieldSupplyPromoModel.kt | 5 +- .../model/YieldSupplyStartEarningModel.kt | 14 +-- .../model/YieldSupplyStopEarningModel.kt | 11 +- 9 files changed, 101 insertions(+), 129 deletions(-) delete mode 100644 domain/tokens/src/test/kotlin/com/tangem/domain/tokens/NeedShowYieldSupplyDepositedWarningUseCaseTest.kt create mode 100644 features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyTrigger.kt diff --git a/core/utils/src/main/java/com/tangem/utils/TangemBlogUrlBuilder.kt b/core/utils/src/main/java/com/tangem/utils/TangemBlogUrlBuilder.kt index 4b6406002d..3bb43d00e2 100644 --- a/core/utils/src/main/java/com/tangem/utils/TangemBlogUrlBuilder.kt +++ b/core/utils/src/main/java/com/tangem/utils/TangemBlogUrlBuilder.kt @@ -22,4 +22,6 @@ object TangemBlogUrlBuilder { const val RESOURCE_TO_LEARN_ABOUT_APPROVING_IN_SWAP = "https://tangem.com/en/blog/post/give-revoke-permission/" const val YIELD_SUPPLY_HOW_IT_WORKS_URL = "https://tangem.com/en/blog/post/savings-account" + const val YIELD_SUPPLY_TOS_URL = "https://aave.com/terms-of-service" + const val YIELD_SUPPLY_PRIVACY_URL = "https://aave.com/privacy-policy" } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/NeedShowYieldSupplyDepositedWarningUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/NeedShowYieldSupplyDepositedWarningUseCase.kt index 417e84e987..fa90d45903 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/NeedShowYieldSupplyDepositedWarningUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/NeedShowYieldSupplyDepositedWarningUseCase.kt @@ -5,15 +5,18 @@ import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext +@Suppress("UnusedPrivateProperty") class NeedShowYieldSupplyDepositedWarningUseCase( private val yieldSupplyWarningsViewedRepository: YieldSupplyWarningsViewedRepository, private val dispatchers: CoroutineDispatcherProvider, ) { suspend operator fun invoke(cryptoCurrencyStatus: CryptoCurrencyStatus?): Boolean = withContext(dispatchers.io) { - val hasActiveLending = cryptoCurrencyStatus?.value?.yieldSupplyStatus?.isActive == true - if (!hasActiveLending) return@withContext false - val showedWarnings = yieldSupplyWarningsViewedRepository.getViewedWarnings() - return@withContext !showedWarnings.contains(cryptoCurrencyStatus?.currency?.name) + // TEMPORARY REQUIREMENTS + return@withContext false + // val hasActiveLending = cryptoCurrencyStatus?.value?.yieldSupplyStatus?.isActive == true + // if (!hasActiveLending) return@withContext false + // val showedWarnings = yieldSupplyWarningsViewedRepository.getViewedWarnings() + // return@withContext !showedWarnings.contains(cryptoCurrencyStatus?.currency?.name) } } \ No newline at end of file diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/NeedShowYieldSupplyDepositedWarningUseCaseTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/NeedShowYieldSupplyDepositedWarningUseCaseTest.kt deleted file mode 100644 index 1873ddeed3..0000000000 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/NeedShowYieldSupplyDepositedWarningUseCaseTest.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.tangem.domain.tokens - -import com.google.common.truth.Truth.assertThat -import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.domain.models.network.NetworkAddress -import com.tangem.domain.models.serialization.SerializedBigDecimal -import com.tangem.domain.models.yield.supply.YieldSupplyStatus -import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository -import com.tangem.domain.tokens.mock.MockTokens -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider -import io.mockk.coEvery -import io.mockk.coVerify -import io.mockk.impl.annotations.RelaxedMockK -import io.mockk.junit5.MockKExtension -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith - -@OptIn(ExperimentalCoroutinesApi::class) -@ExtendWith(MockKExtension::class) -class NeedShowYieldSupplyDepositedWarningUseCaseTest { - - @RelaxedMockK - private lateinit var repository: YieldSupplyWarningsViewedRepository - - private lateinit var dispatchers: TestingCoroutineDispatcherProvider - - @BeforeEach - fun setup() { - dispatchers = TestingCoroutineDispatcherProvider() - } - - @Test - fun `GIVEN null status WHEN invoke THEN returns false`() = runTest { - val useCase = NeedShowYieldSupplyDepositedWarningUseCase(repository, dispatchers) - - val result = useCase.invoke(null) - - assertThat(result).isFalse() - coVerify(exactly = 0) { repository.getViewedWarnings() } - } - - @Test - fun `GIVEN inactive lending WHEN invoke THEN returns false`() = runTest { - val useCase = NeedShowYieldSupplyDepositedWarningUseCase(repository, dispatchers) - val status = createStatus(isActive = false) - - val result = useCase.invoke(status) - - assertThat(result).isFalse() - coVerify(exactly = 0) { repository.getViewedWarnings() } - } - - @Test - fun `GIVEN active lending and not viewed WHEN invoke THEN returns true`() = runTest { - val useCase = NeedShowYieldSupplyDepositedWarningUseCase(repository, dispatchers) - val status = createStatus(isActive = true) - coEvery { repository.getViewedWarnings() } returns emptySet() - - val result = useCase.invoke(status) - - assertThat(result).isTrue() - coVerify(exactly = 1) { repository.getViewedWarnings() } - } - - @Test - fun `GIVEN active lending and already viewed WHEN invoke THEN returns false`() = runTest { - val useCase = NeedShowYieldSupplyDepositedWarningUseCase(repository, dispatchers) - val status = createStatus(isActive = true) - coEvery { repository.getViewedWarnings() } returns setOf(status.currency.name) - - val result = useCase.invoke(status) - - assertThat(result).isFalse() - coVerify(exactly = 1) { repository.getViewedWarnings() } - } - - private fun createStatus(isActive: Boolean): CryptoCurrencyStatus { - val currency = MockTokens.token1 - val yieldSupplyStatus = YieldSupplyStatus( - isActive = isActive, - isInitialized = true, - isAllowedToSpend = true, - ) - val value = CryptoCurrencyStatus.NoQuote( - amount = SerializedBigDecimal.ZERO, - yieldBalance = null, - yieldSupplyStatus = yieldSupplyStatus, - hasCurrentNetworkTransactions = false, - pendingTransactions = emptySet(), - networkAddress = NetworkAddress.Single( - defaultAddress = NetworkAddress.Address( - value = "address", - type = NetworkAddress.Address.Type.Primary, - ), - ), - sources = CryptoCurrencyStatus.Sources(), - ) - - return CryptoCurrencyStatus( - currency = currency, - value = value, - ) - } -} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyTrigger.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyTrigger.kt new file mode 100644 index 0000000000..691095237a --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyTrigger.kt @@ -0,0 +1,39 @@ +package com.tangem.features.yield.supply.impl.common + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Trigger for entering/exiting protocol from other components + */ +interface YieldSupplyProtocolTrigger { + suspend fun onEnterProtocol() + suspend fun onExitProtocol() +} + +/** + * Listener to observe entering/exiting protocol events + */ +interface YieldSupplyProtocolListener { + val enterProtocolTriggerFlow: Flow + val exitProtocolTriggerFlow: Flow +} + +@Singleton +internal class DefaultYieldSupplyProtocolTrigger @Inject constructor() : + YieldSupplyProtocolTrigger, + YieldSupplyProtocolListener { + + override val enterProtocolTriggerFlow = MutableSharedFlow() + override val exitProtocolTriggerFlow = MutableSharedFlow() + + override suspend fun onEnterProtocol() { + enterProtocolTriggerFlow.emit(Unit) + } + + override suspend fun onExitProtocol() { + exitProtocolTriggerFlow.emit(Unit) + } +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/di/YieldSupplyFeatureModule.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/di/YieldSupplyFeatureModule.kt index 45b8806bd6..9226bcfa8e 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/di/YieldSupplyFeatureModule.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/di/YieldSupplyFeatureModule.kt @@ -3,6 +3,10 @@ package com.tangem.features.yield.supply.impl.di import com.tangem.core.configtoggle.feature.FeatureTogglesManager import com.tangem.features.yield.supply.impl.DefaultYieldSupplyFeatureToggles import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles +import com.tangem.features.yield.supply.impl.common.DefaultYieldSupplyProtocolTrigger +import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolListener +import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolTrigger +import dagger.Binds import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -18,4 +22,17 @@ internal object YieldSupplyFeatureModule { fun provideYieldFeatureToggles(featureTogglesManager: FeatureTogglesManager): YieldSupplyFeatureToggles { return DefaultYieldSupplyFeatureToggles(featureTogglesManager) } +} + +@InstallIn(SingletonComponent::class) +@Module +internal interface YieldSupplyProtocolModuleBinds { + + @Singleton + @Binds + fun bindYieldSupplyProtocolTrigger(impl: DefaultYieldSupplyProtocolTrigger): YieldSupplyProtocolTrigger + + @Singleton + @Binds + fun bindYieldSupplyProtocolListener(impl: DefaultYieldSupplyProtocolTrigger): YieldSupplyProtocolListener } \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt index 8b1e2a09d7..053cd01001 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt @@ -27,6 +27,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyIsAvailableUseCase import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.api.YieldSupplyComponent import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics +import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolListener import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM import com.tangem.features.yield.supply.impl.main.model.transformers.YieldSupplyTokenStatusSuccessTransformer import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -56,6 +57,7 @@ internal class YieldSupplyModel @Inject constructor( private val yieldSupplyIsAvailableUseCase: YieldSupplyIsAvailableUseCase, private val yieldSupplyActivateUseCase: YieldSupplyActivateUseCase, private val yieldSupplyDeactivateUseCase: YieldSupplyDeactivateUseCase, + private val yieldSupplyProtocolListener: YieldSupplyProtocolListener, ) : Model(), YieldSupplyClickIntents { private val params = paramsContainer.require() @@ -83,6 +85,28 @@ internal class YieldSupplyModel @Inject constructor( init { checkIfYieldSupplyIsAvailable() + observeProtocolEvents() + } + + private fun observeProtocolEvents() { + yieldSupplyProtocolListener.exitProtocolTriggerFlow.onEach { + uiState.update { + YieldSupplyUM.Processing.Exit + } + coroutineScope.launch(dispatchers.io) { + delay(PROCESSING_UPDATE_DELAY) + fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId, cryptoCurrency.id) + } + }.launchIn(modelScope) + yieldSupplyProtocolListener.enterProtocolTriggerFlow.onEach { + uiState.update { + YieldSupplyUM.Processing.Enter + } + coroutineScope.launch(dispatchers.io) { + delay(PROCESSING_UPDATE_DELAY) + fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId, cryptoCurrency.id) + } + }.launchIn(modelScope) } private fun checkIfYieldSupplyIsAvailable() { diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoModel.kt index 812323df89..09c57f0305 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoModel.kt @@ -15,6 +15,7 @@ import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics import com.tangem.features.yield.supply.impl.promo.YieldSupplyPromoConfig import com.tangem.features.yield.supply.impl.promo.entity.YieldSupplyPromoUM +import com.tangem.utils.TangemBlogUrlBuilder import com.tangem.utils.TangemBlogUrlBuilder.YIELD_SUPPLY_HOW_IT_WORKS_URL import com.tangem.utils.coroutines.CoroutineDispatcherProvider import javax.inject.Inject @@ -31,8 +32,8 @@ internal class YieldSupplyPromoModel @Inject constructor( val params: YieldSupplyPromoComponent.Params = paramsContainer.require() val uiState: YieldSupplyPromoUM = YieldSupplyPromoUM( - tosLink = "https://tangem.com/terms-of-service/", // TODO replace with real link - policyLink = "https://tangem.com/privacy-policy/", // TODO replace with real link + tosLink = TangemBlogUrlBuilder.YIELD_SUPPLY_TOS_URL, + policyLink = TangemBlogUrlBuilder.YIELD_SUPPLY_PRIVACY_URL, title = resourceReference(R.string.yield_module_promo_screen_title), subtitle = resourceReference( R.string.yield_module_promo_screen_variable_rate_info, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index f7390118e6..aaa41615e2 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt @@ -15,7 +15,6 @@ import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.tokens.FetchCurrencyStatusUseCase import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.transaction.error.GetFeeError @@ -29,6 +28,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyStartEarningUseCase import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory +import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolTrigger import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM import com.tangem.features.yield.supply.impl.common.entity.transformer.YieldSupplyTransactionInProgressTransformer @@ -41,7 +41,6 @@ import com.tangem.features.yield.supply.impl.subcomponents.startearning.model.tr import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.orZero import com.tangem.utils.transformer.update -import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber @@ -63,11 +62,11 @@ internal class YieldSupplyStartEarningModel @Inject constructor( private val yieldSupplyEstimateEnterFeeUseCase: YieldSupplyEstimateEnterFeeUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val yieldSupplyNotificationsUpdateTrigger: YieldSupplyNotificationsUpdateTrigger, - private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, private val yieldSupplyAlertFactory: YieldSupplyAlertFactory, private val yieldSupplyActivateUseCase: YieldSupplyActivateUseCase, private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase, private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase, + private val yieldSupplyProtocolTrigger: YieldSupplyProtocolTrigger, ) : Model(), YieldSupplyNotificationsComponent.ModelCallback { private val params: YieldSupplyStartEarningComponent.Params = paramsContainer.require() @@ -253,14 +252,9 @@ internal class YieldSupplyStartEarningModel @Inject constructor( ) }, ifRight = { - yieldSupplyActivateUseCase(cryptoCurrency) - modelScope.launch(NonCancellable) { - fetchCurrencyStatusUseCase( - userWalletId = userWallet.walletId, - cryptoCurrency.id, - ) - } + yieldSupplyProtocolTrigger.onEnterProtocol() analytics.send(YieldSupplyAnalytics.FundsEarned) + yieldSupplyActivateUseCase(cryptoCurrency) modelScope.launch { params.callback.onTransactionSent() } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt index 9e704f9967..268ab35f31 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt @@ -13,7 +13,6 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.domain.tokens.FetchCurrencyStatusUseCase import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase import com.tangem.domain.transaction.usecase.GetFeeUseCase import com.tangem.domain.transaction.usecase.SendTransactionUseCase @@ -22,6 +21,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyStopEarningUseCase import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory +import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolTrigger import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM import com.tangem.features.yield.supply.impl.common.entity.transformer.YieldSupplyTransactionInProgressTransformer @@ -35,7 +35,6 @@ import com.tangem.utils.TangemBlogUrlBuilder import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.orZero import com.tangem.utils.transformer.update -import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber @@ -56,7 +55,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor( private val yieldSupplyNotificationsUpdateTrigger: YieldSupplyNotificationsUpdateTrigger, private val yieldSupplyAlertFactory: YieldSupplyAlertFactory, private val yieldSupplyDeactivateUseCase: YieldSupplyDeactivateUseCase, - private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, + private val yieldSupplyProtocolTrigger: YieldSupplyProtocolTrigger, ) : Model(), YieldSupplyNotificationsComponent.ModelCallback { private val params: YieldSupplyStopEarningComponent.Params = paramsContainer.require() @@ -159,6 +158,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor( ) }, ifRight = { + yieldSupplyProtocolTrigger.onExitProtocol() analytics.send( YieldSupplyAnalytics.FundsWithdrawn( token = cryptoCurrency.symbol, @@ -166,10 +166,9 @@ internal class YieldSupplyStopEarningModel @Inject constructor( ), ) yieldSupplyDeactivateUseCase(cryptoCurrency) - modelScope.launch(NonCancellable) { - fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId, cryptoCurrency.id) + modelScope.launch { + params.callback.onTransactionSent() } - params.callback.onTransactionSent() }, ) }