mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-05-31 22:11:05 +00:00
feat: Add bizinikiwi signing context for Pezkuwi ecosystem
Pezkuwi chains use "bizinikiwi" signing context instead of standard "substrate" context used by Polkadot ecosystem. This was causing "bad signature" errors on HEZ transfers. Changes: - Add sr25519-bizinikiwi native Rust binding with bizinikiwi context - Add isPezkuwiChain extension to detect Pezkuwi ecosystem chains - Add PezkuwiKeyPairSigner for signing with bizinikiwi context - Modify SecretsSigner to use correct context based on chain: - Pezkuwi chains (3) -> BizinikiwSr25519 (bizinikiwi) - Other chains (98+) -> KeyPairSigner (substrate) - Add live transfer test for Pezkuwi mainnet Tested with successful HEZ transfer on Pezkuwi mainnet: TX: 0xe25a4eaaeaa04122cca130582dba3cacb2280dea5d908924b45757ea67c27996
This commit is contained in:
+61
-6
@@ -7,20 +7,29 @@ import io.novafoundation.nova.common.data.secrets.v2.getMetaAccountKeypair
|
||||
import io.novafoundation.nova.common.di.scope.FeatureScope
|
||||
import io.novafoundation.nova.common.sequrity.TwoFactorVerificationResult
|
||||
import io.novafoundation.nova.common.sequrity.TwoFactorVerificationService
|
||||
import io.novafoundation.nova.feature_account_api.data.signer.SigningContext
|
||||
import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount
|
||||
import io.novafoundation.nova.feature_account_api.domain.model.ethereumAccountId
|
||||
import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdKeyIn
|
||||
import io.novafoundation.nova.feature_account_api.domain.model.substrateFrom
|
||||
import io.novafoundation.nova.feature_account_impl.data.signer.LeafSigner
|
||||
import io.novafoundation.nova.runtime.ext.isPezkuwiChain
|
||||
import io.novafoundation.nova.runtime.extrinsic.signer.PezkuwiKeyPairSigner
|
||||
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
|
||||
import io.novafoundation.nova.runtime.multiNetwork.ChainsById
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chainsById
|
||||
import io.novasama.substrate_sdk_android.encrypt.MultiChainEncryption
|
||||
import io.novasama.substrate_sdk_android.encrypt.SignatureWrapper
|
||||
import io.novasama.substrate_sdk_android.encrypt.keypair.Keypair
|
||||
import io.novasama.substrate_sdk_android.runtime.AccountId
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.builder.ExtrinsicBuilder
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.signer.KeyPairSigner
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.signer.SignedRaw
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.signer.SignerPayloadRaw
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.v5.transactionExtension.InheritedImplication
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.v5.transactionExtension.extensions.CheckNonce.Companion.setNonce
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.v5.transactionExtension.extensions.verifySignature.VerifySignature.Companion.setVerifySignature
|
||||
import javax.inject.Inject
|
||||
|
||||
@FeatureScope
|
||||
@@ -47,21 +56,63 @@ class SecretsSigner(
|
||||
private val twoFactorVerificationService: TwoFactorVerificationService,
|
||||
) : LeafSigner(metaAccount) {
|
||||
|
||||
// Track current signing chain to determine which context to use
|
||||
@Volatile
|
||||
private var currentSigningChain: Chain? = null
|
||||
|
||||
context(ExtrinsicBuilder)
|
||||
override suspend fun setSignerDataForSubmission(context: SigningContext) {
|
||||
// Capture the chain for use in signInheritedImplication
|
||||
currentSigningChain = context.chain
|
||||
|
||||
val accountId = metaAccount.requireAccountIdKeyIn(context.chain)
|
||||
setNonce(context.getNonce(accountId))
|
||||
setVerifySignature(signer = this, accountId = accountId.value)
|
||||
}
|
||||
|
||||
context(ExtrinsicBuilder)
|
||||
override suspend fun setSignerDataForFee(context: SigningContext) {
|
||||
// Capture the chain for use in signInheritedImplication
|
||||
currentSigningChain = context.chain
|
||||
|
||||
// Call parent implementation for fee signing
|
||||
super.setSignerDataForFee(context)
|
||||
}
|
||||
|
||||
override suspend fun signInheritedImplication(
|
||||
inheritedImplication: InheritedImplication,
|
||||
accountId: AccountId
|
||||
): SignatureWrapper {
|
||||
runTwoFactorVerificationIfEnabled()
|
||||
|
||||
val delegate = createDelegate(accountId)
|
||||
return delegate.signInheritedImplication(inheritedImplication, accountId)
|
||||
val chain = currentSigningChain
|
||||
val keypair = getKeypair(accountId)
|
||||
|
||||
// Use PezkuwiKeyPairSigner for Pezkuwi chains (bizinikiwi context)
|
||||
// Use standard KeyPairSigner for other chains (substrate context)
|
||||
return if (chain?.isPezkuwiChain == true) {
|
||||
val pezkuwiSigner = PezkuwiKeyPairSigner(keypair)
|
||||
pezkuwiSigner.signInheritedImplication(inheritedImplication, accountId)
|
||||
} else {
|
||||
val delegate = createDelegate(accountId, keypair)
|
||||
delegate.signInheritedImplication(inheritedImplication, accountId)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun signRaw(payload: SignerPayloadRaw): SignedRaw {
|
||||
runTwoFactorVerificationIfEnabled()
|
||||
|
||||
val delegate = createDelegate(payload.accountId)
|
||||
return delegate.signRaw(payload)
|
||||
val chain = currentSigningChain
|
||||
val keypair = getKeypair(payload.accountId)
|
||||
|
||||
// Use PezkuwiKeyPairSigner for Pezkuwi chains (bizinikiwi context)
|
||||
return if (chain?.isPezkuwiChain == true) {
|
||||
val pezkuwiSigner = PezkuwiKeyPairSigner(keypair)
|
||||
pezkuwiSigner.signRaw(payload)
|
||||
} else {
|
||||
val delegate = createDelegate(payload.accountId, keypair)
|
||||
delegate.signRaw(payload)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun maxCallsPerTransaction(): Int? {
|
||||
@@ -77,16 +128,20 @@ class SecretsSigner(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun createDelegate(accountId: AccountId): KeyPairSigner {
|
||||
private suspend fun getKeypair(accountId: AccountId): Keypair {
|
||||
val chainsById = chainRegistry.chainsById()
|
||||
val multiChainEncryption = metaAccount.multiChainEncryptionFor(accountId, chainsById)!!
|
||||
|
||||
val keypair = secretStoreV2.getKeypair(
|
||||
return secretStoreV2.getKeypair(
|
||||
metaAccount = metaAccount,
|
||||
accountId = accountId,
|
||||
isEthereumBased = multiChainEncryption is MultiChainEncryption.Ethereum
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun createDelegate(accountId: AccountId, keypair: Keypair): KeyPairSigner {
|
||||
val chainsById = chainRegistry.chainsById()
|
||||
val multiChainEncryption = metaAccount.multiChainEncryptionFor(accountId, chainsById)!!
|
||||
return KeyPairSigner(keypair, multiChainEncryption)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user