Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-06 13:39:30 +03:00
commit 92849d43c2
1407 changed files with 64092 additions and 11990 deletions

View file

@ -10,31 +10,33 @@ android {
}
dependencies {
/* Core */
implementation(projects.core.decompose)
implementation(projects.core.configToggles)
implementation(projects.core.utils)
/* Domain */
implementation(projects.domain.qrScanning.models)
implementation(projects.domain.models)
implementation(projects.domain.tokens.models)
implementation(projects.domain.wallets.models)
implementation(projects.domain.staking)
implementation(projects.domain.markets.models)
implementation(projects.domain.onramp.models)
implementation(projects.domain.appCurrency.models)
implementation(projects.domain.nft.models)
implementation(projects.domain.feedback.models)
implementation(projects.domain.visa.models)
/* Libs - Other */
// region Kotlin
api(deps.kotlin.serialization)
implementation(deps.androidx.core.ktx)
// endregion
/* Tests */
testImplementation(deps.test.junit5)
// region Core
api(projects.core.analytics.models)
api(projects.core.decompose)
api(projects.core.utils)
// endregion
// region Domain
api(projects.domain.appCurrency.models)
api(projects.domain.feedback.models)
api(projects.domain.markets.models)
api(projects.domain.models)
api(projects.domain.nft.models)
api(projects.domain.onramp.models)
api(projects.domain.staking)
api(projects.domain.tokens.models)
implementation(projects.domain.visa.models)
// endregion
// region Tests
testImplementation(deps.test.coroutine)
testImplementation(deps.test.truth)
testImplementation(deps.test.junit5)
testImplementation(deps.test.mockk)
testImplementation(deps.test.truth)
// endregion
}

View file

