Updated on 2026-08-14

This commit is contained in:
Tangem 2025-05-21 16:24:36 +05:00
commit fdfb07ee33
17 changed files with 263 additions and 20 deletions

View file

@ -154,6 +154,28 @@
android:scheme="tangem" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="main"
android:scheme="tangem" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="token"
android:scheme="tangem" />
</intent-filter>
</activity>
<!-- Disable android.startup completely. Used for Worker according doc -->

View file

@ -8,6 +8,8 @@ import com.tangem.feature.referral.api.deeplink.ReferralDeepLinkHandler
import com.tangem.features.onramp.deeplink.BuyDeepLinkHandler
import com.tangem.features.onramp.deeplink.OnrampDeepLinkHandler
import com.tangem.features.send.v2.api.deeplink.SellDeepLinkHandler
import com.tangem.features.tokendetails.deeplink.TokenDetailsDeepLinkHandler
import com.tangem.features.wallet.deeplink.WalletDeepLinkHandler
import com.tangem.features.walletconnect.components.deeplink.WalletConnectDeepLinkHandler
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
@ -20,6 +22,7 @@ import kotlinx.coroutines.flow.transformLatest
import timber.log.Timber
import javax.inject.Inject
@Suppress("LongParameterList")
@ActivityScoped
internal class DeepLinkFactory @Inject constructor(
private val onrampDeepLink: OnrampDeepLinkHandler.Factory,
@ -27,6 +30,8 @@ internal class DeepLinkFactory @Inject constructor(
private val buyDeepLink: BuyDeepLinkHandler.Factory,
private val referralDeepLink: ReferralDeepLinkHandler.Factory,
private val walletConnectDeepLink: WalletConnectDeepLinkHandler.Factory,
private val walletDeepLink: WalletDeepLinkHandler.Factory,
private val tokenDetailsDeepLink: TokenDetailsDeepLinkHandler.Factory,
) {
private val permittedAppRoute = MutableStateFlow(false)
@ -88,25 +93,27 @@ internal class DeepLinkFactory @Inject constructor(
}
private fun handleTangemDeepLinks(deeplinkUri: Uri, coroutineScope: CoroutineScope) {
val params = getParams(deeplinkUri)
val queryParams = getQueryParams(deeplinkUri)
when (deeplinkUri.host) {
DeepLinkRoute.Onramp.host -> onrampDeepLink.create(coroutineScope, params)
DeepLinkRoute.Sell.host -> sellDeepLink.create(coroutineScope, params)
DeepLinkRoute.Onramp.host -> onrampDeepLink.create(coroutineScope, queryParams)
DeepLinkRoute.Sell.host -> sellDeepLink.create(coroutineScope, queryParams)
DeepLinkRoute.Buy.host -> buyDeepLink.create(coroutineScope)
DeepLinkRoute.Referral.host -> referralDeepLink.create()
DeepLinkRoute.Wallet.host -> walletDeepLink.create()
DeepLinkRoute.TokenDetails.host -> tokenDetailsDeepLink.create(coroutineScope, queryParams)
else -> {
Timber.i(
"""
No match found for deep link
|- Received URI: $deeplinkUri
|- With params: $params
|- With params: $queryParams
""".trimIndent(),
)
}
}
}
private fun getParams(uri: Uri): Map<String, String> {
private fun getQueryParams(uri: Uri): Map<String, String> {
val params = mutableMapOf<String, String>()
uri.queryParameterNames.forEach { paramName ->

View file

@ -6,6 +6,8 @@ import com.tangem.feature.referral.api.deeplink.ReferralDeepLinkHandler
import com.tangem.features.onramp.deeplink.BuyDeepLinkHandler
import com.tangem.features.onramp.deeplink.OnrampDeepLinkHandler
import com.tangem.features.send.v2.api.deeplink.SellDeepLinkHandler
import com.tangem.features.tokendetails.deeplink.TokenDetailsDeepLinkHandler
import com.tangem.features.wallet.deeplink.WalletDeepLinkHandler
import com.tangem.features.walletconnect.components.deeplink.WalletConnectDeepLinkHandler
import io.mockk.every
import io.mockk.mockk
@ -37,6 +39,12 @@ class DeepLinkFactoryTest {
private val walletConnectDeepLinkFactory = mockk<WalletConnectDeepLinkHandler.Factory>(relaxed = true) {
every { create(any()) } returns mockk()
}
private val walletDeepLinkFactory = mockk<WalletDeepLinkHandler.Factory>(relaxed = true) {
every { create() } returns mockk()
}
private val tokenDetailsDeepLinkFactory = mockk<TokenDetailsDeepLinkHandler.Factory>(relaxed = true) {
every { create(any(), any()) } returns mockk()
}
private val mockedUri = mockk<Uri>(relaxed = true)
@ -49,6 +57,8 @@ class DeepLinkFactoryTest {
buyDeepLinkFactory,
referralDeepLinkFactory,
walletConnectDeepLinkFactory,
walletDeepLinkFactory,
tokenDetailsDeepLinkFactory,
)
@OptIn(ExperimentalCoroutinesApi::class)
@ -162,6 +172,8 @@ class DeepLinkFactoryTest {
buyDeepLinkFactory.create(any())
referralDeepLinkFactory.create()
walletConnectDeepLinkFactory.create(any())
walletDeepLinkFactory.create()
tokenDetailsDeepLinkFactory.create(any(), any())
}
}
@ -186,6 +198,12 @@ class DeepLinkFactoryTest {
advanceUntilIdle()
verify { sellDeepLinkFactory.create(eq(testScope), eq(mapOf("param" to "value"))) }
// Test Token Details
every { mockedUri.host } returns "token"
deepLinkFactory.handleDeeplink(mockedUri, testScope)
advanceUntilIdle()
verify { tokenDetailsDeepLinkFactory.create(eq(testScope), eq(mapOf("param" to "value"))) }
// Reset params
every { mockedUri.queryParameterNames } returns emptySet()
every { mockedUri.getQueryParameter(any()) } returns ""
@ -201,6 +219,12 @@ class DeepLinkFactoryTest {
deepLinkFactory.handleDeeplink(mockedUri, testScope)
advanceUntilIdle()
verify { referralDeepLinkFactory.create() }
// Test Wallet
every { mockedUri.host } returns "main"
deepLinkFactory.handleDeeplink(mockedUri, testScope)
advanceUntilIdle()
verify { walletDeepLinkFactory.create() }
}
@Test
@ -219,6 +243,8 @@ class DeepLinkFactoryTest {
buyDeepLinkFactory.create(any())
referralDeepLinkFactory.create()
walletConnectDeepLinkFactory.create(any())
walletDeepLinkFactory.create()
tokenDetailsDeepLinkFactory.create(any(), any())
}
}