feat(xcm): Add Pezkuwi Teyrchain junction support for cross-chain transfers

- Add TEYRCHAIN_INFO constant and TeyrchainInfo pallet lookup
- Add PezkuwiXcm pallet support in xcmPalletName functions
- Update ParachainInfoRepository to query TeyrchainId storage
- Add junctionTypeName to ParachainId for Teyrchain encoding
- Update MultiLocationEncoding to handle both Parachain and Teyrchain
- Detect Pezkuwi chains by genesis hash for correct junction type

Fixes cross-chain transfers between Pezkuwi, Asset Hub, and People chains.
This commit is contained in:
2026-02-09 01:01:48 +03:00
parent 9babf454c9
commit 35ce943f65
9 changed files with 89 additions and 13 deletions
@@ -2,17 +2,27 @@ package io.novafoundation.nova.feature_xcm_api.chain
import io.novafoundation.nova.feature_xcm_api.multiLocation.AbsoluteMultiLocation
import io.novafoundation.nova.feature_xcm_api.multiLocation.ChainLocation
import io.novafoundation.nova.feature_xcm_api.multiLocation.MultiLocation.Junction.ParachainId.Companion.JUNCTION_TYPE_PARACHAIN
import io.novafoundation.nova.feature_xcm_api.multiLocation.MultiLocation.Junction.ParachainId.Companion.JUNCTION_TYPE_TEYRCHAIN
import io.novafoundation.nova.feature_xcm_api.multiLocation.chainLocation
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import java.math.BigInteger
// Pezkuwi chain IDs - these chains use "Teyrchain" instead of "Parachain" in XCM
private val PEZKUWI_CHAIN_IDS = setOf(
"bb4a61ab0c4b8c12f5eab71d0c86c482e03a275ecdafee678dea712474d33d75", // PEZKUWI
"00d0e1d0581c3cd5c5768652d52f4520184018b44f56a2ae1e0dc9d65c00c948", // PEZKUWI_ASSET_HUB
"58269e9c184f721e0309332d90cafc410df1519a5dc27a5fd9b3bf5fd2d129f8" // PEZKUWI_PEOPLE
)
class XcmChain(
val parachainId: BigInteger?,
val chain: Chain
)
fun XcmChain.absoluteLocation(): AbsoluteMultiLocation {
return AbsoluteMultiLocation.chainLocation(parachainId)
val junctionTypeName = if (chain.id in PEZKUWI_CHAIN_IDS) JUNCTION_TYPE_TEYRCHAIN else JUNCTION_TYPE_PARACHAIN
return AbsoluteMultiLocation.chainLocation(parachainId, junctionTypeName)
}
fun XcmChain.isRelay(): Boolean {
@@ -41,6 +41,9 @@ class AbsoluteMultiLocation(
}
}
fun AbsoluteMultiLocation.Companion.chainLocation(parachainId: ParaId?): AbsoluteMultiLocation {
return listOfNotNull(parachainId?.let(MultiLocation.Junction::ParachainId)).asLocation()
fun AbsoluteMultiLocation.Companion.chainLocation(
parachainId: ParaId?,
junctionTypeName: String = MultiLocation.Junction.ParachainId.JUNCTION_TYPE_PARACHAIN
): AbsoluteMultiLocation {
return listOfNotNull(parachainId?.let { MultiLocation.Junction.ParachainId(it, junctionTypeName) }).asLocation()
}
@@ -37,9 +37,17 @@ abstract class MultiLocation(
sealed class Junction {
data class ParachainId(val id: ParaId) : Junction() {
data class ParachainId(
val id: ParaId,
val junctionTypeName: String = JUNCTION_TYPE_PARACHAIN
) : Junction() {
constructor(id: Int) : this(id.toBigInteger())
constructor(id: Int, junctionTypeName: String = JUNCTION_TYPE_PARACHAIN) : this(id.toBigInteger(), junctionTypeName)
companion object {
const val JUNCTION_TYPE_PARACHAIN = "Parachain"
const val JUNCTION_TYPE_TEYRCHAIN = "Teyrchain"
}
}
data class GeneralKey(val key: HexString) : Junction()
@@ -1,5 +1,6 @@
package io.novafoundation.nova.feature_xcm_api.multiLocation
import android.util.Log
import io.novafoundation.nova.common.address.AccountIdKey
import io.novafoundation.nova.common.address.intoKey
import io.novafoundation.nova.common.data.network.runtime.binding.bindAccountId
@@ -69,7 +70,8 @@ private fun bindJunction(instance: Any?): Junction {
return when (asDictEnum.name) {
"GeneralKey" -> Junction.GeneralKey(bindGeneralKey(asDictEnum.value))
"PalletInstance" -> Junction.PalletInstance(bindNumber(asDictEnum.value))
"Parachain" -> Junction.ParachainId(bindNumber(asDictEnum.value))
// Accept both "Parachain" (Polkadot ecosystem) and "Teyrchain" (Pezkuwi ecosystem)
"Parachain", "Teyrchain" -> Junction.ParachainId(bindNumber(asDictEnum.value), asDictEnum.name)
"GeneralIndex" -> Junction.GeneralIndex(bindNumber(asDictEnum.value))
"GlobalConsensus" -> bindGlobalConsensusJunction(asDictEnum.value)
"AccountKey20" -> Junction.AccountKey20(bindAccountIdJunction(asDictEnum.value, accountIdKey = "key"))
@@ -146,7 +148,10 @@ private fun MultiLocation.Interior.toEncodableInstance(xcmVersion: XcmVersion) =
private fun Junction.toEncodableInstance(xcmVersion: XcmVersion) = when (this) {
is Junction.GeneralKey -> DictEnum.Entry("GeneralKey", encodableGeneralKey(xcmVersion, key))
is Junction.PalletInstance -> DictEnum.Entry("PalletInstance", index)
is Junction.ParachainId -> DictEnum.Entry("Parachain", id)
is Junction.ParachainId -> {
Log.d("XCM_ENCODE", "Encoding ParachainId: id=$id, junctionTypeName=$junctionTypeName")
DictEnum.Entry(junctionTypeName, id)
}
is Junction.AccountKey20 -> DictEnum.Entry("AccountKey20", accountId.toJunctionAccountIdInstance(accountIdKey = "key", xcmVersion))
is Junction.AccountId32 -> DictEnum.Entry("AccountId32", accountId.toJunctionAccountIdInstance(accountIdKey = "id", xcmVersion))
is Junction.GeneralIndex -> DictEnum.Entry("GeneralIndex", index)