git.delta.rocks / unique-network / refs/commits / e2da42b8b024

difftreelog

feat xcm nft support

Daniel Shiposha2023-10-18parent: #5bde44b.patch.diff
in: master

5 files changed

modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -2351,6 +2351,11 @@
 	/// Is the collection a foreign one?
 	fn is_foreign(&self) -> bool;
 
+	/// Does the token have children?
+	fn token_has_children(&self, _token: TokenId) -> bool {
+		false
+	}
+
 	/// Create a collection's item using a transaction.
 	///
 	/// This function performs additional XCM-related checks before the actual creation.
modifiedpallets/foreign-assets/src/lib.rsdiffbeforeafterboth
--- a/pallets/foreign-assets/src/lib.rs
+++ b/pallets/foreign-assets/src/lib.rs
@@ -364,7 +364,7 @@
 
 	fn check_out(_dest: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}
 
-	fn deposit_asset(what: &MultiAsset, to: &MultiLocation, context: &XcmContext) -> XcmResult {
+	fn deposit_asset(what: &MultiAsset, to: &MultiLocation, _context: &XcmContext) -> XcmResult {
 		let collection_id = Self::multiasset_to_collection(what)?;
 		let dispatch =
 			T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;
@@ -397,7 +397,42 @@
 		from: &MultiLocation,
 		_maybe_context: Option<&XcmContext>,
 	) -> Result<staging_xcm_executor::Assets, XcmError> {
-		Err(XcmError::Unimplemented)
+		let from = T::LocationToAccountId::convert_location(from)
+			.ok_or(XcmExecutorError::AccountIdConversionFailed)?;
+
+		let collection_id = Self::multiasset_to_collection(what)?;
+		let dispatch =
+			T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;
+
+		let collection = dispatch.as_dyn();
+		let xcm_ext = collection.xcm_extensions().ok_or(XcmError::NoPermission)?;
+
+		match what.fun {
+			Fungibility::Fungible(amount) => xcm_ext
+				.burn_item(from, TokenId::default(), amount)
+				.map_err(|_| XcmError::FailedToTransactAsset("fungible item withdraw failed"))?,
+
+			Fungibility::NonFungible(asset_instance) => {
+				let token_id =
+					Self::asset_instance_to_token_id(xcm_ext, collection_id, &asset_instance)?
+						.ok_or(XcmError::AssetNotFound)?;
+
+				if xcm_ext.token_has_children(token_id) {
+					return Err(XcmError::Unimplemented);
+				}
+
+				let depositor = &from;
+				let to = Self::pallet_account();
+				let amount = 1;
+				xcm_ext
+					.transfer_item(depositor, &from, &to, token_id, amount, &ZeroBudget)
+					.map_err(|_| {
+						XcmError::FailedToTransactAsset("nonfungible item withdraw failed")
+					})?;
+			}
+		}
+
+		Ok(what.clone().into())
 	}
 
 	fn internal_transfer_asset(
@@ -406,7 +441,49 @@
 		to: &MultiLocation,
 		_context: &XcmContext,
 	) -> Result<staging_xcm_executor::Assets, XcmError> {
-		Err(XcmError::Unimplemented)
+		let collection_id = Self::multiasset_to_collection(what)?;
+
+		let dispatch =
+			T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;
+		let collection = dispatch.as_dyn();
+		let xcm_ext = collection.xcm_extensions().ok_or(XcmError::NoPermission)?;
+
+		let from = T::LocationToAccountId::convert_location(from)
+			.ok_or(XcmExecutorError::AccountIdConversionFailed)?;
+
+		let to = T::LocationToAccountId::convert_location(to)
+			.ok_or(XcmExecutorError::AccountIdConversionFailed)?;
+
+		let depositor = &from;
+
+		match what.fun {
+			Fungibility::Fungible(amount) => xcm_ext
+				.transfer_item(
+					depositor,
+					&from,
+					&to,
+					TokenId::default(),
+					amount,
+					&ZeroBudget,
+				)
+				.map_err(|_| XcmError::FailedToTransactAsset("fungible item transfer failed"))?,
+
+			Fungibility::NonFungible(asset_instance) => {
+				let token_id =
+					Self::asset_instance_to_token_id(xcm_ext, collection_id, &asset_instance)?
+						.ok_or(XcmError::AssetNotFound)?;
+
+				let amount = 1;
+
+				xcm_ext
+					.transfer_item(depositor, &from, &to, token_id, amount, &ZeroBudget)
+					.map_err(|_| {
+						XcmError::FailedToTransactAsset("nonfungible item transfer failed")
+					})?;
+			}
+		}
+
+		Ok(what.clone().into())
 	}
 }
 
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -95,9 +95,8 @@
 use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
 use sp_std::{collections::btree_map::BTreeMap, vec::Vec};
 use up_data_structs::{
-	budget::{Budget, ZeroBudget},
-	mapping::TokenAddressMapping,
-	AccessMode, CollectionId, CreateCollectionData, Property, PropertyKey, TokenId,
+	budget::Budget, mapping::TokenAddressMapping, AccessMode, CollectionId, Property, PropertyKey,
+	TokenId,
 };
 use weights::WeightInfo;
 
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -576,6 +576,10 @@
 		self.flags.foreign
 	}
 
+	fn token_has_children(&self, token: TokenId) -> bool {
+		<Pallet<T>>::token_has_children(self.id, token)
+	}
+
 	fn create_item_internal(
 		&self,
 		depositor: &<T>::CrossAccountId,
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
117use sp_std::{collections::btree_map::BTreeMap, vec, vec::Vec};117use sp_std::{collections::btree_map::BTreeMap, vec, vec::Vec};
118use up_data_structs::{118use up_data_structs::{
119 budget::Budget, mapping::TokenAddressMapping, AccessMode, AuxPropertyValue, CollectionId,119 budget::Budget, mapping::TokenAddressMapping, AccessMode, AuxPropertyValue, CollectionId,
120 CreateCollectionData, CreateNftExData, CustomDataLimit, PropertiesPermissionMap, Property,120 CreateNftExData, CustomDataLimit, PropertiesPermissionMap, Property, PropertyKey,
121 PropertyKey, PropertyKeyPermission, PropertyScope, PropertyValue, TokenChild, TokenId,121 PropertyKeyPermission, PropertyScope, PropertyValue, TokenChild, TokenId,
122 TokenProperties as TokenPropertiesT,122 TokenProperties as TokenPropertiesT,
123};123};