Initial commit: Pezkuwi Wallet Android

Complete rebrand of Nova Wallet for Pezkuwichain ecosystem.

## Features
- Full Pezkuwichain support (HEZ & PEZ tokens)
- Polkadot ecosystem compatibility
- Staking, Governance, DeFi, NFTs
- XCM cross-chain transfers
- Hardware wallet support (Ledger, Polkadot Vault)
- WalletConnect v2
- Push notifications

## Languages
- English, Turkish, Kurmanci (Kurdish), Spanish, French, German, Russian, Japanese, Chinese, Korean, Portuguese, Vietnamese

Based on Nova Wallet by Novasama Technologies GmbH
© Dijital Kurdistan Tech Institute 2026
This commit is contained in:
2026-01-23 01:31:12 +03:00
commit 31c8c5995f
7621 changed files with 425838 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/build
+11
View File
@@ -0,0 +1,11 @@
android {
namespace 'io.novafoundation.nova.feature_proxy_api'
}
dependencies {
implementation project(":common")
implementation project(':runtime')
implementation substrateSdkDep
}
+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,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
@@ -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.novasama.substrate_sdk_android.runtime.definitions.types.instances.AddressInstanceConstructor
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 AddressInstanceConstructor.constructInstance(runtime.typeRegistry, proxyAccountId),
"proxy_type" to DictEnum.Entry(proxyType.name, null),
"delay" to BigInteger.ZERO
)
}
@@ -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
)
@@ -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
}
@@ -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
)
@@ -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
)
@@ -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>
@@ -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
)
@@ -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>
}
@@ -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
}
@@ -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
}
@@ -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)
}
}
@@ -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
)
)
}
@@ -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
)
)
}