mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-04-22 09:08:03 +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" />
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.data.calls
|
||||
|
||||
import io.novafoundation.nova.common.utils.Modules
|
||||
import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType
|
||||
import java.math.BigInteger
|
||||
import io.novasama.substrate_sdk_android.runtime.AccountId
|
||||
import io.novasama.substrate_sdk_android.runtime.RuntimeSnapshot
|
||||
import io.novasama.substrate_sdk_android.runtime.definitions.types.composite.DictEnum
|
||||
import io.novafoundation.nova.common.utils.PezkuwiAddressConstructor
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.builder.ExtrinsicBuilder
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.call
|
||||
|
||||
fun ExtrinsicBuilder.addProxyCall(proxyAccountId: AccountId, proxyType: ProxyType): ExtrinsicBuilder {
|
||||
return call(
|
||||
Modules.PROXY,
|
||||
"add_proxy",
|
||||
argumentsForProxy(runtime, proxyAccountId, proxyType)
|
||||
)
|
||||
}
|
||||
|
||||
fun ExtrinsicBuilder.removeProxyCall(proxyAccountId: AccountId, proxyType: ProxyType): ExtrinsicBuilder {
|
||||
return call(
|
||||
Modules.PROXY,
|
||||
"remove_proxy",
|
||||
argumentsForProxy(runtime, proxyAccountId, proxyType)
|
||||
)
|
||||
}
|
||||
|
||||
private fun argumentsForProxy(runtime: RuntimeSnapshot, proxyAccountId: AccountId, proxyType: ProxyType): Map<String, Any> {
|
||||
return mapOf(
|
||||
"delegate" to PezkuwiAddressConstructor.constructInstance(runtime.typeRegistry, proxyAccountId),
|
||||
"proxy_type" to DictEnum.Entry(proxyType.name, null),
|
||||
"delay" to BigInteger.ZERO
|
||||
)
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.data.common
|
||||
|
||||
import java.math.BigInteger
|
||||
|
||||
class DepositBaseAndFactor(
|
||||
val baseAmount: BigInteger,
|
||||
val factorAmount: BigInteger
|
||||
)
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.data.common
|
||||
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
|
||||
import java.math.BigInteger
|
||||
|
||||
interface ProxyDepositCalculator {
|
||||
|
||||
fun calculateProxyDepositForQuantity(baseAndFactor: DepositBaseAndFactor, proxiesCount: Int): BigInteger
|
||||
|
||||
suspend fun calculateProxyDepositForQuantity(chainId: ChainId, proxiesCount: Int): BigInteger
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.data.model
|
||||
|
||||
import java.math.BigInteger
|
||||
|
||||
class OnChainProxiedModel(
|
||||
val proxies: List<OnChainProxyModel>,
|
||||
val deposit: BigInteger
|
||||
)
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.data.model
|
||||
|
||||
import io.novafoundation.nova.common.address.AccountIdKey
|
||||
import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType
|
||||
import java.math.BigInteger
|
||||
|
||||
class OnChainProxyModel(
|
||||
val proxy: AccountIdKey,
|
||||
val proxyType: ProxyType,
|
||||
val delay: BigInteger
|
||||
)
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.data.model
|
||||
|
||||
import io.novafoundation.nova.common.address.AccountIdKey
|
||||
|
||||
typealias ProxiesMap = Map<AccountIdKey, OnChainProxiedModel>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.data.model
|
||||
|
||||
import io.novafoundation.nova.common.address.AccountIdKey
|
||||
import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType
|
||||
|
||||
data class ProxyPermission(
|
||||
val proxiedAccountId: AccountIdKey,
|
||||
val proxyAccountId: AccountIdKey,
|
||||
val proxyType: ProxyType
|
||||
)
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.data.repository
|
||||
|
||||
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.domain.model.ProxyType
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
|
||||
import io.novasama.substrate_sdk_android.runtime.AccountId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.math.BigInteger
|
||||
|
||||
interface GetProxyRepository {
|
||||
|
||||
suspend fun getAllProxies(chainId: ChainId): ProxiesMap
|
||||
|
||||
suspend fun getDelegatedProxyTypesRemote(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List<ProxyType>
|
||||
|
||||
suspend fun getDelegatedProxyTypesLocal(chainId: ChainId, proxiedAccountId: AccountId, proxyAccountId: AccountId): List<ProxyType>
|
||||
|
||||
suspend fun getProxiesQuantity(chainId: ChainId, proxiedAccountId: AccountId): Int
|
||||
|
||||
suspend fun getProxyDeposit(chainId: ChainId, proxiedAccountId: AccountId): BigInteger
|
||||
|
||||
suspend fun maxProxiesQuantity(chain: Chain): Int
|
||||
|
||||
fun proxiesByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow<List<ProxyPermission>>
|
||||
|
||||
fun proxiesQuantityByTypeFlow(chain: Chain, accountId: AccountId, proxyType: ProxyType): Flow<Int>
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.data.repository
|
||||
|
||||
import io.novafoundation.nova.feature_proxy_api.data.common.DepositBaseAndFactor
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
|
||||
|
||||
interface ProxyConstantsRepository {
|
||||
|
||||
suspend fun getDepositConstants(chainId: ChainId): DepositBaseAndFactor
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.di
|
||||
|
||||
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
|
||||
|
||||
interface ProxyFeatureApi {
|
||||
|
||||
val proxyRepository: GetProxyRepository
|
||||
|
||||
val proxyDepositCalculator: ProxyDepositCalculator
|
||||
|
||||
val proxyConstantsRepository: ProxyConstantsRepository
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.domain.model
|
||||
|
||||
sealed class ProxyType(open val name: String) {
|
||||
|
||||
data object Any : ProxyType("Any")
|
||||
|
||||
data object NonTransfer : ProxyType("NonTransfer")
|
||||
|
||||
data object Governance : ProxyType("Governance")
|
||||
|
||||
data object Staking : ProxyType("Staking")
|
||||
|
||||
data object IdentityJudgement : ProxyType("IdentityJudgement")
|
||||
|
||||
data object CancelProxy : ProxyType("CancelProxy")
|
||||
|
||||
data object Auction : ProxyType("Auction")
|
||||
|
||||
data object NominationPools : ProxyType("NominationPools")
|
||||
|
||||
data class Other(override val name: String) : ProxyType(name)
|
||||
|
||||
companion object
|
||||
}
|
||||
|
||||
fun ProxyType.Companion.fromString(name: String): ProxyType {
|
||||
return when (name) {
|
||||
"Any" -> ProxyType.Any
|
||||
"NonTransfer" -> ProxyType.NonTransfer
|
||||
"Governance" -> ProxyType.Governance
|
||||
"Staking" -> ProxyType.Staking
|
||||
"IdentityJudgement" -> ProxyType.IdentityJudgement
|
||||
"CancelProxy" -> ProxyType.CancelProxy
|
||||
"Auction" -> ProxyType.Auction
|
||||
"NominationPools" -> ProxyType.NominationPools
|
||||
else -> ProxyType.Other(name)
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.domain.validators
|
||||
|
||||
import io.novafoundation.nova.common.validation.Validation
|
||||
import io.novafoundation.nova.common.validation.ValidationStatus
|
||||
import io.novafoundation.nova.common.validation.ValidationSystemBuilder
|
||||
import io.novafoundation.nova.common.validation.validOrError
|
||||
import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
|
||||
import io.novasama.substrate_sdk_android.runtime.AccountId
|
||||
|
||||
class MaximumProxiesNotReachedValidation<P, E>(
|
||||
private val chain: (P) -> Chain,
|
||||
private val accountId: (P) -> AccountId,
|
||||
private val proxiesQuantity: (P) -> Int,
|
||||
private val error: (P, Int) -> E,
|
||||
private val proxyRepository: GetProxyRepository
|
||||
) : Validation<P, E> {
|
||||
|
||||
override suspend fun validate(value: P): ValidationStatus<E> {
|
||||
val newProxiesQuantity = proxiesQuantity(value)
|
||||
val maximumProxiesQuantiy = proxyRepository.maxProxiesQuantity(chain(value))
|
||||
|
||||
return validOrError(newProxiesQuantity <= maximumProxiesQuantiy) {
|
||||
error(value, maximumProxiesQuantiy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <P, E> ValidationSystemBuilder<P, E>.maximumProxiesNotReached(
|
||||
chain: (P) -> Chain,
|
||||
accountId: (P) -> AccountId,
|
||||
proxiesQuantity: (P) -> Int,
|
||||
error: (P, Int) -> E,
|
||||
proxyRepository: GetProxyRepository
|
||||
) {
|
||||
validate(
|
||||
MaximumProxiesNotReachedValidation(
|
||||
chain = chain,
|
||||
accountId = accountId,
|
||||
proxiesQuantity = proxiesQuantity,
|
||||
error = error,
|
||||
proxyRepository = proxyRepository
|
||||
)
|
||||
)
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package io.novafoundation.nova.feature_proxy_api.domain.validators
|
||||
|
||||
import io.novafoundation.nova.common.validation.Validation
|
||||
import io.novafoundation.nova.common.validation.ValidationStatus
|
||||
import io.novafoundation.nova.common.validation.ValidationSystemBuilder
|
||||
import io.novafoundation.nova.common.validation.validOrError
|
||||
import io.novafoundation.nova.feature_proxy_api.data.repository.GetProxyRepository
|
||||
import io.novafoundation.nova.feature_proxy_api.domain.model.ProxyType
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
|
||||
import io.novasama.substrate_sdk_android.runtime.AccountId
|
||||
|
||||
class ProxyIsNotDuplicationForAccount<P, E>(
|
||||
private val chain: (P) -> Chain,
|
||||
private val proxiedAccountId: (P) -> AccountId,
|
||||
private val proxyAccountId: (P) -> AccountId,
|
||||
private val proxyType: (P) -> ProxyType,
|
||||
private val error: (P) -> E,
|
||||
private val proxyRepository: GetProxyRepository
|
||||
) : Validation<P, E> {
|
||||
|
||||
override suspend fun validate(value: P): ValidationStatus<E> {
|
||||
val chain = chain(value)
|
||||
val proxyTypes = proxyRepository.getDelegatedProxyTypesLocal(chain.id, proxiedAccountId(value), proxyAccountId(value))
|
||||
|
||||
return validOrError(!proxyTypes.contains(proxyType(value))) {
|
||||
error(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <P, E> ValidationSystemBuilder<P, E>.proxyIsNotDuplicationForAccount(
|
||||
chain: (P) -> Chain,
|
||||
proxiedAccountId: (P) -> AccountId,
|
||||
proxyAccountId: (P) -> AccountId,
|
||||
proxyType: (P) -> ProxyType,
|
||||
error: (P) -> E,
|
||||
proxyRepository: GetProxyRepository
|
||||
) {
|
||||
validate(
|
||||
ProxyIsNotDuplicationForAccount(
|
||||
chain = chain,
|
||||
proxiedAccountId = proxiedAccountId,
|
||||
proxyAccountId = proxyAccountId,
|
||||
proxyType = proxyType,
|
||||
error = error,
|
||||
proxyRepository = proxyRepository
|
||||
)
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user