Initial commit: Pezkuwi Wallet Android

Security hardened release:
- Code obfuscation enabled (minifyEnabled=true, shrinkResources=true)
- Sensitive files excluded (google-services.json, keystores)
- Branch.io key moved to BuildConfig placeholder
- Updated dependencies: OkHttp 4.12.0, Gson 2.10.1, BouncyCastle 1.77
- Comprehensive ProGuard rules for crypto wallet
- Navigation 2.7.7, Lifecycle 2.7.0, ConstraintLayout 2.1.4
This commit is contained in:
2026-02-12 05:19:41 +03:00
commit a294aa1a6b
7687 changed files with 441811 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/build
+19
View File
@@ -0,0 +1,19 @@
android {
namespace 'io.novafoundation.nova.feature_ledger_core'
}
dependencies {
implementation coroutinesDep
implementation project(':runtime')
implementation project(":common")
implementation substrateSdkDep
implementation daggerDep
ksp daggerCompiler
implementation androidDep
api project(':core-api')
}
+21
View File
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
@@ -0,0 +1,35 @@
package io.novafoundation.nova.feature_ledger_core
import dagger.Component
import io.novafoundation.nova.common.di.CommonApi
import io.novafoundation.nova.common.di.scope.FeatureScope
import io.novafoundation.nova.feature_ledger_core.di.LedgerCoreApi
import io.novafoundation.nova.runtime.di.RuntimeApi
@Component(
dependencies = [
LedgerCoreDependencies::class,
],
modules = [
LedgerFeatureModule::class,
]
)
@FeatureScope
interface LedgerCoreComponent : LedgerCoreApi {
@Component.Factory
interface Factory {
fun create(
deps: LedgerCoreDependencies,
): LedgerCoreComponent
}
@Component(
dependencies = [
CommonApi::class,
RuntimeApi::class,
]
)
interface LedgerCoreDependenciesComponent : LedgerCoreDependencies
}
@@ -0,0 +1,11 @@
package io.novafoundation.nova.feature_ledger_core
import io.novafoundation.nova.runtime.extrinsic.metadata.MetadataShortenerService
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
interface LedgerCoreDependencies {
val chainRegistry: ChainRegistry
val metadataShortenerService: MetadataShortenerService
}
@@ -0,0 +1,23 @@
package io.novafoundation.nova.feature_ledger_core
import io.novafoundation.nova.common.di.FeatureApiHolder
import io.novafoundation.nova.common.di.FeatureContainer
import io.novafoundation.nova.common.di.scope.ApplicationScope
import io.novafoundation.nova.runtime.di.RuntimeApi
import javax.inject.Inject
@ApplicationScope
class LedgerCoreHolder @Inject constructor(
featureContainer: FeatureContainer,
) : FeatureApiHolder(featureContainer) {
override fun initializeDependencies(): Any {
val accountFeatureDependencies = DaggerLedgerCoreComponent_LedgerCoreDependenciesComponent.builder()
.commonApi(commonApi())
.runtimeApi(getFeature(RuntimeApi::class.java))
.build()
return DaggerLedgerCoreComponent.factory()
.create(accountFeatureDependencies)
}
}
@@ -0,0 +1,22 @@
package io.novafoundation.nova.feature_ledger_core
import dagger.Module
import dagger.Provides
import io.novafoundation.nova.common.di.scope.FeatureScope
import io.novafoundation.nova.feature_ledger_core.domain.LedgerMigrationTracker
import io.novafoundation.nova.feature_ledger_core.domain.RealLedgerMigrationTracker
import io.novafoundation.nova.runtime.extrinsic.metadata.MetadataShortenerService
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
@Module
class LedgerFeatureModule {
@Provides
@FeatureScope
fun provideLedgerMigrationTracker(
metadataShortenerService: MetadataShortenerService,
chainRegistry: ChainRegistry
): LedgerMigrationTracker {
return RealLedgerMigrationTracker(metadataShortenerService, chainRegistry)
}
}
@@ -0,0 +1,8 @@
package io.novafoundation.nova.feature_ledger_core.di
import io.novafoundation.nova.feature_ledger_core.domain.LedgerMigrationTracker
interface LedgerCoreApi {
val ledgerMigrationTracker: LedgerMigrationTracker
}
@@ -0,0 +1,66 @@
package io.novafoundation.nova.feature_ledger_core.domain
import io.novafoundation.nova.common.utils.mapNotNullToSet
import io.novafoundation.nova.runtime.ext.isGenericLedgerAppSupported
import io.novafoundation.nova.runtime.extrinsic.metadata.MetadataShortenerService
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
import io.novafoundation.nova.runtime.multiNetwork.findChainIds
import io.novafoundation.nova.runtime.multiNetwork.findChains
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
interface LedgerMigrationTracker {
suspend fun shouldUseMigrationApp(chainId: ChainId): Boolean
suspend fun supportedChainsByGenericApp(): List<Chain>
suspend fun anyChainSupportsMigrationApp(): Boolean
fun supportedChainIdsByGenericAppFlow(): Flow<Set<ChainId>>
suspend fun supportedChainIdsByGenericApp(): Set<ChainId>
}
internal class RealLedgerMigrationTracker(
private val metadataShortenerService: MetadataShortenerService,
private val chainRegistry: ChainRegistry
) : LedgerMigrationTracker {
override suspend fun shouldUseMigrationApp(chainId: ChainId): Boolean {
val supportedFromRuntime = metadataShortenerService.isCheckMetadataHashAvailable(chainId)
// While automatically detect generic app availability from runtime, it is also usefully to be able to disable this for a specific chain
// via a feature flag
val supportedFromLedger = chainRegistry.getChain(chainId).additional.isGenericLedgerAppSupported()
return supportedFromRuntime && supportedFromLedger
}
override suspend fun supportedChainsByGenericApp(): List<Chain> {
return chainRegistry.findChains {
it.additional.isGenericLedgerAppSupported()
}
}
override suspend fun supportedChainIdsByGenericApp(): Set<ChainId> {
return chainRegistry.findChainIds {
it.additional.isGenericLedgerAppSupported()
}
}
override suspend fun anyChainSupportsMigrationApp(): Boolean {
return supportedChainsByGenericApp().isNotEmpty()
}
override fun supportedChainIdsByGenericAppFlow(): Flow<Set<ChainId>> {
return chainRegistry.currentChains.map { chains ->
chains.mapNotNullToSet { chain ->
chain.id.takeIf { chain.additional.isGenericLedgerAppSupported() }
}
}.distinctUntilChanged()
}
}