Updated on 2026-08-14
This commit is contained in:
parent
b9eb3a6ab4
commit
b63f8be2ce
5 changed files with 384 additions and 22 deletions
74
.claude/docs/running-the-app.md
Normal file
74
.claude/docs/running-the-app.md
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Running the App on a Device (ADB)
|
||||||
|
|
||||||
|
Practical notes for launching the app on a connected device for manual/on-device testing.
|
||||||
|
|
||||||
|
## Package & main activity
|
||||||
|
|
||||||
|
| | Value |
|
||||||
|
|---|---|
|
||||||
|
| Debug package (Google flavor) | `com.tangem.wallet.debug` |
|
||||||
|
| Main launcher activity | `com.tangem.tap.MainActivity` |
|
||||||
|
| Application class | `com.tangem.tap.TangemHiltApplication` |
|
||||||
|
|
||||||
|
## Launch the main screen (correct way)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
adb shell am force-stop com.tangem.wallet.debug
|
||||||
|
adb shell am start -n com.tangem.wallet.debug/com.tangem.tap.MainActivity
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify the real screen is in the foreground:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
adb shell dumpsys activity activities | grep -i topResumedActivity | grep -i tangem
|
||||||
|
# expect: topResumedActivity=ActivityRecord{... com.tangem.wallet.debug/com.tangem.tap.MainActivity ...}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pitfall: do NOT launch via `monkey`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ❌ ambiguous — may open the wrong screen
|
||||||
|
adb shell monkey -p com.tangem.wallet.debug -c android.intent.category.LAUNCHER 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Debug builds bundle **LeakCanary**, which registers its own `LAUNCHER` activity ("Leaks").
|
||||||
|
The package therefore has **multiple** MAIN/LAUNCHER activities, so `monkey` (and
|
||||||
|
`cmd package resolve-activity`) resolves to Android's `ResolverActivity` / the wrong entry
|
||||||
|
and can open **LeakCanary instead of the app**. Always launch `MainActivity` explicitly with
|
||||||
|
`am start -n`.
|
||||||
|
|
||||||
|
List the launcher activities to confirm:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
adb shell cmd package query-activities \
|
||||||
|
-a android.intent.action.MAIN -c android.intent.category.LAUNCHER \
|
||||||
|
| grep -iE "name=" | grep -i tangem
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cold start vs warm start (matters for `Application.init()`)
|
||||||
|
|
||||||
|
`TangemApplication.init()` (Hilt setup, and one-time bootstrap such as backend-auth device
|
||||||
|
key generation + registration) runs **once per process**, on `Application.onCreate()`.
|
||||||
|
|
||||||
|
- **Warm start** (process already alive / resumed from background): `init()` does **not** re-run.
|
||||||
|
You will NOT see the startup log banner `APP STARTED` or any one-time bootstrap logs.
|
||||||
|
- **Cold start** (after `am force-stop`, or first launch): `init()` runs → look for the
|
||||||
|
`APP STARTED` banner in logcat (tag `TangemApplication`).
|
||||||
|
|
||||||
|
To reliably observe anything that happens in `init()`, always `force-stop` first, then launch.
|
||||||
|
|
||||||
|
> Note: `init()` runs on process start regardless of *which* activity brought the process up
|
||||||
|
> (even LeakCanary's). So process-scoped logs are still valid on a wrong-activity launch — but
|
||||||
|
> for observing actual app UI/flows, launch `MainActivity` explicitly.
|
||||||
|
|
||||||
|
## Build & install (Google debug)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew :app:assembleGoogleDebug
|
||||||
|
adb install -r app/build/outputs/apk/google/debug/app-google-debug.apk
|
||||||
|
```
|
||||||
|
|
||||||
|
## Product flavors
|
||||||
|
|
||||||
|
Flavors: `google`, `huawei` (dimension `services`); default dev flavor is `google`.
|
||||||
|
Build types: `debug`, `mocked`, `internal`, `external`, `release`.
|
||||||
|
|
@ -5,15 +5,10 @@
|
||||||
"command": "npx",
|
"command": "npx",
|
||||||
"args": ["-y", "firebase-tools@latest", "mcp"]
|
"args": ["-y", "firebase-tools@latest", "mcp"]
|
||||||
},
|
},
|
||||||
"atlassian": {
|
|
||||||
"type": "stdio",
|
|
||||||
"command": "npx",
|
|
||||||
"args": ["-y", "mcp-remote", "https://mcp.atlassian.com/v1/sse"]
|
|
||||||
},
|
|
||||||
"notion": {
|
"notion": {
|
||||||
"type": "stdio",
|
"type": "stdio",
|
||||||
"command": "npx",
|
"command": "npx",
|
||||||
"args": ["-y", "mcp-remote", "https://mcp.notion.com/mcp"]
|
"args": ["-y", "mcp-remote", "https://mcp.notion.com/mcp"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
289
build.gradle.kts
289
build.gradle.kts
|
|
@ -12,6 +12,8 @@ plugins {
|
||||||
alias(deps.plugins.room) apply false
|
alias(deps.plugins.room) apply false
|
||||||
alias(deps.plugins.kotlin.compose.compiler) apply false
|
alias(deps.plugins.kotlin.compose.compiler) apply false
|
||||||
alias(deps.plugins.ksp) apply false
|
alias(deps.plugins.ksp) apply false
|
||||||
|
// Applied (not `apply false`) so the root project gets the aggregate `buildHealth` task.
|
||||||
|
alias(deps.plugins.dependency.analysis)
|
||||||
}
|
}
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
|
|
@ -21,6 +23,288 @@ buildscript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dependency Analysis (DAGP) global configuration.
|
||||||
|
dependencyAnalysis {
|
||||||
|
structure {
|
||||||
|
// Treat co-versioned artifact splits as a single logical dependency, so the plugin doesn't
|
||||||
|
// advise "declare the transitive directly" when you depend on one part and use a sibling.
|
||||||
|
// e.g. `serialization-json` always brings `serialization-core` (@Serializable lives there).
|
||||||
|
bundle("kotlinx-serialization") {
|
||||||
|
includeDependency("org.jetbrains.kotlinx:kotlinx-serialization-core")
|
||||||
|
includeDependency("org.jetbrains.kotlinx:kotlinx-serialization-json")
|
||||||
|
}
|
||||||
|
// Hilt/Dagger is split across many artifacts (hilt-android pulls dagger, hilt-core,
|
||||||
|
// javax.inject; hilt-compiler pulls dagger-compiler). Declaring hilt-android + hilt-compiler
|
||||||
|
// is the single entry point — don't advise expanding each transitive separately.
|
||||||
|
bundle("hilt") {
|
||||||
|
primary("com.google.dagger:hilt-android")
|
||||||
|
includeGroup("com.google.dagger")
|
||||||
|
includeDependency("javax.inject:javax.inject")
|
||||||
|
}
|
||||||
|
// `junit-jupiter` is an aggregator over `-api`/`-params`/`-engine`. Tests import the `-api`
|
||||||
|
// package; declaring the `junit-jupiter` aggregator (deps.test.junit5) is the project standard.
|
||||||
|
bundle("junit5") {
|
||||||
|
primary("org.junit.jupiter:junit-jupiter")
|
||||||
|
includeGroup("org.junit.jupiter")
|
||||||
|
}
|
||||||
|
// MockK's DSL functions (every/coEvery/verify) live in `mockk-dsl`, pulled by `mockk`.
|
||||||
|
// Declaring `mockk` (deps.test.mockk) is enough.
|
||||||
|
bundle("mockk") {
|
||||||
|
primary("io.mockk:mockk")
|
||||||
|
includeGroup("io.mockk")
|
||||||
|
}
|
||||||
|
// DataStore is split into datastore-core / datastore-preferences-core / datastore-preferences,
|
||||||
|
// all co-versioned. Declaring the one you use covers the sibling packages.
|
||||||
|
bundle("androidx-datastore") {
|
||||||
|
includeGroup("androidx.datastore")
|
||||||
|
}
|
||||||
|
// web3j is split across core/abi/crypto/tuples (+ its rxjava reactive layer), all co-versioned.
|
||||||
|
// The generated Solidity contract wrappers expose these in their public API; declaring
|
||||||
|
// web3j-core (the entry point) covers the family. rxjava is web3j-only in this repo.
|
||||||
|
bundle("web3j") {
|
||||||
|
primary("org.web3j:core")
|
||||||
|
includeGroup("org.web3j")
|
||||||
|
includeDependency("io.reactivex.rxjava2:rxjava")
|
||||||
|
}
|
||||||
|
// Decompose's public API (ComponentContext etc.) extends Essenty owner interfaces, so the
|
||||||
|
// essenty artifacts are part of decompose's surface. Declaring `decompose` covers them.
|
||||||
|
bundle("decompose") {
|
||||||
|
primary("com.arkivanov.decompose:decompose")
|
||||||
|
includeGroup("com.arkivanov.decompose")
|
||||||
|
includeGroup("com.arkivanov.essenty")
|
||||||
|
}
|
||||||
|
// Jetpack Compose is split across ~15 co-versioned artifacts (ui, ui-graphics, ui-text,
|
||||||
|
// ui-unit, foundation, foundation-layout, animation, animation-core, runtime, runtime-saveable,
|
||||||
|
// material-ripple, …). Treat the whole `androidx.compose.*` family as one logical dependency.
|
||||||
|
bundle("compose") {
|
||||||
|
include("^androidx\\.compose\\..*")
|
||||||
|
}
|
||||||
|
// Co-versioned families split across many artifacts — declaring one covers the siblings.
|
||||||
|
bundle("androidx-lifecycle") {
|
||||||
|
primary("androidx.lifecycle:lifecycle-runtime-ktx")
|
||||||
|
includeGroup("androidx.lifecycle")
|
||||||
|
}
|
||||||
|
bundle("androidx-appcompat") {
|
||||||
|
primary("androidx.appcompat:appcompat")
|
||||||
|
includeGroup("androidx.appcompat")
|
||||||
|
}
|
||||||
|
bundle("androidx-paging") {
|
||||||
|
includeGroup("androidx.paging")
|
||||||
|
}
|
||||||
|
bundle("coil") {
|
||||||
|
includeGroup("io.coil-kt")
|
||||||
|
}
|
||||||
|
// Room is split into runtime/ktx/common/compiler/paging (+ its androidx.sqlite runtime).
|
||||||
|
// Declaring room-runtime covers the siblings.
|
||||||
|
bundle("room") {
|
||||||
|
primary("androidx.room:room-runtime")
|
||||||
|
includeGroup("androidx.room")
|
||||||
|
includeGroup("androidx.sqlite")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
issues {
|
||||||
|
all {
|
||||||
|
// hilt-android / hilt-core get flagged as `api`: Kotlin `internal` @Inject classes (and
|
||||||
|
// public @Inject impls) compile to public bytecode carrying RUNTIME javax.inject annotations,
|
||||||
|
// so DAGP sees javax.inject in the ABI. The Hilt runtime is never genuinely public API — keep
|
||||||
|
// it `implementation` repo-wide.
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(
|
||||||
|
"com.google.dagger:hilt-android",
|
||||||
|
"com.google.dagger:hilt-core",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// dagger-compiler is always pulled by hilt-compiler (declared via kapt(deps.hilt.kapt));
|
||||||
|
// no need to declare the annotation processor separately.
|
||||||
|
// :test:core is the documented single entry point for the unit-test stack — it re-exports
|
||||||
|
// junit5/mockk/truth/turbine/coroutines-test as `api`. Because those re-exports are excluded
|
||||||
|
// from the "declare directly" advice above, DAGP sees :test:core itself as unused. It isn't —
|
||||||
|
// keep declaring testImplementation(projects.test.core) and silence the false positive.
|
||||||
|
onUnusedDependencies {
|
||||||
|
exclude(":test:core")
|
||||||
|
}
|
||||||
|
onUsedTransitiveDependencies {
|
||||||
|
exclude("com.google.dagger:dagger-compiler")
|
||||||
|
// jsr305 is a ubiquitous CLASS-retention nullability-annotation transitive (pulled in
|
||||||
|
// by many libs); consumers tolerate its absence, it's never declared directly.
|
||||||
|
exclude("com.google.code.findbugs:jsr305")
|
||||||
|
// :test:core re-exports the unit-test stack as `api` and is the documented single
|
||||||
|
// entry point (testImplementation(projects.test.core)). Don't advise declaring its
|
||||||
|
// re-exports directly in every test module.
|
||||||
|
exclude(
|
||||||
|
"app.cash.turbine:turbine",
|
||||||
|
"com.google.truth:truth",
|
||||||
|
"io.mockk:mockk",
|
||||||
|
"org.jetbrains.kotlinx:kotlinx-coroutines-test",
|
||||||
|
"org.junit.jupiter:junit-jupiter",
|
||||||
|
)
|
||||||
|
// wire-runtime (protobuf) and jakarta.inject-api are deep transitives of the Visa /
|
||||||
|
// WalletConnect (reown) SDKs. A few generated/SDK-facing types reference them, but they're
|
||||||
|
// never declared directly — they always arrive with their owning SDK. Don't advise
|
||||||
|
// declaring them per-module.
|
||||||
|
exclude(
|
||||||
|
"com.squareup.wire:wire-runtime",
|
||||||
|
"jakarta.inject:jakarta.inject-api",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// In :libs:auth these are injected only into `internal` classes (DI modules / Default* impls).
|
||||||
|
// DAGP advises `api` because Kotlin `internal` compiles to public bytecode (and Hilt's
|
||||||
|
// generated `_Factory` classes expose the constructor types publicly) — a false positive, not
|
||||||
|
// a real ABI leak. Keep them `implementation`. Scoped to this module so genuine api advice in
|
||||||
|
// other modules still surfaces.
|
||||||
|
project(":libs:auth") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(
|
||||||
|
"com.squareup.moshi:moshi",
|
||||||
|
":core:config-toggles",
|
||||||
|
":core:datasource",
|
||||||
|
":core:utils",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Same Kotlin-`internal`-compiles-to-public false positive: these are used only inside
|
||||||
|
// `internal` classes / DI modules / method bodies (verified), not in the public ABI.
|
||||||
|
project(":libs:blockchain-sdk") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(
|
||||||
|
"androidx.datastore:datastore-preferences",
|
||||||
|
"com.squareup.moshi:moshi",
|
||||||
|
":core:analytics",
|
||||||
|
":core:utils",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// config-toggles is used only inside the `internal` DefaultCardSdkFeatureToggles (the public
|
||||||
|
// CardSdkFeatureToggles interface is empty) — internal→public false positive.
|
||||||
|
project(":libs:tangem-sdk-api") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":core:config-toggles")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// web3j leaks into the ABI only via incidentally-public generated contract wrappers
|
||||||
|
// (ERC20/TangemPaymentAccount/…), not the module's intended public API (VisaContractInfoProvider
|
||||||
|
// / VisaContractInfo) — keep it `implementation` (see PR review), so silence the `api` advice.
|
||||||
|
project(":libs:visa") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude("org.web3j:core")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// datasource/utils are used only inside the `internal` DI module + Amplitude impl (the public
|
||||||
|
// ABTestsManager interface doesn't expose them) — internal→public false positive.
|
||||||
|
project(":core:ab-tests") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":core:datasource", ":core:utils")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// datasource is used only inside `internal` DI modules + LocalTogglesStorage (the public
|
||||||
|
// FeatureTogglesManager API doesn't expose it) — internal→public false positive.
|
||||||
|
project(":core:config-toggles") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":core:datasource")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// moshi-polymorphic-adapter is used only in @Provides bodies / as annotation args, never in a
|
||||||
|
// public signature — internal→public false positive, keep it `implementation`.
|
||||||
|
project(":core:datasource") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude("dev.onenowy.moshipolymorphicadapter:moshi-polymorphic-adapter")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// material is consumed only via resources (styles.xml inherits MaterialComponents themes), which
|
||||||
|
// DAGP can't see — it suggests runtimeOnly, but resource linking needs it on the compile
|
||||||
|
// classpath. Keep it `implementation`.
|
||||||
|
project(":core:ui") {
|
||||||
|
onRuntimeOnly {
|
||||||
|
exclude("com.google.android.material:material")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// core:error exposes UniversalError, a supertype of VisaActivationError that card consumes via
|
||||||
|
// domain:visa:models. The compiler needs the supertype on the classpath, but DAGP sees no direct
|
||||||
|
// reference and flags it unused — false positive, keep it `implementation`.
|
||||||
|
project(":domain:card") {
|
||||||
|
onUnusedDependencies {
|
||||||
|
exclude(":core:error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// core:utils is deliberately re-exported as api from the ubiquitous domain:models module so the
|
||||||
|
// many consumers that use TangemLogger / utils through it keep compiling. Demoting it to
|
||||||
|
// implementation would cascade across the whole repo, so silence the incorrect-config advice.
|
||||||
|
project(":domain:models") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":core:utils")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// :domain:models is kept as api because domain:markets:models exposes CryptoCurrency.RawID (a
|
||||||
|
// domain:models type) in its public data classes (TokenMarket/RawMarketToken/TokenMarketParams).
|
||||||
|
// DAGP misses this nested-type ABI leak and advises implementation; that advice is a false negative.
|
||||||
|
project(":domain:markets:models") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":domain:models")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// :domain:core is kept as api in :domain:legacy and :domain:express because their public APIs
|
||||||
|
// (RampStateManager, ExpressServiceFetcher#getInitializationStatus) return Flow<Lce<...>> where Lce
|
||||||
|
// is a domain:core type. DAGP doesn't trace the generic type argument into the ABI and advises
|
||||||
|
// implementation; that advice is a false negative.
|
||||||
|
project(":domain:legacy") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":domain:core")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project(":domain:express") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":domain:core")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// :domain:core kept as api in :domain:onramp — public use cases (GetOnrampCurrenciesUseCase etc.)
|
||||||
|
// return EitherFlow<...> (a domain:core alias). DAGP doesn't trace the alias/generic into the ABI.
|
||||||
|
project(":domain:onramp") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":domain:core")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// arrow-core kept as api in :domain:onboarding — WasTwinsOnboardingShownUseCase#invoke returns
|
||||||
|
// Flow<Either<...>> (arrow.core.Either in the public ABI). DAGP advises implementation here (false
|
||||||
|
// negative on the generic type argument).
|
||||||
|
project(":domain:onboarding") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude("io.arrow-kt:arrow-core")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// :domain:core kept as api in :domain:wallets — GetUserWalletUseCase#invokeFlow returns
|
||||||
|
// EitherFlow<...> (a domain:core alias). DAGP false-negative on the alias/generic.
|
||||||
|
project(":domain:wallets") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":domain:core")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// :domain:models kept as api in :domain:yield-supply:models — YieldMarketToken (public data
|
||||||
|
// class) exposes SerializedBigDecimal (a domain:models type) in public fields. DAGP misses it.
|
||||||
|
project(":domain:yield-supply:models") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":domain:models")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// :common is deliberately re-exported as api from common:ui (a ubiquitous UI dependency) so the
|
||||||
|
// many feature modules that use TangemBlogUrlBuilder / common types through it keep compiling.
|
||||||
|
// Demoting it to implementation would cascade across the feature graph.
|
||||||
|
project(":common:ui") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":common")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// libs:crypto is deliberately re-exported as api from the ubiquitous :common module so the many
|
||||||
|
// feature modules that use BlockchainUtils / crypto helpers through it keep compiling. Demoting
|
||||||
|
// it to implementation would cascade across the feature graph.
|
||||||
|
project(":common") {
|
||||||
|
onIncorrectConfiguration {
|
||||||
|
exclude(":libs:crypto")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val clean by tasks.registering {
|
val clean by tasks.registering {
|
||||||
delete(rootProject.buildDir)
|
delete(rootProject.buildDir)
|
||||||
}
|
}
|
||||||
|
|
@ -37,6 +321,11 @@ val unitTest by tasks.registering {
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
|
// Dependency Analysis (DAGP) registers `projectHealth`/`reason` on each module. In 3.x the
|
||||||
|
// root application no longer auto-applies to subprojects, so apply it here. Reusing the plugin
|
||||||
|
// already resolved by the root `plugins {}` block keeps it in the same classloader as AGP/Kotlin.
|
||||||
|
apply(plugin = "com.autonomousapps.dependency-analysis")
|
||||||
|
|
||||||
// App module
|
// App module
|
||||||
plugins.withId("com.android.application") {
|
plugins.withId("com.android.application") {
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
plugins {
|
plugins {
|
||||||
alias(deps.plugins.android.library)
|
alias(deps.plugins.android.library)
|
||||||
alias(deps.plugins.kotlin.android)
|
alias(deps.plugins.kotlin.android)
|
||||||
alias(deps.plugins.kotlin.kapt)
|
|
||||||
alias(deps.plugins.hilt.android)
|
|
||||||
id("configuration")
|
id("configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12,28 +10,35 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation(projects.core.utils)
|
// region Other libraries
|
||||||
api(projects.domain.models)
|
implementation(deps.hilt.android)
|
||||||
api(projects.domain.appCurrency.models)
|
// endregion
|
||||||
api(projects.domain.staking.models)
|
|
||||||
api(projects.libs.crypto)
|
|
||||||
|
|
||||||
// region Firebase libraries
|
// region Firebase libraries
|
||||||
implementation(platform(deps.firebase.bom))
|
implementation(platform(deps.firebase.bom))
|
||||||
implementation(deps.firebase.analytics)
|
implementation(deps.firebase.analytics)
|
||||||
implementation(deps.firebase.crashlytics)
|
implementation(deps.firebase.crashlytics)
|
||||||
implementation(deps.firebase.messaging)
|
implementation(deps.firebase.messaging)
|
||||||
// end
|
// endregion
|
||||||
|
|
||||||
|
// region Core modules
|
||||||
|
implementation(projects.core.utils)
|
||||||
|
// endregion
|
||||||
|
|
||||||
implementation(deps.arrow.core)
|
// region Domain
|
||||||
|
api(projects.domain.models)
|
||||||
|
// endregion
|
||||||
|
|
||||||
testImplementation(projects.test.core)
|
// region Libs
|
||||||
|
// libs:crypto is intentionally re-exported (api): :common is ubiquitous and many feature modules
|
||||||
|
// use BlockchainUtils / crypto helpers through it. Demoting to implementation cascades across the
|
||||||
|
// feature graph, so keep it api despite DAGP's advice (suppressed below).
|
||||||
|
api(projects.libs.crypto)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Tests
|
||||||
testImplementation(deps.test.junit5)
|
testImplementation(deps.test.junit5)
|
||||||
testImplementation(deps.test.truth)
|
testImplementation(deps.test.truth)
|
||||||
|
testImplementation(projects.test.core)
|
||||||
// region DI
|
// endregion
|
||||||
implementation(deps.hilt.android)
|
|
||||||
kapt(deps.hilt.kapt)
|
|
||||||
// end
|
|
||||||
}
|
}
|
||||||
|
|
@ -264,7 +264,6 @@ coil-gif = { module = "io.coil-kt:coil-gif", version.ref = "coil" }
|
||||||
coil-svg = { module = "io.coil-kt:coil-svg", version.ref = "coil" }
|
coil-svg = { module = "io.coil-kt:coil-svg", version.ref = "coil" }
|
||||||
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutine" }
|
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutine" }
|
||||||
kotlin-coroutines-jvm = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", version.ref = "coroutine" }
|
kotlin-coroutines-jvm = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", version.ref = "coroutine" }
|
||||||
kotlin-coroutines-rx2 = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-rx2", version.ref = "coroutine" }
|
|
||||||
kotlin-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutine" }
|
kotlin-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutine" }
|
||||||
kotlin-immutable-collections = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlin-immutable-collections" }
|
kotlin-immutable-collections = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlin-immutable-collections" }
|
||||||
desugar = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugarJdkLibs" }
|
desugar = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugarJdkLibs" }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue