From 830febbfdf580dbd4d8cd82196b3dd106ec3ce19 Mon Sep 17 00:00:00 2001 From: ERussel Date: Mon, 18 Nov 2024 18:17:30 +0100 Subject: [PATCH] support xcmv4 multilocation for asset conversion --- novawallet.xcodeproj/project.pbxproj | 8 ++++ .../CrosschainAssetConversionFactory.swift | 2 +- .../AssetConversionPallet.swift | 15 ++++++- .../Types/Xcm/V4/XcmJunctionV4.swift | 43 +++++++++++++++++++ .../Common/Substrate/Types/Xcm/V4/XcmV4.swift | 4 +- .../Types/Xcm/V4/XcmV4Multilocation.swift | 9 ++++ .../AssetHub/AssetHubTokensConverter.swift | 12 +++--- .../OnChainTransferSetupPresenter.swift | 2 + 8 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 novawallet/Common/Substrate/Types/Xcm/V4/XcmJunctionV4.swift create mode 100644 novawallet/Common/Substrate/Types/Xcm/V4/XcmV4Multilocation.swift diff --git a/novawallet.xcodeproj/project.pbxproj b/novawallet.xcodeproj/project.pbxproj index 91cca28746..30c13f3fa7 100644 --- a/novawallet.xcodeproj/project.pbxproj +++ b/novawallet.xcodeproj/project.pbxproj @@ -63,6 +63,8 @@ 0C0E0AA32B3F01FD00865F10 /* UniquesPallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0E0AA22B3F01FD00865F10 /* UniquesPallet.swift */; }; 0C12A2472AA1D96000C7FA49 /* SubqueryMultistakingTypeFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C12A2462AA1D96000C7FA49 /* SubqueryMultistakingTypeFactory.swift */; }; 0C12A2492AA35AE300C7FA49 /* RelaychainStakingValidatorFacade.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C12A2482AA35AE300C7FA49 /* RelaychainStakingValidatorFacade.swift */; }; + 0C12BC482CEB996700AB919D /* XcmV4Multilocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C12BC472CEB996700AB919D /* XcmV4Multilocation.swift */; }; + 0C12BC492CEB996700AB919D /* XcmJunctionV4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C12BC462CEB996700AB919D /* XcmJunctionV4.swift */; }; 0C1338102AB832B30036BCD6 /* QRImageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C13380F2AB832B30036BCD6 /* QRImageViewModel.swift */; }; 0C1338122AB8330D0036BCD6 /* AnimatedImageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C1338112AB8330D0036BCD6 /* AnimatedImageViewModel.swift */; }; 0C1338142AB834750036BCD6 /* QRImageViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C1338132AB834750036BCD6 /* QRImageViewModelFactory.swift */; }; @@ -5206,6 +5208,8 @@ 0C0E0AA22B3F01FD00865F10 /* UniquesPallet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UniquesPallet.swift; sourceTree = ""; }; 0C12A2462AA1D96000C7FA49 /* SubqueryMultistakingTypeFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubqueryMultistakingTypeFactory.swift; sourceTree = ""; }; 0C12A2482AA35AE300C7FA49 /* RelaychainStakingValidatorFacade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaychainStakingValidatorFacade.swift; sourceTree = ""; }; + 0C12BC462CEB996700AB919D /* XcmJunctionV4.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcmJunctionV4.swift; sourceTree = ""; }; + 0C12BC472CEB996700AB919D /* XcmV4Multilocation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcmV4Multilocation.swift; sourceTree = ""; }; 0C13380F2AB832B30036BCD6 /* QRImageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRImageViewModel.swift; sourceTree = ""; }; 0C1338112AB8330D0036BCD6 /* AnimatedImageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedImageViewModel.swift; sourceTree = ""; }; 0C1338132AB834750036BCD6 /* QRImageViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRImageViewModelFactory.swift; sourceTree = ""; }; @@ -11932,6 +11936,8 @@ 0CEB6B342CA4507200609DC2 /* V4 */ = { isa = PBXGroup; children = ( + 0C12BC462CEB996700AB919D /* XcmJunctionV4.swift */, + 0C12BC472CEB996700AB919D /* XcmV4Multilocation.swift */, 0CEB6B352CA450AC00609DC2 /* XcmV4LocatableAsset.swift */, 0CEB6B372CA450C200609DC2 /* XcmV4.swift */, ); @@ -25108,6 +25114,8 @@ 777BD86429F979DA004969A2 /* SelectableFilterCell.swift in Sources */, 0C992C3F2B53AEF700ACC129 /* OperationSearchService.swift in Sources */, 8849AD6229C3532600F4F7FF /* String+Split.swift in Sources */, + 0C12BC482CEB996700AB919D /* XcmV4Multilocation.swift in Sources */, + 0C12BC492CEB996700AB919D /* XcmJunctionV4.swift in Sources */, 8466781C27ED9644007935D3 /* AsyncWarningConditionViolation.swift in Sources */, 0C3976A92C330A1D00998DD6 /* HydraXYK+PoolAccount.swift in Sources */, 849067CA299BCCB700B2983E /* GovernanceRevokeDelegationConfirmPresenter+Update.swift in Sources */, diff --git a/novawallet/Common/Substrate/AssetConverters/CrosschainAssetConversionFactory.swift b/novawallet/Common/Substrate/AssetConverters/CrosschainAssetConversionFactory.swift index 74101b782a..9bdb2b3916 100644 --- a/novawallet/Common/Substrate/AssetConverters/CrosschainAssetConversionFactory.swift +++ b/novawallet/Common/Substrate/AssetConverters/CrosschainAssetConversionFactory.swift @@ -32,7 +32,7 @@ final class CrosschainAssetConversionFactory { private func createAssetsPalletWrapper( for paraId: ParaId, - assetId: AssetConversionPallet.AssetId, + assetId: XcmV3.Multilocation, chainRegistry: ChainRegistryProtocol ) -> CompoundOperationWrapper { let paraResolutionWrapper = parachainResolver.resolveChainId( diff --git a/novawallet/Common/Substrate/Types/AssetConversionPallet/AssetConversionPallet.swift b/novawallet/Common/Substrate/Types/AssetConversionPallet/AssetConversionPallet.swift index be2c3dd2b1..7bf83d5fd6 100644 --- a/novawallet/Common/Substrate/Types/AssetConversionPallet/AssetConversionPallet.swift +++ b/novawallet/Common/Substrate/Types/AssetConversionPallet/AssetConversionPallet.swift @@ -5,7 +5,7 @@ import BigInt enum AssetConversionPallet { static let name = "AssetConversion" - typealias AssetId = XcmV3.Multilocation + typealias AssetId = XcmV4.Multilocation enum PoolAsset { case native @@ -42,3 +42,16 @@ enum AssetConversionPallet { } } } + +protocol AssetConversionAssetIdProtocol { + var parents: UInt8 { get } + var items: [XcmV3.Junction] { get } +} + +extension AssetConversionPallet.AssetId: AssetConversionAssetIdProtocol { + var items: [XcmV3.Junction] { interior.items } +} + +extension XcmV3.Multilocation: AssetConversionAssetIdProtocol { + var items: [XcmV3.Junction] { interior.items } +} diff --git a/novawallet/Common/Substrate/Types/Xcm/V4/XcmJunctionV4.swift b/novawallet/Common/Substrate/Types/Xcm/V4/XcmJunctionV4.swift new file mode 100644 index 0000000000..3e0f05ecc9 --- /dev/null +++ b/novawallet/Common/Substrate/Types/Xcm/V4/XcmJunctionV4.swift @@ -0,0 +1,43 @@ +import Foundation +import SubstrateSdk + +extension XcmV4 { + struct GenericJunctions: Codable where J: Codable { + let items: [J] + + init(items: [J]) { + self.items = items + } + + init(from decoder: Decoder) throws { + var container = try decoder.unkeyedContainer() + + let type = try container.decode(String.self) + + if type == Xcm.JunctionsConstants.hereField { + items = [] + } else { + items = try container.decode([J].self) + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.unkeyedContainer() + + if items.isEmpty { + try container.encode(Xcm.JunctionsConstants.hereField) + } else { + let xLocation = "\(Xcm.JunctionsConstants.junctionPrefix)\(items.count)" + try container.encode(xLocation) + } + + if items.isEmpty { + try container.encode(JSON.null) + } else { + try container.encode(items) + } + } + } + + typealias Junctions = GenericJunctions +} diff --git a/novawallet/Common/Substrate/Types/Xcm/V4/XcmV4.swift b/novawallet/Common/Substrate/Types/Xcm/V4/XcmV4.swift index 06ef79f744..f15f2a9e45 100644 --- a/novawallet/Common/Substrate/Types/Xcm/V4/XcmV4.swift +++ b/novawallet/Common/Substrate/Types/Xcm/V4/XcmV4.swift @@ -1,3 +1,5 @@ import Foundation -enum XcmV4 {} +enum XcmV4 { + typealias Junction = XcmV3.Junction +} diff --git a/novawallet/Common/Substrate/Types/Xcm/V4/XcmV4Multilocation.swift b/novawallet/Common/Substrate/Types/Xcm/V4/XcmV4Multilocation.swift new file mode 100644 index 0000000000..b25084985c --- /dev/null +++ b/novawallet/Common/Substrate/Types/Xcm/V4/XcmV4Multilocation.swift @@ -0,0 +1,9 @@ +import Foundation +import SubstrateSdk + +extension XcmV4 { + struct Multilocation: Codable { + @StringCodable var parents: UInt8 + let interior: XcmV4.Junctions + } +} diff --git a/novawallet/Modules/AssetConversion/Service/AssetHub/AssetHubTokensConverter.swift b/novawallet/Modules/AssetConversion/Service/AssetHub/AssetHubTokensConverter.swift index 24e59a684c..f6887dbf19 100644 --- a/novawallet/Modules/AssetConversion/Service/AssetHub/AssetHubTokensConverter.swift +++ b/novawallet/Modules/AssetConversion/Service/AssetHub/AssetHubTokensConverter.swift @@ -26,10 +26,10 @@ enum AssetHubTokensConverter { } static func convertFromMultilocation( - _ assetId: AssetConversionPallet.AssetId, + _ assetId: AssetConversionAssetIdProtocol, chain: ChainModel ) -> AssetConversionPallet.PoolAsset { - let junctions = assetId.interior.items + let junctions = assetId.items if assetId.parents == 0 { guard !junctions.isEmpty else { @@ -43,20 +43,20 @@ enum AssetHubTokensConverter { case let .generalIndex(index) = junctions[1] { return .assets(pallet: pallet, index: index) } else { - return .undefined(assetId) + return .undefined(.init(parents: assetId.parents, interior: .init(items: junctions))) } default: - return .undefined(assetId) + return .undefined(.init(parents: assetId.parents, interior: .init(items: junctions))) } } else if assetId.parents == 1, junctions.isEmpty, chain.isUtilityTokenOnRelaychain { return .native } else { - return .foreign(assetId) + return .foreign(.init(parents: assetId.parents, interior: .init(items: junctions))) } } static func convertFromMultilocationToLocal( - _ assetId: AssetConversionPallet.AssetId, + _ assetId: AssetConversionAssetIdProtocol, chain: ChainModel, conversionClosure: (AssetConversionPallet.PoolAsset) -> ChainAsset? ) -> ChainAsset? { diff --git a/novawallet/Modules/Transfer/TransferSetup/OnChain/OnChainTransferSetupPresenter.swift b/novawallet/Modules/Transfer/TransferSetup/OnChain/OnChainTransferSetupPresenter.swift index ecb6107241..74951789bb 100644 --- a/novawallet/Modules/Transfer/TransferSetup/OnChain/OnChainTransferSetupPresenter.swift +++ b/novawallet/Modules/Transfer/TransferSetup/OnChain/OnChainTransferSetupPresenter.swift @@ -328,6 +328,8 @@ final class OnChainTransferSetupPresenter: OnChainTransferPresenter, OnChainTran override func didReceiveError(_ error: Error) { super.didReceiveError(error) + logger?.debug("Did receive error: \(error)") + _ = wireframe.present(error: error, from: view, locale: selectedLocale) } }