@ -6,6 +6,7 @@ import android.annotation.SuppressLint
import android.os.Bundle
import com.tangem.common.routing.bundle.RouteBundleParams
import com.tangem.common.routing.bundle.bundle
import com.tangem.common.routing.entity.AddressBookOpenMode
import com.tangem.common.routing.entity.InitScreenLaunchMode
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.decompose.navigation.Route
@ -99,9 +100,19 @@ sealed class AppRoute(val path: String) : Route {
val userWalletId: UserWalletId,
) : AppRoute(path = "/details/security")
/**
* Support chat (Usedesk) screen.
*
* @property walletMetaInfo wallet meta info; its user wallet id is sent to Usedesk as the client email
* @property source source of the chat opening (Settings by default, Swap for FR-02). Drives both
* analytics and the Usedesk additional fields mapped by the component.
* @property prefilledMessage optional message sent to the chat on behalf of the user right after init
*/
@Serializable
data class Usedesk(
val walletMetaInfo: WalletMetaInfo,
val source: AnalyticsParam.ScreensSources = AnalyticsParam.ScreensSources.Settings,
val prefilledMessage: String? = null,
) : AppRoute(path = "/usedesk/${walletMetaInfo.userWalletId}")
@Serializable
@ -174,8 +185,15 @@ sealed class AppRoute(val path: String) : Route {
@Serializable
data class AddressBook(
val predefinedAddress: String? = null,
) : AppRoute(path = "/address_book/predefinedAddress/$predefinedAddress")
val addressBookOpenMode: AddressBookOpenMode = AddressBookOpenMode.Default,
) : AppRoute(
path = when (addressBookOpenMode) {
is AddressBookOpenMode.WithContactCreation ->
"/address_book/${addressBookOpenMode.address}-${addressBookOpenMode.networkId}"
is AddressBookOpenMode.ContactSelection -> "/address_book/select/${addressBookOpenMode.networkId}"
AddressBookOpenMode.Default -> "/address_book"
},
)
@Serializable
data class QrScanning(val source: Source) : AppRoute(path = "/$source/qr_scanning${source.path}") {
@ -187,6 +205,7 @@ sealed class AppRoute(val path: String) : Route {
is Send -> "/$networkName"
WalletConnect -> ""
MainScreen -> ""
AddressBook -> ""
}
data class Send(val networkName: String) : Source()
@ -194,6 +213,8 @@ sealed class AppRoute(val path: String) : Route {
data object WalletConnect : Source()
data object MainScreen : Source()
data object AddressBook : Source()
}
}
@ -324,11 +345,6 @@ sealed class AppRoute(val path: String) : Route {
val userWalletId: UserWalletId,
) : AppRoute(path = "/sell_crypto/${userWalletId.stringValue}")
@Serializable
data class SwapCrypto(
val userWalletId: UserWalletId,
) : AppRoute(path = "/swap_crypto/${userWalletId.stringValue}")
/**
* Onboarding V2
* @property scanResponse scan response, determines onboarding route by the product type
@ -508,6 +524,24 @@ sealed class AppRoute(val path: String) : Route {
@Serializable
data class Kyc(val userWalletId: UserWalletId) : AppRoute(path = "/kyc")
@Serializable
data class VirtualAccountOnboarding(
val mode: Mode,
) : AppRoute(path = "/virtual_account_onboarding/$mode") {
@Serializable
sealed class Mode {
@Serializable
data class Deeplink(val userWalletId: UserWalletId, val deeplink: String) : Mode()
@Serializable
data class FromMain(val userWalletId: UserWalletId) : Mode()
@Serializable
data class FromDetailsScreen(val userWalletId: UserWalletId) : Mode()
}
}
@Serializable
data class Survey(val token: String, val displayId: String? = null) : AppRoute(path = "/survey")

View file

@ -68,6 +68,10 @@ sealed class DeepLinkRoute {
override val host: String = "onboard-visa"
}
data object OnboardVirtualAccounts : DeepLinkRoute() {
override val host: String = "onboard-virtual-account"
}
data object PayApp : DeepLinkRoute() {
override val host: String = "tangem.com"
}

View file

@ -0,0 +1,26 @@
package com.tangem.common.routing.entity
import kotlinx.serialization.Serializable
/** How the address book is opened — part of the navigation contract, carried by [com.tangem.common.routing.AppRoute.AddressBook]. */
@Serializable
sealed interface AddressBookOpenMode {
@Serializable
data object Default : AddressBookOpenMode
@Serializable
data class WithContactCreation(
val address: String,
val networkId: String,
) : AddressBookOpenMode
/**
* Opened from the Send flow to pick a recipient. The list is filtered by [networkId] (the current send network),
* and the chosen contact's address is delivered back via `ContactSelectionTrigger` rather than navigation.
*/
@Serializable
data class ContactSelection(
val networkId: String,
) : AddressBookOpenMode
}

View file

@ -9,30 +9,36 @@ android {
}
dependencies {
implementation(projects.core.datasource)
implementation(projects.core.utils)
implementation(projects.data.common)
implementation(projects.data.staking)
implementation(projects.domain.legacy)
implementation(projects.domain.models)
implementation(projects.domain.card)
implementation(projects.domain.staking.models)
implementation(projects.domain.tokens.models)
implementation(projects.domain.txhistory.models)
implementation(projects.domain.wallets)
implementation(projects.domain.wallets.models)
implementation(projects.libs.blockchainSdk)
implementation(deps.androidx.datastore)
// region Other libraries
implementation(deps.jodatime)
implementation(deps.test.coroutine)
// endregion
implementation(tangemDeps.blockchain)
implementation(tangemDeps.card.core)
// region Tangem SDK
api(tangemDeps.blockchain)
api(tangemDeps.card.core)
// endregion
implementation(deps.test.junit5)
implementation(deps.test.truth)
// region Core
api(projects.core.datasource)
implementation(projects.core.utils)
// endregion
// region Data
implementation(projects.data.common)
// endregion
// region Domain
api(projects.domain.card)
api(projects.domain.models)
implementation(projects.domain.wallets)
// endregion
// region Domain models
api(projects.domain.staking.models)
// endregion
// region Libs
api(projects.libs.blockchainSdk)
// endregion
}

View file

