diff --git a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt index 55dab8c3b9..52ecf3a396 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt @@ -5,6 +5,7 @@ import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.demo.models.DemoConfig import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.networks.single.SingleNetworkStatusSupplier +import com.tangem.domain.notifications.repository.PushNotificationsRepository import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase @@ -56,6 +57,7 @@ internal object TransactionDomainModule { singleNetworkStatusFetcher: SingleNetworkStatusFetcher, tangemHotWalletSignerFactory: TangemHotWalletSigner.Factory, dispatchers: CoroutineDispatcherProvider, + pushNotificationsRepository: PushNotificationsRepository, ): SendTransactionUseCase { return SendTransactionUseCase( demoConfig = DemoConfig, @@ -65,6 +67,7 @@ internal object TransactionDomainModule { singleNetworkStatusFetcher = singleNetworkStatusFetcher, parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.io), getHotWalletSigner = tangemHotWalletSignerFactory::create, + pushNotificationsRepository = pushNotificationsRepository, ) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt index cf0d66f054..aa8748eb2c 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt @@ -203,7 +203,7 @@ interface TangemTechApi { * Used when yield operations generate intermediate transactions * that should not trigger notifications. */ - @POST("v1/transaction-events") + @POST("v2/transaction-events") suspend fun transactionEvents(@Body name: TransactionEventBody): ApiResponse // region Earn diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/TransactionEventBody.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/TransactionEventBody.kt index 806b775af1..853a2ce043 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/TransactionEventBody.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/TransactionEventBody.kt @@ -7,6 +7,7 @@ import com.squareup.moshi.JsonClass data class TransactionEventBody( @Json(name = "transactionId") val transactionId: String, @Json(name = "operationType") val operationType: OperationType, + @Json(name = "userAddress") val userAddress: String? = null, ) @JsonClass(generateAdapter = false) diff --git a/data/notifications/src/main/java/com/tangem/data/notifications/DefaultPushNotificationsRepository.kt b/data/notifications/src/main/java/com/tangem/data/notifications/DefaultPushNotificationsRepository.kt index e98f62d817..34a6666a6c 100644 --- a/data/notifications/src/main/java/com/tangem/data/notifications/DefaultPushNotificationsRepository.kt +++ b/data/notifications/src/main/java/com/tangem/data/notifications/DefaultPushNotificationsRepository.kt @@ -15,10 +15,14 @@ import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getSyncOrNull import com.tangem.datasource.local.preferences.utils.store +import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.notifications.models.ApplicationId import com.tangem.domain.notifications.models.NotificationsError import com.tangem.domain.notifications.repository.PushNotificationsRepository import com.tangem.domain.notifications.models.NotificationsEligibleNetwork +import com.tangem.datasource.local.preferences.utils.getObjectMap +import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.flow.map import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.info.AppInfoProvider import kotlinx.coroutines.withContext @@ -96,4 +100,9 @@ internal class DefaultPushNotificationsRepository @Inject constructor( NotificationsEligibleNetworkConverter.convert(it) } } + + override suspend fun isNotificationsEnabled(userWalletId: UserWalletId): Boolean = + appPreferencesStore.getObjectMap(PreferencesKeys.NOTIFICATIONS_ENABLED_STATES_KEY) + .map { it[userWalletId.stringValue] == true } + .firstOrNull() == true } \ No newline at end of file diff --git a/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt b/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt index f7c4ffff50..06b461cbd4 100644 --- a/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt +++ b/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt @@ -422,7 +422,11 @@ internal class DefaultTransactionRepository( preparer.prepareAndSignMultiple(transactionData, signer) } - override suspend fun sendTransactionHash(hash: String, transactionType: EventTransactionTypeDto) { + override suspend fun sendTransactionHash( + hash: String, + transactionType: EventTransactionTypeDto, + userAddress: String?, + ) { runCatching(dispatchers.io) { val operationType = when (transactionType) { EventTransactionTypeDto.DEPOSIT -> OperationType.YIELD_DEPOSIT @@ -432,6 +436,7 @@ internal class DefaultTransactionRepository( val body = TransactionEventBody( operationType = operationType, transactionId = hash, + userAddress = userAddress, ) val response = tangemTechApi.transactionEvents(body) response.fold( diff --git a/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/PushNotificationsRepository.kt b/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/PushNotificationsRepository.kt index 53f7b08f65..e6024ff337 100644 --- a/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/PushNotificationsRepository.kt +++ b/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/PushNotificationsRepository.kt @@ -1,6 +1,7 @@ package com.tangem.domain.notifications.repository import arrow.core.Either +import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.notifications.models.ApplicationId import com.tangem.domain.notifications.models.NotificationsEligibleNetwork import com.tangem.domain.notifications.models.NotificationsError @@ -20,4 +21,6 @@ interface PushNotificationsRepository { @Throws suspend fun getEligibleNetworks(): List + + suspend fun isNotificationsEnabled(userWalletId: UserWalletId): Boolean } \ No newline at end of file diff --git a/domain/transaction/build.gradle.kts b/domain/transaction/build.gradle.kts index 8488e0c17b..9bf72aeddb 100644 --- a/domain/transaction/build.gradle.kts +++ b/domain/transaction/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { implementation(projects.domain.transaction.models) implementation(projects.domain.demo) implementation(projects.domain.card) + implementation(projects.domain.notifications) api(projects.domain.networks) testRuntimeOnly(deps.test.junit5.engine) diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt index efa2d59016..74958179f4 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt @@ -125,5 +125,5 @@ interface TransactionRepository { network: Network, ): com.tangem.blockchain.extensions.Result> - suspend fun sendTransactionHash(hash: String, transactionType: EventTransactionTypeDto) + suspend fun sendTransactionHash(hash: String, transactionType: EventTransactionTypeDto, userAddress: String?) } \ No newline at end of file diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/SendTransactionUseCase.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/SendTransactionUseCase.kt index 17b9fc38cc..05bc7a7445 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/SendTransactionUseCase.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/SendTransactionUseCase.kt @@ -25,6 +25,7 @@ import com.tangem.domain.demo.models.DemoConfig import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.networks.single.SingleNetworkStatusFetcher +import com.tangem.domain.notifications.repository.PushNotificationsRepository import com.tangem.domain.transaction.TransactionRepository import com.tangem.domain.transaction.error.SendTransactionError import com.tangem.domain.transaction.error.parseWrappedError @@ -44,6 +45,7 @@ class SendTransactionUseCase( private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher, private val parallelUpdatingScope: CoroutineScope, private val getHotWalletSigner: (UserWallet.Hot) -> TransactionSigner, + private val pushNotificationsRepository: PushNotificationsRepository, ) { suspend operator fun invoke( txsData: List, @@ -112,7 +114,11 @@ class SendTransactionUseCase( } .fold( ifRight = { result -> - processSentTransactionsHashes(txsData, result.hashes) + processSentTransactionsHashes( + userWallet = userWallet, + transactions = txsData, + hashes = result.hashes, + ) result.hashes.right() }, ifLeft = { it.left() }, @@ -128,11 +134,19 @@ class SendTransactionUseCase( .map { it.first() } } - private fun processSentTransactionsHashes(transactions: List, hashes: List) { + private fun processSentTransactionsHashes( + userWallet: UserWallet, + transactions: List, + hashes: List, + ) { parallelUpdatingScope.launch { withContext(NonCancellable) { transactions.forEachIndexed { ind, tx -> - sendHashToBackendIfNeeded(tx, hashes[ind]) + sendHashToBackendIfNeeded( + userWallet = userWallet, + transaction = tx, + txHash = hashes[ind], + ) } } } @@ -141,7 +155,11 @@ class SendTransactionUseCase( /** * Sends tx hash to backend for specific transaction types */ - private suspend fun sendHashToBackendIfNeeded(transaction: TransactionData, txHash: String) { + private suspend fun sendHashToBackendIfNeeded( + userWallet: UserWallet, + transaction: TransactionData, + txHash: String, + ) { (transaction as? TransactionData.Uncompiled)?.let { tx -> val extras = tx.extras when (extras) { @@ -152,7 +170,19 @@ class SendTransactionUseCase( is EthereumYieldSupplyExitCallData -> EventTransactionTypeDto.WITHDRAW else -> return } - transactionRepository.sendTransactionHash(txHash, txType) + val isPushNotificationEnabled = pushNotificationsRepository.isNotificationsEnabled( + userWallet.walletId, + ) + val userAddress = if (isPushNotificationEnabled) { + transaction.sourceAddress + } else { + null + } + transactionRepository.sendTransactionHash( + hash = txHash, + transactionType = txType, + userAddress = userAddress, + ) } } }