fix: Add safety improvements for swap and XCM functionality

- Add independent chain warm-up with error handling
- Add fallback fee estimation when dry run fails
- Handle empty forwarded XCMs in dry run gracefully
- Support both legacy and new XCM config destination formats
- Use xcmPalletNameOrNull for safer pallet detection
- Add Teyrchain junction support for legacy cross-chain config
- Recover from dry run failures in cross-chain transfers
- Add Pezkuwi Asset Hub to swap warm-up chains
This commit is contained in:
2026-02-09 03:03:06 +03:00
parent 0457819ba4
commit 8c74b537d0
9 changed files with 149 additions and 39 deletions
@@ -3,7 +3,7 @@ package io.novafoundation.nova.feature_xcm_impl.versions.detector
import android.util.Log
import io.novafoundation.nova.common.di.scope.FeatureScope
import io.novafoundation.nova.common.utils.enumValueOfOrNull
import io.novafoundation.nova.common.utils.xcmPalletName
import io.novafoundation.nova.common.utils.xcmPalletNameOrNull
import io.novafoundation.nova.feature_xcm_api.versions.XcmVersion
import io.novafoundation.nova.feature_xcm_api.versions.detector.XcmVersionDetector
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
@@ -26,7 +26,7 @@ class RealXcmVersionDetector @Inject constructor(
override suspend fun lowestPresentMultiLocationVersion(chainId: ChainId): XcmVersion? {
return lowestPresentXcmTypeVersionFromCallArgument(
chainId = chainId,
getCall = { it.moduleOrNull(it.xcmPalletName())?.callOrNull("reserve_transfer_assets") },
getCall = { it.xcmPalletNameOrNull()?.let { pallet -> it.moduleOrNull(pallet) }?.callOrNull("reserve_transfer_assets") },
argumentName = "dest"
)
}
@@ -34,7 +34,7 @@ class RealXcmVersionDetector @Inject constructor(
override suspend fun lowestPresentMultiAssetsVersion(chainId: ChainId): XcmVersion? {
return lowestPresentXcmTypeVersionFromCallArgument(
chainId = chainId,
getCall = { it.moduleOrNull(it.xcmPalletName())?.callOrNull("reserve_transfer_assets") },
getCall = { it.xcmPalletNameOrNull()?.let { pallet -> it.moduleOrNull(pallet) }?.callOrNull("reserve_transfer_assets") },
argumentName = "assets"
)
}
@@ -42,7 +42,7 @@ class RealXcmVersionDetector @Inject constructor(
override suspend fun lowestPresentMultiAssetIdVersion(chainId: ChainId): XcmVersion? {
return lowestPresentXcmTypeVersionFromCallArgument(
chainId = chainId,
getCall = { it.moduleOrNull(it.xcmPalletName())?.callOrNull("transfer_assets_using_type_and_then") },
getCall = { it.xcmPalletNameOrNull()?.let { pallet -> it.moduleOrNull(pallet) }?.callOrNull("transfer_assets_using_type_and_then") },
argumentName = "remote_fees_id"
)
}
@@ -55,7 +55,7 @@ class RealXcmVersionDetector @Inject constructor(
val actualCheckedType = multiLocationType?.skipAliases() ?: return null
val versionedType = getVersionedType(
chainId = chainId,
getCall = { moduleOrNull(xcmPalletName())?.callOrNull("reserve_transfer_assets") },
getCall = { xcmPalletNameOrNull()?.let { moduleOrNull(it) }?.callOrNull("reserve_transfer_assets") },
argumentName = "dest"
) ?: return null