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
2351 /// Is the collection a foreign one?2351 /// Is the collection a foreign one?
2352 fn is_foreign(&self) -> bool;2352 fn is_foreign(&self) -> bool;
2353
2354 /// Does the token have children?
2355 fn token_has_children(&self, _token: TokenId) -> bool {
2356 false
2357 }
23532358
2354 /// Create a collection's item using a transaction.2359 /// Create a collection's item using a transaction.
2355 ///2360 ///
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
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -117,8 +117,8 @@
 use sp_std::{collections::btree_map::BTreeMap, vec, vec::Vec};
 use up_data_structs::{
 	budget::Budget, mapping::TokenAddressMapping, AccessMode, AuxPropertyValue, CollectionId,
-	CreateCollectionData, CreateNftExData, CustomDataLimit, PropertiesPermissionMap, Property,
-	PropertyKey, PropertyKeyPermission, PropertyScope, PropertyValue, TokenChild, TokenId,
+	CreateNftExData, CustomDataLimit, PropertiesPermissionMap, Property, PropertyKey,
+	PropertyKeyPermission, PropertyScope, PropertyValue, TokenChild, TokenId,
 	TokenProperties as TokenPropertiesT,
 };
 use weights::WeightInfo;