@ -22,6 +22,7 @@ class MockCryptoCurrencyFactory(private val userWallet: UserWallet.Cold = defaul
private val factory = CryptoCurrencyFactory(excludedBlockchains = ExcludedBlockchains())
val bitcoin by lazy { createCoin(Blockchain.Bitcoin) }
val cardano by lazy { createCoin(blockchain = Blockchain.Cardano) }
val chia by lazy { createCoin(Blockchain.Chia) }
val ethereum by lazy { createCoin(Blockchain.Ethereum) }

View file

@ -9,19 +9,30 @@ android {
}
dependencies {
/** Project - Core */
implementation(projects.core.ui)
implementation(projects.core.utils)
// region Kotlin
api(deps.kotlin.coroutines)
api(deps.kotlin.immutable.collections)
// endregion
/** Compose */
implementation(tangemDeps.vico.core)
implementation(tangemDeps.vico.compose)
implementation(tangemDeps.vico.compose.m3)
implementation(deps.lifecycle.compose)
implementation(deps.compose.foundation)
// region Compose
api(deps.compose.foundation)
implementation(deps.compose.material3)
implementation(deps.compose.ui.tooling)
implementation(deps.compose.ui.utils)
implementation(deps.kotlin.immutable.collections)
// endregion
// region Other libraries
implementation(deps.androidx.annotation)
implementation(deps.jodatime)
// endregion
// region Vico
implementation(tangemDeps.vico.core)
implementation(tangemDeps.vico.compose)
// endregion
// region Project - Core
implementation(projects.core.ui)
implementation(projects.core.utils)
// endregion
}

View file

@ -1,8 +1,6 @@
plugins {
alias(deps.plugins.android.library)
alias(deps.plugins.kotlin.android)
alias(deps.plugins.kotlin.kapt)
alias(deps.plugins.hilt.android)
id("configuration")
}
@ -11,41 +9,59 @@ android {
}
dependencies {
/** Project - Core */
implementation(projects.core.ui)
implementation(projects.core.utils)
implementation(projects.core.navigation)
implementation(projects.core.analytics)
/** Project - Common */
implementation(projects.common.uiCharts)
implementation(projects.common.ui)
implementation(projects.common.routing)
// region Kotlin
api(deps.kotlin.coroutines)
api(deps.kotlin.immutable.collections)
// endregion
/** Project - Domain */
implementation(projects.domain.models)
implementation(projects.domain.tokens)
implementation(projects.domain.tokens.models)
implementation(projects.domain.staking)
implementation(projects.domain.staking.models)
implementation(projects.domain.onramp.models)
implementation(projects.domain.offramp)
implementation(projects.domain.demo)
implementation(projects.domain.card)
implementation(projects.domain.feedback)
implementation(deps.lifecycle.compose)
implementation(deps.compose.foundation)
implementation(deps.compose.material3)
// region Compose
api(deps.compose.foundation)
implementation(deps.compose.ui.tooling)
implementation(deps.compose.material3)
implementation(deps.compose.ui.utils)
implementation(deps.kotlin.immutable.collections)
// endregion
/** DI */
// region Other libraries
implementation(deps.androidx.annotation)
implementation(deps.arrow.core)
implementation(deps.haze)
implementation(deps.hilt.android)
kapt(deps.hilt.kapt)
// endregion
/** Test */
testImplementation(projects.test.core)
// region Project - Core
api(projects.core.analytics)
api(projects.core.decompose)
api(projects.core.navigation)
api(projects.core.ui)
api(projects.core.utils)
implementation(projects.core.analytics.models)
// endregion
// region Project - Common
api(projects.common.routing)
api(projects.common.uiCharts)
implementation(projects.common.ui)
// endregion
// region Project - Domain
api(projects.domain.appCurrency.models)
api(projects.domain.card)
api(projects.domain.demo)
api(projects.domain.feedback)
api(projects.domain.models)
api(projects.domain.offramp)
api(projects.domain.tokens)
implementation(projects.domain.onramp.models)
implementation(projects.domain.staking)
implementation(projects.domain.tokens.models)
// endregion
// region Test
testImplementation(deps.test.coroutine)
testImplementation(deps.test.junit5)
testImplementation(deps.test.mockk)
testImplementation(deps.test.truth)
testImplementation(projects.common.test)
// endregion
}

View file

@ -8,47 +8,70 @@ android {
namespace = "com.tangem.common.ui"
}
dependencies {
api(projects.common)
/** Compose */
implementation(deps.compose.material3)
implementation(deps.compose.foundation)
implementation(deps.compose.ui)
implementation(deps.compose.ui.tooling)
implementation(deps.compose.navigation)
implementation(deps.compose.navigation.hilt)
// region Kotlin
api(deps.kotlin.immutable.collections)
implementation(deps.kotlin.coroutines)
// endregion
// region Compose
api(deps.compose.foundation)
api(deps.compose.material3)
implementation(deps.compose.coil)
implementation(deps.compose.constraintLayout)
implementation(deps.compose.ui)
implementation(deps.compose.ui.tooling)
// endregion
/** Deps */
implementation(deps.kotlin.immutable.collections)
// region Other libraries
api(deps.arrow.core)
implementation(deps.hilt.android)
implementation(deps.androidx.annotation)
implementation(deps.androidx.core.ktx)
implementation(deps.haze)
// endregion
/** Project - Common */
implementation(projects.core.ui)
implementation(projects.core.utils)
implementation(projects.core.res)
implementation(projects.libs.crypto)
implementation(projects.libs.blockchainSdk)
/** Project - Domain */
implementation(projects.domain.appCurrency.models)
implementation(projects.domain.models)
implementation(projects.domain.legacy)
implementation(projects.domain.card)
implementation(projects.domain.staking.models)
implementation(projects.domain.staking)
implementation(projects.domain.account)
implementation(projects.domain.tokens.models)
implementation(projects.domain.transaction.models)
implementation(projects.domain.wallets.models)
implementation(projects.domain.onramp.models)
implementation(projects.domain.common)
implementation(tangemDeps.card.core)
implementation(tangemDeps.blockchain) {
// region Tangem SDK
api(tangemDeps.blockchain) {
exclude(module = "joda-time")
}
// endregion
/** Tests */
// region Project - Core
api(projects.core.analytics)
api(projects.core.ui)
api(projects.core.utils)
implementation(projects.core.analytics.models)
implementation(projects.core.res)
// endregion
// region Project - Common
// :common is intentionally re-exported (api): common:ui is a ubiquitous UI dependency and many
// feature modules rely on TangemBlogUrlBuilder / common types through it. Demoting to implementation
// cascades across the feature graph, so keep it api despite DAGP's advice (suppressed below).
api(projects.common)
// endregion
// region Project - Domain
api(projects.domain.account)
api(projects.domain.appCurrency.models)
api(projects.domain.common)
api(projects.domain.core)
api(projects.domain.models)
api(projects.domain.onramp.models)
api(projects.domain.staking)
api(projects.domain.tokens.models)
api(projects.domain.transaction.models)
implementation(projects.domain.card)
implementation(projects.domain.staking.models)
// endregion
// region Project - Libs
implementation(projects.libs.blockchainSdk)
implementation(projects.libs.crypto)
// endregion
// region Tests
testImplementation(projects.test.core)
// endregion
}

View file

@ -1,8 +1,10 @@
package com.tangem.common.ui.account
import androidx.compose.runtime.Immutable
import com.tangem.domain.models.account.CryptoPortfolioIcon.Color
import com.tangem.domain.models.account.CryptoPortfolioIcon.Icon
@Immutable
sealed class AccountIconUM {
data class CryptoPortfolio(val value: Icon, val color: Color) : AccountIconUM()

View file

@ -244,6 +244,11 @@ sealed class NotificationUM(val config: NotificationConfig) {
subtitle = resourceReference(id = R.string.send_notification_fee_too_high_text, wrappedList(value)),
)
data object HighNetworkFee : Warning(
title = resourceReference(id = R.string.high_fee_warning_title),
subtitle = resourceReference(id = R.string.high_fee_warning_description),
)
data class NetworkFeeUnreachable(val onRefresh: () -> Unit) : Warning(
title = resourceReference(R.string.send_fee_unreachable_error_title),
subtitle = resourceReference(R.string.send_fee_unreachable_error_text),