mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-04-22 10:17:57 +00:00
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:
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"/>
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package io.novafoundation.nova.feature_proxy_impl.data.common
|
||||
|
||||
import io.novafoundation.nova.feature_proxy_api.data.common.DepositBaseAndFactor
|
||||
import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator
|
||||
import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
|
||||
import java.math.BigInteger
|
||||
|
||||
class RealProxyDepositCalculator(
|
||||
private val proxyConstantsRepository: ProxyConstantsRepository
|
||||
) : ProxyDepositCalculator {
|
||||
|
||||
override fun calculateProxyDepositForQuantity(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger {
|
||||
return if (proxiesCount == 0) {
|
||||
BigInteger.ZERO
|
||||
} else {
|
||||
baseAndFactor.baseAmount + baseAndFactor.factorAmount * proxiesCount.toBigInteger()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun calculateProxyDepositForQuantity(chainId: ChainId, proxiesCount: Int): BigInteger {
|
||||
val depositAndFactor = proxyConstantsRepository.getDepositConstants(chainId)
|
||||
|
||||
return calculateProxyDepositForQuantity(depositAndFactor, proxiesCount)
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
package io.novafoundation.nova.feature_proxy_impl.data.repository
|
||||
|
||||
import io.novafoundation.nova.common.address.AccountIdKey
|
||||
import io.novafoundation.nova.common.address.intoKey
|
||||
import io.novafoundation.nova.common.data.network.runtime.binding.cast
|
||||
import io.novafoundation.nova.common.data.network.runtime.binding.castToDictEnum
|
||||
import io.novafoundation.nova.common.data.network.runtime.binding.castToList
|
||||
import io.novafoundation.nova.common.data.network.runtime.binding.castToStruct
|
||||
import io.novafoundation.nova.common.data.network.runtime.binding.getTyped
|
||||
import io.novafoundation.nova.common.utils.Modules
|
||||
import io.novafoundation.nova.common.utils.numberConstant
|
||||
import io.novafoundation.nova.common.utils.proxy
|
||||
import io.novafoundation.nova.feature_proxy_api.data.model.OnChainProxiedModel
|
||||
import io.novafoundation.nova.feature_proxy_api.data.model.OnChainProxyModel
|
||||
import io.novafoundation.nova.feature_proxy_api.data.model.ProxiesMap
|
||||
import io.novafoundation.nova.feature_proxy_api.data.model.ProxyPermission
|
||||
import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository
|
||||
import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType
|
||||
import io.novafoundation.nova.feature_proxy_api.domain.model.fromString
|
||||
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.getRuntime
|
||||
import io.novafoundation.nova.runtime.storage.source.StorageDataSource
|
||||
import io.novasama.substrate_sdk_android.runtime.AccountId
|
||||
import io.novasama.substrate_sdk_android.runtime.metadata.module
|
||||
import io.novasama.substrate_sdk_android.runtime.metadata.storage
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import java.math.BigInteger
|
||||
|
||||
class RealGetProxyRepository(
|
||||
private val remoteSource: StorageDataSource,
|
||||
private val localSource: StorageDataSource,
|
||||
private val chainRegistry: ChainRegistry,
|
||||
) : GetProxyRepository {
|
||||
|
||||
override suspend fun getAllProxies(chainId: ChainId): ProxiesMap {
|
||||
return receiveAllProxiesInChain(chainId)
|
||||
}
|
||||
|
||||
override suspend fun getDelegatedProxyTypesRemote(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List<ProxyType> {
|
||||
return getDelegatedProxyTypes(remoteSource, chainId, proxiedAccountId, proxyAccountId)
|
||||
}
|
||||
|
||||
// TODO: use it for staking after merge "add staking proxy" branch
|
||||
override suspend fun getDelegatedProxyTypesLocal(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List<ProxyType> {
|
||||
return getDelegatedProxyTypes(localSource, chainId, proxiedAccountId, proxyAccountId)
|
||||
}
|
||||
|
||||
override suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int {
|
||||
val proxied = getAllProxiesFor(localSource, chainId, proxiedAccountId)
|
||||
|
||||
return proxied.proxies.size
|
||||
}
|
||||
|
||||
override suspend fun getProxyDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger {
|
||||
val proxied = getAllProxiesFor(localSource, chainId, proxiedAccountId)
|
||||
|
||||
return proxied.deposit
|
||||
}
|
||||
|
||||
override suspend fun maxProxiesQuantity(chain: Chain): Int {
|
||||
val runtime = chainRegistry.getRuntime(chain.id)
|
||||
val constantQuery = runtime.metadata.proxy()
|
||||
return constantQuery.numberConstant("MaxProxies", runtime).toInt()
|
||||
}
|
||||
|
||||
override fun proxiesByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow<List<ProxyPermission>> {
|
||||
return localSource.subscribe(chain.id) {
|
||||
runtime.metadata.module(Modules.PROXY)
|
||||
.storage("Proxies")
|
||||
.observe(
|
||||
accountId,
|
||||
binding = { bindProxyAccounts(it) }
|
||||
)
|
||||
}.map { proxied ->
|
||||
proxied.proxies
|
||||
.filter { it.proxyType.name == proxyType.name }
|
||||
.map { ProxyPermission(accountId.intoKey(), it.proxy, it.proxyType) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun proxiesQuantityByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow<Int> {
|
||||
return proxiesByTypeFlow(chain, accountId, proxyType)
|
||||
.map { it.size }
|
||||
}
|
||||
|
||||
private suspend fun getDelegatedProxyTypes(
|
||||
storageDataSource: StorageDataSource,
|
||||
chainId: ChainId,
|
||||
proxiedAccountId: AccountId,
|
||||
proxyAccountId: AccountId
|
||||
): List<ProxyType> {
|
||||
val proxied = getAllProxiesFor(storageDataSource, chainId, proxiedAccountId)
|
||||
|
||||
return proxied.proxies
|
||||
.filter { it.proxy == proxyAccountId.intoKey() }
|
||||
.map { it.proxyType }
|
||||
}
|
||||
|
||||
private suspend fun getAllProxiesFor(storageDataSource: StorageDataSource, chainId: ChainId, accountId: AccountId): OnChainProxiedModel {
|
||||
return storageDataSource.query(chainId) {
|
||||
runtime.metadata.module(Modules.PROXY)
|
||||
.storage("Proxies")
|
||||
.query(
|
||||
keyArguments = arrayOf(accountId),
|
||||
binding = { result -> bindProxyAccounts(result) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun receiveAllProxiesInChain(chainId: ChainId): Map<AccountIdKey, OnChainProxiedModel> {
|
||||
return remoteSource.query(chainId) {
|
||||
runtime.metadata.module(Modules.PROXY)
|
||||
.storage("Proxies")
|
||||
.entries(
|
||||
keyExtractor = { (accountId: AccountId) -> AccountIdKey(accountId) },
|
||||
binding = { result, _ -> bindProxyAccounts(result) },
|
||||
recover = { _, _ ->
|
||||
// Do nothing if entry binding throws an exception
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindProxyAccounts(dynamicInstance: Any?): OnChainProxiedModel {
|
||||
if (dynamicInstance == null) return OnChainProxiedModel(emptyList(), BigInteger.ZERO)
|
||||
|
||||
val root = dynamicInstance.castToList()
|
||||
val proxies = root[0].castToList()
|
||||
|
||||
return OnChainProxiedModel(
|
||||
proxies = proxies.map {
|
||||
val proxy = it.castToStruct()
|
||||
val proxyAccountId: ByteArray = proxy.getTyped("delegate")
|
||||
val proxyType = proxy.get<Any?>("proxyType").castToDictEnum()
|
||||
val delay = proxy.getTyped<BigInteger>("delay")
|
||||
OnChainProxyModel(
|
||||
proxy = proxyAccountId.intoKey(),
|
||||
proxyType = ProxyType.fromString(proxyType.name),
|
||||
delay = delay
|
||||
)
|
||||
},
|
||||
deposit = root[1].cast()
|
||||
)
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package io.novafoundation.nova.feature_proxy_impl.data.repository
|
||||
|
||||
import io.novafoundation.nova.common.utils.numberConstant
|
||||
import io.novafoundation.nova.common.utils.proxy
|
||||
import io.novafoundation.nova.feature_proxy_api.data.common.DepositBaseAndFactor
|
||||
import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository
|
||||
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
|
||||
import io.novafoundation.nova.runtime.multiNetwork.getRuntime
|
||||
|
||||
class RealProxyConstantsRepository(
|
||||
private val chainRegestry: ChainRegistry
|
||||
) : ProxyConstantsRepository {
|
||||
|
||||
override suspend fun getDepositConstants(chainId: ChainId): DepositBaseAndFactor {
|
||||
val runtime = chainRegestry.getRuntime(chainId)
|
||||
val constantQuery = runtime.metadata.proxy()
|
||||
return DepositBaseAndFactor(
|
||||
baseAmount = constantQuery.numberConstant("ProxyDepositBase", runtime),
|
||||
factorAmount = constantQuery.numberConstant("ProxyDepositFactor", runtime)
|
||||
)
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package io.novafoundation.nova.feature_proxy_impl.di
|
||||
|
||||
import dagger.Component
|
||||
import io.novafoundation.nova.common.di.CommonApi
|
||||
import io.novafoundation.nova.common.di.scope.FeatureScope
|
||||
import io.novafoundation.nova.feature_proxy_api.di.ProxyFeatureApi
|
||||
import io.novafoundation.nova.runtime.di.RuntimeApi
|
||||
|
||||
@Component(
|
||||
dependencies = [
|
||||
ProxyFeatureDependencies::class
|
||||
],
|
||||
modules = [
|
||||
ProxyFeatureModule::class,
|
||||
]
|
||||
)
|
||||
@FeatureScope
|
||||
interface ProxyFeatureComponent : ProxyFeatureApi {
|
||||
|
||||
@Component.Factory
|
||||
interface Factory {
|
||||
|
||||
fun create(
|
||||
deps: ProxyFeatureDependencies
|
||||
): ProxyFeatureComponent
|
||||
}
|
||||
|
||||
@Component(
|
||||
dependencies = [
|
||||
CommonApi::class,
|
||||
RuntimeApi::class
|
||||
]
|
||||
)
|
||||
interface VoteFeatureDependenciesComponent : ProxyFeatureDependencies
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package io.novafoundation.nova.feature_proxy_impl.di
|
||||
|
||||
import io.novafoundation.nova.runtime.di.LOCAL_STORAGE_SOURCE
|
||||
import io.novafoundation.nova.runtime.di.REMOTE_STORAGE_SOURCE
|
||||
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
|
||||
import io.novafoundation.nova.runtime.storage.source.StorageDataSource
|
||||
import javax.inject.Named
|
||||
|
||||
interface ProxyFeatureDependencies {
|
||||
|
||||
@Named(REMOTE_STORAGE_SOURCE)
|
||||
fun remoteStorageSource(): StorageDataSource
|
||||
|
||||
@Named(LOCAL_STORAGE_SOURCE)
|
||||
fun localStorageSource(): StorageDataSource
|
||||
|
||||
fun chainRegistry(): ChainRegistry
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package io.novafoundation.nova.feature_proxy_impl.di
|
||||
|
||||
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 ProxyFeatureHolder @Inject constructor(
|
||||
featureContainer: FeatureContainer
|
||||
) : FeatureApiHolder(featureContainer) {
|
||||
|
||||
override fun initializeDependencies(): Any {
|
||||
val dependencies = DaggerProxyFeatureComponent_VoteFeatureDependenciesComponent.builder()
|
||||
.commonApi(commonApi())
|
||||
.runtimeApi(getFeature(RuntimeApi::class.java))
|
||||
.build()
|
||||
return DaggerProxyFeatureComponent.factory()
|
||||
.create(dependencies)
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package io.novafoundation.nova.feature_proxy_impl.di
|
||||
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import io.novafoundation.nova.common.di.scope.FeatureScope
|
||||
import io.novafoundation.nova.feature_proxy_api.data.common.ProxyDepositCalculator
|
||||
import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository
|
||||
import io.novafoundation.nova.feature_proxy_api.data.repository.ProxyConstantsRepository
|
||||
import io.novafoundation.nova.feature_proxy_impl.data.common.RealProxyDepositCalculator
|
||||
import io.novafoundation.nova.feature_proxy_impl.data.repository.RealGetProxyRepository
|
||||
import io.novafoundation.nova.feature_proxy_impl.data.repository.RealProxyConstantsRepository
|
||||
import io.novafoundation.nova.runtime.di.LOCAL_STORAGE_SOURCE
|
||||
import io.novafoundation.nova.runtime.di.REMOTE_STORAGE_SOURCE
|
||||
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
|
||||
import io.novafoundation.nova.runtime.storage.source.StorageDataSource
|
||||
import javax.inject.Named
|
||||
|
||||
@Module
|
||||
class ProxyFeatureModule {
|
||||
|
||||
@Provides
|
||||
@FeatureScope
|
||||
fun provideProxyRepository(
|
||||
@Named(REMOTE_STORAGE_SOURCE) remoteSource: StorageDataSource,
|
||||
@Named(LOCAL_STORAGE_SOURCE) localSource: StorageDataSource,
|
||||
chainRegistry: ChainRegistry
|
||||
): GetProxyRepository = RealGetProxyRepository(
|
||||
remoteSource = remoteSource,
|
||||
localSource = localSource,
|
||||
chainRegistry
|
||||
)
|
||||
|
||||
@Provides
|
||||
@FeatureScope
|
||||
fun provideProxyConstantsRepository(
|
||||
chainRegistry: ChainRegistry
|
||||
): ProxyConstantsRepository = RealProxyConstantsRepository(
|
||||
chainRegistry
|
||||
)
|
||||
|
||||
@Provides
|
||||
@FeatureScope
|
||||
fun provideProxyDepositCalculator(
|
||||
proxyConstantsRepository: ProxyConstantsRepository
|
||||
): ProxyDepositCalculator {
|
||||
return RealProxyDepositCalculator(proxyConstantsRepository)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user