git.delta.rocks / unique-network / refs/commits / 00b9fd625e6d

difftreelog

feat initial rmrk send impl

Daniel Shiposha2022-06-03parent: #70623cc.patch.diff
in: master

10 files changed

modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -1298,6 +1298,7 @@
 		spender: T::CrossAccountId,
 		token: TokenId,
 		amount: u128,
+		nesting_budget: &dyn Budget,
 	) -> DispatchResultWithPostInfo;
 	fn transfer_from(
 		&self,
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -226,6 +226,7 @@
 		spender: T::CrossAccountId,
 		token: TokenId,
 		amount: u128,
+		_nesting_budget: &dyn Budget,
 	) -> DispatchResultWithPostInfo {
 		ensure!(
 			token == TokenId::default(),
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -308,14 +308,15 @@
 		spender: T::CrossAccountId,
 		token: TokenId,
 		amount: u128,
+		nesting_budget: &dyn Budget,
 	) -> DispatchResultWithPostInfo {
 		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
 
 		with_weight(
 			if amount == 1 {
-				<Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))
+				<Pallet<T>>::set_allowance(self, &sender, token, Some(&spender), nesting_budget)
 			} else {
-				<Pallet<T>>::set_allowance(self, &sender, token, None)
+				<Pallet<T>>::set_allowance(self, &sender, token, None, nesting_budget)
 			},
 			<CommonWeights<T>>::approve(),
 		)
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -269,8 +269,11 @@
 		let caller = T::CrossAccountId::from_eth(caller);
 		let approved = T::CrossAccountId::from_eth(approved);
 		let token = token_id.try_into()?;
+		let budget = self
+			.recorder
+			.weight_calls_budget(<StructureWeight<T>>::find_parent());
 
-		<Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))
+		<Pallet<T>>::set_allowance(self, &caller, token, Some(&approved), &budget)
 			.map_err(dispatch_to_evm::<T>)?;
 		Ok(())
 	}
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -878,6 +878,7 @@
 		sender: &T::CrossAccountId,
 		token: TokenId,
 		spender: Option<&T::CrossAccountId>,
+		nesting_budget: &dyn Budget,
 	) -> DispatchResult {
 		if collection.permissions.access() == AccessMode::AllowList {
 			collection.check_allowlist(sender)?;
@@ -889,9 +890,16 @@
 		if let Some(spender) = spender {
 			<PalletCommon<T>>::ensure_correct_receiver(spender)?;
 		}
-		let token_data =
-			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
-		if &token_data.owner != sender {
+
+		let is_owned = <PalletStructure<T>>::check_indirectly_owned(
+			sender.clone(),
+			collection.id,
+			token,
+			None,
+			nesting_budget
+		)?;
+
+		if !is_owned {
 			ensure!(
 				collection.ignores_owned_amount(sender),
 				<CommonError<T>>::CantApproveMoreThanOwned
@@ -918,6 +926,9 @@
 			// `from`, `to` checked in [`transfer`]
 			collection.check_allowlist(spender)?;
 		}
+		if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
+			return Ok(());
+		}
 		if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {
 			// TODO: should collection owner be allowed to perform this transfer?
 			ensure!(
@@ -930,9 +941,6 @@
 				)?,
 				<CommonError<T>>::ApprovedValueTooLow,
 			);
-			return Ok(());
-		}
-		if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
 			return Ok(());
 		}
 		ensure!(
modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -20,7 +20,7 @@
 use frame_system::{pallet_prelude::*, ensure_signed};
 use sp_runtime::{DispatchError, Permill, traits::StaticLookup};
 use sp_std::vec::Vec;
-use up_data_structs::*;
+use up_data_structs::{*, mapping::TokenAddressMapping};
 use pallet_common::{
 	Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
 };
@@ -39,6 +39,8 @@
 
 use RmrkProperty::*;
 
+const NESTING_BUDGET: u32 = 5;
+
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
@@ -56,10 +58,13 @@
 	pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn collection_index_map)]
-	pub type CollectionIndexMap<T: Config> =
+	pub type UniqueCollectionId<T: Config> =
 		StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;
 
+	#[pallet::storage]
+	pub type RmrkInernalCollectionId<T: Config> =
+		StorageMap<_, Twox64Concat, CollectionId, RmrkCollectionId, ValueQuery>;
+
 	#[pallet::pallet]
 	#[pallet::generate_store(pub(super) trait Store)]
 	pub struct Pallet<T>(_);
@@ -151,10 +156,12 @@
 					.into_inner()
 					.try_into()
 					.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
+				permissions: Some(CollectionPermissions {
+					nesting: Some(NestingRule::Owner),
+					..Default::default()
+				}),
 				..Default::default()
 			};
-
-			<CollectionIndex<T>>::mutate(|n| *n += 1);
 
 			let unique_collection_id = Self::init_collection(
 				T::CrossAccountId::from_sub(sender.clone()),
@@ -167,7 +174,10 @@
 			)?;
 			let rmrk_collection_id = <CollectionIndex<T>>::get();
 
-			<CollectionIndexMap<T>>::insert(rmrk_collection_id, unique_collection_id);
+			<UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);
+			<RmrkInernalCollectionId<T>>::insert(unique_collection_id, rmrk_collection_id);
+
+			<CollectionIndex<T>>::mutate(|n| *n += 1);
 
 			Self::deposit_event(Event::CollectionCreated {
 				issuer: sender,
@@ -356,6 +366,81 @@
 
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
+		pub fn send(
+			origin: OriginFor<T>,
+			rmrk_collection_id: RmrkCollectionId,
+			rmrk_nft_id: RmrkNftId,
+			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,
+		) -> DispatchResult {
+			let sender = ensure_signed(origin.clone())?;
+			let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+
+			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
+			let nft_id = rmrk_nft_id.into();
+
+			let token_data = <TokenData<T>>::get((collection_id, nft_id))
+				.ok_or(<Error<T>>::NoAvailableNftId)?;
+
+			let from = token_data.owner;
+
+			let collection = Self::get_typed_nft_collection(
+				collection_id,
+				misc::CollectionType::Regular,
+			)?;
+
+			let budget = budget::Value::new(NESTING_BUDGET);
+
+			let target_owner;
+
+			match new_owner {
+				RmrkAccountIdOrCollectionNftTuple::AccountId(account_id) => {
+					target_owner = T::CrossAccountId::from_sub(account_id);
+				},
+				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(target_collection_id, target_nft_id) => {
+					let target_collection_id = Self::unique_collection_id(target_collection_id)?;
+
+					target_owner = T::CrossTokenAddressMapping::token_to_address(
+						target_collection_id,
+						target_nft_id.into(),
+					);
+
+					let spender = <PalletStructure<T>>::get_indirect_owner(
+						target_collection_id,
+						target_nft_id.into(),
+						Some((collection_id, nft_id)),
+						&budget,
+					)?;
+
+					let is_approval_required = cross_sender != spender;
+
+					if is_approval_required {
+						<PalletNft<T>>::set_allowance(
+							&collection,
+							&cross_sender,
+							nft_id,
+							Some(&spender),
+							&budget
+						).map_err(Self::map_common_err_to_proxy)?;
+
+						return Ok(());
+					}
+				}
+			}
+
+			<PalletNft<T>>::transfer_from(
+				&collection,
+				&cross_sender,
+				&from,
+				&target_owner,
+				nft_id,
+				&budget
+			).map_err(Self::map_common_err_to_proxy)?;
+
+			Ok(())
+		}
+
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[transactional]
 		pub fn set_property(
 			origin: OriginFor<T>,
 			#[pallet::compact] rmrk_collection_id: RmrkCollectionId,
@@ -367,12 +452,13 @@
 			let sender = T::CrossAccountId::from_sub(sender);
 
 			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
+			let budget = budget::Value::new(NESTING_BUDGET);
 
 			match maybe_nft_id {
 				Some(nft_id) => {
 					let token_id: TokenId = nft_id.into();
 
-					Self::ensure_nft_owner(collection_id, token_id, &sender)?;
+					Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;
 					Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
 
 					<PalletNft<T>>::set_scoped_token_property(
@@ -607,7 +693,7 @@
 			owner: owner.clone(),
 		};
 
-		let budget = budget::Value::new(2);
+		let budget = budget::Value::new(NESTING_BUDGET);
 
 		<PalletNft<T>>::create_item(collection, sender, data, &budget)?;
 
@@ -651,14 +737,8 @@
 		//ensure!(!Pallet::<T>::is_locked(collection_id, nft_id), pallet_uniques::Error::<T>::Locked);
 
 		let sender = T::CrossAccountId::from_sub(sender);
-		let budget = budget::Value::new(10);
-		let pending = !<PalletStructure<T>>::check_indirectly_owned(
-			sender.clone(),
-			collection_id,
-			token_id,
-			None,
-			&budget,
-		)?;
+		let budget = budget::Value::new(NESTING_BUDGET);
+		let pending = Self::ensure_nft_owner(collection_id, token_id, &sender, &budget).is_err();
 
 		let resource_collection_id: CollectionId =
 			Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;
@@ -757,7 +837,14 @@
 	pub fn unique_collection_id(
 		rmrk_collection_id: RmrkCollectionId,
 	) -> Result<CollectionId, DispatchError> {
-		<CollectionIndexMap<T>>::try_get(rmrk_collection_id)
+		<UniqueCollectionId<T>>::try_get(rmrk_collection_id)
+			.map_err(|_| <Error<T>>::CollectionUnknown.into())
+	}
+
+	pub fn rmrk_collection_id(
+		unique_collection_id: CollectionId
+	) -> Result<RmrkCollectionId, DispatchError> {
+		<RmrkInernalCollectionId<T>>::try_get(unique_collection_id)
 			.map_err(|_| <Error<T>>::CollectionUnknown.into())
 	}
 
@@ -873,12 +960,18 @@
 		collection_id: CollectionId,
 		token_id: TokenId,
 		possible_owner: &T::CrossAccountId,
+		nesting_budget: &dyn budget::Budget
 	) -> DispatchResult {
-		let token_data =
-			<TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;
+		let is_owned = <PalletStructure<T>>::check_indirectly_owned(
+			possible_owner.clone(),
+			collection_id,
+			token_id,
+			None,
+			nesting_budget,
+		)?;
 
 		ensure!(
-			token_data.owner == *possible_owner,
+			is_owned,
 			<Error<T>>::NoPermission
 		);
 
@@ -965,7 +1058,8 @@
 				NoPermission => NoPermission,
 				CollectionTokenLimitExceeded => CollectionFullOrLocked,
 				PublicMintingNotAllowed => NoPermission,
-				TokenNotFound => NoAvailableNftId
+				TokenNotFound => NoAvailableNftId,
+				ApprovedValueTooLow => NoPermission
 			}
 		}
 	}
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -254,6 +254,7 @@
 		spender: T::CrossAccountId,
 		token: TokenId,
 		amount: u128,
+		_nesting_budget: &dyn Budget,
 	) -> DispatchResultWithPostInfo {
 		with_weight(
 			<Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),
modifiedpallets/structure/src/lib.rsdiffbeforeafterboth
--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -149,19 +149,12 @@
 		})
 	}
 
-	/// Check if token indirectly owned by specified user
-	pub fn check_indirectly_owned(
-		user: T::CrossAccountId,
+	pub fn get_indirect_owner(
 		collection: CollectionId,
 		token: TokenId,
 		for_nest: Option<(CollectionId, TokenId)>,
 		budget: &dyn Budget,
-	) -> Result<bool, DispatchError> {
-		let target_parent = match T::CrossTokenAddressMapping::address_to_token(&user) {
-			Some((collection, token)) => Self::find_topmost_owner(collection, token, budget)?,
-			None => user,
-		};
-
+	) -> Result<T::CrossAccountId, DispatchError> {
 		// Tried to nest token in itself
 		if Some((collection, token)) == for_nest {
 			return Err(<Error<T>>::OuroborosDetected.into());
@@ -173,10 +166,8 @@
 				Parent::Token(collection, token) if Some((collection, token)) == for_nest => {
 					return Err(<Error<T>>::OuroborosDetected.into())
 				}
-				// Found needed parent, token is indirecty owned
-				Parent::User(user) if user == target_parent => return Ok(true),
 				// Token is owned by other user
-				Parent::User(_) => return Ok(false),
+				Parent::User(user) => return Ok(user),
 				Parent::TokenNotFound => return Err(<Error<T>>::TokenNotFound.into()),
 				// Continue parent chain
 				Parent::Token(_, _) => {}
@@ -199,6 +190,27 @@
 		dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)
 	}
 
+	/// Check if token indirectly owned by specified user
+	pub fn check_indirectly_owned(
+		user: T::CrossAccountId,
+		collection: CollectionId,
+		token: TokenId,
+		for_nest: Option<(CollectionId, TokenId)>,
+		budget: &dyn Budget,
+	) -> Result<bool, DispatchError> {
+		let target_parent = match T::CrossTokenAddressMapping::address_to_token(&user) {
+			Some((collection, token)) => Self::find_topmost_owner(collection, token, budget)?,
+			None => user,
+		};
+
+		Self::get_indirect_owner(
+			collection,
+			token,
+			for_nest,
+			budget
+		).map(|indirect_owner| indirect_owner == target_parent)
+	}
+
 	pub fn check_nesting(
 		from: T::CrossAccountId,
 		under: &T::CrossAccountId,
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -815,8 +815,9 @@
 		#[transactional]
 		pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let budget = budget::Value::new(NESTING_BUDGET);
 
-			dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
+			dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount, &budget))
 		}
 
 		/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
before · runtime/common/src/runtime_apis.rs
1#[macro_export]2macro_rules! impl_common_runtime_apis {3    (4        $(5            #![custom_apis]67            $($custom_apis:tt)+8        )?9    ) => {10        impl_runtime_apis! {11            $($($custom_apis)+)?1213            impl up_rpc::UniqueApi<Block, CrossAccountId, AccountId> for Runtime {14                fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>, DispatchError> {15                    dispatch_unique_runtime!(collection.account_tokens(account))16                }17                fn collection_tokens(collection: CollectionId) -> Result<Vec<TokenId>, DispatchError> {18                    dispatch_unique_runtime!(collection.collection_tokens())19                }20                fn token_exists(collection: CollectionId, token: TokenId) -> Result<bool, DispatchError> {21                    dispatch_unique_runtime!(collection.token_exists(token))22                }2324                fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {25                    dispatch_unique_runtime!(collection.token_owner(token))26                }27                fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {28                    let budget = up_data_structs::budget::Value::new(10);2930                    Ok(Some(<pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)?))31                }32                fn token_children(collection: CollectionId, token: TokenId) -> Result<Vec<TokenChild>, DispatchError> {33                    Ok(<pallet_nonfungible::Pallet<Runtime>>::token_children_ids(collection, token))34                }35                fn collection_properties(36                    collection: CollectionId,37                    keys: Option<Vec<Vec<u8>>>38                ) -> Result<Vec<Property>, DispatchError> {39                    let keys = keys.map(40                        |keys| Common::bytes_keys_to_property_keys(keys)41                    ).transpose()?;4243                    Common::filter_collection_properties(collection, keys)44                }4546                fn token_properties(47                    collection: CollectionId,48                    token_id: TokenId,49                    keys: Option<Vec<Vec<u8>>>50                ) -> Result<Vec<Property>, DispatchError> {51                    let keys = keys.map(52                        |keys| Common::bytes_keys_to_property_keys(keys)53                    ).transpose()?;5455                    dispatch_unique_runtime!(collection.token_properties(token_id, keys))56                }5758                fn property_permissions(59                    collection: CollectionId,60                    keys: Option<Vec<Vec<u8>>>61                ) -> Result<Vec<PropertyKeyPermission>, DispatchError> {62                    let keys = keys.map(63                        |keys| Common::bytes_keys_to_property_keys(keys)64                    ).transpose()?;6566                    Common::filter_property_permissions(collection, keys)67                }6869                fn token_data(70                    collection: CollectionId,71                    token_id: TokenId,72                    keys: Option<Vec<Vec<u8>>>73                ) -> Result<TokenData<CrossAccountId>, DispatchError> {74                    let token_data = TokenData {75                        properties: Self::token_properties(collection, token_id, keys)?,76                        owner: Self::token_owner(collection, token_id)?77                    };7879                    Ok(token_data)80                }8182                fn total_supply(collection: CollectionId) -> Result<u32, DispatchError> {83                    dispatch_unique_runtime!(collection.total_supply())84                }85                fn account_balance(collection: CollectionId, account: CrossAccountId) -> Result<u32, DispatchError> {86                    dispatch_unique_runtime!(collection.account_balance(account))87                }88                fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<u128, DispatchError> {89                    dispatch_unique_runtime!(collection.balance(account, token))90                }91                fn allowance(92                    collection: CollectionId,93                    sender: CrossAccountId,94                    spender: CrossAccountId,95                    token: TokenId,96                ) -> Result<u128, DispatchError> {97                    dispatch_unique_runtime!(collection.allowance(sender, spender, token))98                }99100                fn adminlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {101                    Ok(<pallet_common::Pallet<Runtime>>::adminlist(collection))102                }103                fn allowlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {104                    Ok(<pallet_common::Pallet<Runtime>>::allowlist(collection))105                }106                fn allowed(collection: CollectionId, user: CrossAccountId) -> Result<bool, DispatchError> {107                    Ok(<pallet_common::Pallet<Runtime>>::allowed(collection, user))108                }109                fn last_token_id(collection: CollectionId) -> Result<TokenId, DispatchError> {110                    dispatch_unique_runtime!(collection.last_token_id())111                }112                fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>, DispatchError> {113                    Ok(<pallet_common::Pallet<Runtime>>::rpc_collection(collection))114                }115                fn collection_stats() -> Result<CollectionStats, DispatchError> {116                    Ok(<pallet_common::Pallet<Runtime>>::collection_stats())117                }118                fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>, DispatchError> {119                    Ok(<$crate::sponsoring::UniqueSponsorshipPredict<Runtime> as120                            $crate::sponsoring::SponsorshipPredict<Runtime>>::predict(121                        collection,122                        account,123                        token))124                }125126                fn effective_collection_limits(collection: CollectionId) -> Result<Option<CollectionLimits>, DispatchError> {127                    Ok(<pallet_common::Pallet<Runtime>>::effective_collection_limits(collection))128                }129            }130131            impl rmrk_rpc::RmrkApi<132                Block,133                AccountId,134                RmrkCollectionInfo<AccountId>,135                RmrkInstanceInfo<AccountId>,136                RmrkResourceInfo,137                RmrkPropertyInfo,138                RmrkBaseInfo<AccountId>,139                RmrkPartType,140                RmrkTheme141            > for Runtime {142                fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {143                    Ok(RmrkCore::last_collection_idx())144                }145146                fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {147                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};148                    use pallet_common::CommonCollectionOperations;149150                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;151                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {152                        Ok(c) => c,153                        Err(_) => return Ok(None),154                    };155156                    let nfts_count = collection.total_supply();157158                    Ok(Some(RmrkCollectionInfo {159                        issuer: collection.owner.clone(),160                        metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?,161                        max: collection.limits.token_limit,162                        symbol: RmrkCore::rebind(&collection.token_prefix)?,163                        nfts_count164                    }))165                }166167                fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {168                    use up_data_structs::mapping::TokenAddressMapping;169                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};170                    use pallet_common::CommonCollectionOperations;171172                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;173                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {174                        Ok(c) => c,175                        Err(_) => return Ok(None),176                    };177178                    let nft_id = TokenId(nft_by_id);179                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); }180181                    let owner = match collection.token_owner(nft_id) {182                        Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {183                            Some((col, tok)) => RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(col.0, tok.0),184                            None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())185                        },186                        None => return Ok(None)187                    };188189                    let allowance = pallet_nonfungible::Allowance::<Runtime>::get((collection_id, nft_id));190191                    Ok(Some(RmrkInstanceInfo {192                        owner: owner,193                        royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,194                        metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,195                        equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,196                        pending: allowance.is_some(),197                    }))198                }199200                fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {201                    use pallet_proxy_rmrk_core::misc::CollectionType;202                    use pallet_common::CommonCollectionOperations;203204                    let cross_account_id = CrossAccountId::from_sub(account_id);205                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;206                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {207                        Ok(c) => c,208                        Err(_) => return Ok(Vec::new()),209                    };210211                    Ok(212                        collection.account_tokens(cross_account_id)213                            .into_iter()214                            .map(|token| token.0)215                            .collect()216                    )217                }218219                fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {220                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;221                    let nft_id = TokenId(nft_id);222                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }223224                    Ok(225                        pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))226                            .filter_map(|(child_id, is_child)|227                                match is_child {228                                    true => Some(RmrkNftChild {229                                        collection_id: child_id.0.0,230                                        nft_id: child_id.1.0,231                                    }),232                                    false => None,233                                }234                            ).collect()235                    )236                }237238                fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {239                    use pallet_proxy_rmrk_core::misc::CollectionType;240241                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;242                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {243                        return Ok(Vec::new());244                    }245246                    let properties = RmrkCore::filter_user_properties(247                        collection_id,248                        /* token_id = */ None,249                        filter_keys,250                        |key, value| RmrkPropertyInfo {251                            key,252                            value253                        }254                    )?;255256                    Ok(properties)257                }258259                fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {260                    use pallet_proxy_rmrk_core::misc::NftType;261262                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;263                    let token_id = TokenId(nft_id);264265                    if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {266                        return Ok(Vec::new());267                    }268269		            let properties = RmrkCore::filter_user_properties(270                        collection_id,271                        Some(token_id),272                        filter_keys,273                        |key, value| RmrkPropertyInfo {274                            key,275                            value276                        }277                    )?;278279                    Ok(properties)280                }281282                fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {283                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};284                    use pallet_common::CommonCollectionOperations;285286                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;287                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }288289                    let nft_id = TokenId(nft_id);290                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }291292                    let res_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;293                    let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?;294295                    let resources = resource_collection296                        .collection_tokens()297                        .iter()298                        .filter_map(|(res_id)| Some(RmrkResourceInfo {299                            id: res_id.0,300                            pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap(),301                            pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap(),302                            resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap() {303                                ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {304                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),305                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),306                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),307                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),308                                }),309                                ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {310                                    parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).unwrap(),311                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),312                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),313                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),314                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),315                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),316                                }),317                                ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {318                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),319                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),320                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),321                                    slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).unwrap(),322                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),323                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),324                                }),325                            },326                        }))327                        .collect();328329                    Ok(resources)330                }331332                fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {333                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};334335                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;336                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }337338                    let nft_id = TokenId(nft_id);339                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }340341                    /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)342                        .unwrap();343                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }344345                    let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))346                        .filter_map(|(resource_id, properties)| Some((347                            resource_id, // ResourceId property348                            RmrkCore::get_nft_property_decoded(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap(),349                        )))350                        .collect()351                        .sort_by_key(|(_, index)| *index)352                        .into_iter().map(|(resource_id, _)| resource_id)*/353                    let priorities = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?;354355                    Ok(priorities)356                }357358                fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {359                    use pallet_proxy_rmrk_core::{360                        RmrkProperty, misc::{CollectionType},361                    };362363                    let collection_id = RmrkCore::unique_collection_id(base_id)?;364                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {365                        Ok(c) => c,366                        Err(_) => return Ok(None),367                    };368369                    Ok(Some(RmrkBaseInfo {370                        issuer: collection.owner.clone(),371                        base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?,372                        symbol: RmrkCore::rebind(&collection.token_prefix)?,373                    }))374                }375376                fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {377                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};378                    use pallet_common::CommonCollectionOperations;379380                    let collection_id = RmrkCore::unique_collection_id(base_id)?;381                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {382                        Ok(c) => c,383                        Err(_) => return Ok(Vec::new()),384                    };385386387                    let parts = collection.collection_tokens()388                        .into_iter()389                        .filter_map(|token_id| {390                            let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?;391392                            match nft_type {393                                NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {394                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,395                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,396                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,397                                })),398                                NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {399                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,400                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,401                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,402                                    equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?,403                                })),404                                _ => None405                            }406                        })407                        .collect();408409                    Ok(parts)410                }411412                fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {413                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};414                    use pallet_common::CommonCollectionOperations;415416                    let collection_id = RmrkCore::unique_collection_id(base_id)?;417                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {418                        Ok(c) => c,419                        Err(_) => return Ok(Vec::new()),420                    };421422423                    let theme_names = collection.collection_tokens()424                        .iter()425                        .filter_map(|token_id| {426                            let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();427428                            match nft_type {429                                Theme => Some(430                                    RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).unwrap()431                                ),432                                _ => None433                            }434                        })435                        .collect();436437                    Ok(theme_names)438                }439440                fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {441                    use pallet_proxy_rmrk_core::{442                        RmrkProperty,443                        misc::{CollectionType, NftType}444                    };445                    use pallet_common::CommonCollectionOperations;446447                    let collection_id = RmrkCore::unique_collection_id(base_id)?;448                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {449                        Ok(c) => c,450                        Err(_) => return Ok(None),451                    };452453                    let theme_info = collection.collection_tokens()454                        .into_iter()455                        .find_map(|token_id| {456                            RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;457458                            let name: RmrkString = RmrkCore::get_nft_property_decoded(459                                collection_id, token_id, RmrkProperty::ThemeName460                            ).ok()?;461462                            if name == theme_name {463                                Some((name, token_id))464                            } else {465                                None466                            }467                        });468469                    let (name, theme_id) = match theme_info {470                        Some((name, theme_id)) => (name, theme_id),471                        None => return Ok(None)472                    };473474                    let properties = RmrkCore::filter_user_properties(475                        collection_id,476                        Some(theme_id),477                        filter_keys,478                        |key, value| RmrkThemeProperty {479                            key,480                            value481                        }482                    )?;483484                    let inherit = RmrkCore::get_nft_property_decoded(485                        collection_id,486                        theme_id,487                        RmrkProperty::ThemeInherit488                    )?;489490                    let theme = RmrkTheme {491                        name,492                        properties,493                        inherit,494                    };495496                    Ok(Some(theme))497                }498            }499500            impl sp_api::Core<Block> for Runtime {501                fn version() -> RuntimeVersion {502                    VERSION503                }504505                fn execute_block(block: Block) {506                    Executive::execute_block(block)507                }508509                fn initialize_block(header: &<Block as BlockT>::Header) {510                    Executive::initialize_block(header)511                }512            }513514            impl sp_api::Metadata<Block> for Runtime {515                fn metadata() -> OpaqueMetadata {516                    OpaqueMetadata::new(Runtime::metadata().into())517                }518            }519520            impl sp_block_builder::BlockBuilder<Block> for Runtime {521                fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {522                    Executive::apply_extrinsic(extrinsic)523                }524525                fn finalize_block() -> <Block as BlockT>::Header {526                    Executive::finalize_block()527                }528529                fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {530                    data.create_extrinsics()531                }532533                fn check_inherents(534                    block: Block,535                    data: sp_inherents::InherentData,536                ) -> sp_inherents::CheckInherentsResult {537                    data.check_extrinsics(&block)538                }539540                // fn random_seed() -> <Block as BlockT>::Hash {541                //     RandomnessCollectiveFlip::random_seed().0542                // }543            }544545            impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {546                fn validate_transaction(547                    source: TransactionSource,548                    tx: <Block as BlockT>::Extrinsic,549                    hash: <Block as BlockT>::Hash,550                ) -> TransactionValidity {551                    Executive::validate_transaction(source, tx, hash)552                }553            }554555            impl sp_offchain::OffchainWorkerApi<Block> for Runtime {556                fn offchain_worker(header: &<Block as BlockT>::Header) {557                    Executive::offchain_worker(header)558                }559            }560561            impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {562                fn chain_id() -> u64 {563                    <Runtime as pallet_evm::Config>::ChainId::get()564                }565566                fn account_basic(address: H160) -> EVMAccount {567                    let (account, _) = EVM::account_basic(&address);568                    account569                }570571                fn gas_price() -> U256 {572                    let (price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();573                    price574                }575576                fn account_code_at(address: H160) -> Vec<u8> {577                    EVM::account_codes(address)578                }579580                fn author() -> H160 {581                    <pallet_evm::Pallet<Runtime>>::find_author()582                }583584                fn storage_at(address: H160, index: U256) -> H256 {585                    let mut tmp = [0u8; 32];586                    index.to_big_endian(&mut tmp);587                    EVM::account_storages(address, H256::from_slice(&tmp[..]))588                }589590                #[allow(clippy::redundant_closure)]591                fn call(592                    from: H160,593                    to: H160,594                    data: Vec<u8>,595                    value: U256,596                    gas_limit: U256,597                    max_fee_per_gas: Option<U256>,598                    max_priority_fee_per_gas: Option<U256>,599                    nonce: Option<U256>,600                    estimate: bool,601                    access_list: Option<Vec<(H160, Vec<H256>)>>,602                ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {603                    let config = if estimate {604                        let mut config = <Runtime as pallet_evm::Config>::config().clone();605                        config.estimate = true;606                        Some(config)607                    } else {608                        None609                    };610611                    let is_transactional = false;612                    <Runtime as pallet_evm::Config>::Runner::call(613                        CrossAccountId::from_eth(from),614                        to,615                        data,616                        value,617                        gas_limit.low_u64(),618                        max_fee_per_gas,619                        max_priority_fee_per_gas,620                        nonce,621                        access_list.unwrap_or_default(),622                        is_transactional,623                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),624                    ).map_err(|err| err.error.into())625                }626627                #[allow(clippy::redundant_closure)]628                fn create(629                    from: H160,630                    data: Vec<u8>,631                    value: U256,632                    gas_limit: U256,633                    max_fee_per_gas: Option<U256>,634                    max_priority_fee_per_gas: Option<U256>,635                    nonce: Option<U256>,636                    estimate: bool,637                    access_list: Option<Vec<(H160, Vec<H256>)>>,638                ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {639                    let config = if estimate {640                        let mut config = <Runtime as pallet_evm::Config>::config().clone();641                        config.estimate = true;642                        Some(config)643                    } else {644                        None645                    };646647                    let is_transactional = false;648                    <Runtime as pallet_evm::Config>::Runner::create(649                        CrossAccountId::from_eth(from),650                        data,651                        value,652                        gas_limit.low_u64(),653                        max_fee_per_gas,654                        max_priority_fee_per_gas,655                        nonce,656                        access_list.unwrap_or_default(),657                        is_transactional,658                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),659                    ).map_err(|err| err.error.into())660                }661662                fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {663                    Ethereum::current_transaction_statuses()664                }665666                fn current_block() -> Option<pallet_ethereum::Block> {667                    Ethereum::current_block()668                }669670                fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {671                    Ethereum::current_receipts()672                }673674                fn current_all() -> (675                    Option<pallet_ethereum::Block>,676                    Option<Vec<pallet_ethereum::Receipt>>,677                    Option<Vec<TransactionStatus>>678                ) {679                    (680                        Ethereum::current_block(),681                        Ethereum::current_receipts(),682                        Ethereum::current_transaction_statuses()683                    )684                }685686                fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {687                    xts.into_iter().filter_map(|xt| match xt.0.function {688                        Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),689                        _ => None690                    }).collect()691                }692693                fn elasticity() -> Option<Permill> {694                    None695                }696            }697698            impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {699                fn convert_transaction(transaction: pallet_ethereum::Transaction) -> <Block as BlockT>::Extrinsic  {700                    UncheckedExtrinsic::new_unsigned(701                        pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),702                    )703                }704            }705706            impl sp_session::SessionKeys<Block> for Runtime {707                fn decode_session_keys(708                    encoded: Vec<u8>,709                ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {710                    SessionKeys::decode_into_raw_public_keys(&encoded)711                }712713                fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {714                    SessionKeys::generate(seed)715                }716            }717718            impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {719                fn slot_duration() -> sp_consensus_aura::SlotDuration {720                    sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())721                }722723                fn authorities() -> Vec<AuraId> {724                    Aura::authorities().to_vec()725                }726            }727728            impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {729                fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {730                    ParachainSystem::collect_collation_info(header)731                }732            }733734            impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {735                fn account_nonce(account: AccountId) -> Index {736                    System::account_nonce(account)737                }738            }739740            impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {741                fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {742                    TransactionPayment::query_info(uxt, len)743                }744                fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {745                    TransactionPayment::query_fee_details(uxt, len)746                }747            }748749            /*750            impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>751                for Runtime752            {753                fn call(754                    origin: AccountId,755                    dest: AccountId,756                    value: Balance,757                    gas_limit: u64,758                    input_data: Vec<u8>,759                ) -> pallet_contracts_primitives::ContractExecResult {760                    Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)761                }762763                fn instantiate(764                    origin: AccountId,765                    endowment: Balance,766                    gas_limit: u64,767                    code: pallet_contracts_primitives::Code<Hash>,768                    data: Vec<u8>,769                    salt: Vec<u8>,770                ) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>771                {772                    Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)773                }774775                fn get_storage(776                    address: AccountId,777                    key: [u8; 32],778                ) -> pallet_contracts_primitives::GetStorageResult {779                    Contracts::get_storage(address, key)780                }781782                fn rent_projection(783                    address: AccountId,784                ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {785                    Contracts::rent_projection(address)786                }787            }788            */789790            #[cfg(feature = "runtime-benchmarks")]791            impl frame_benchmarking::Benchmark<Block> for Runtime {792                fn benchmark_metadata(extra: bool) -> (793                    Vec<frame_benchmarking::BenchmarkList>,794                    Vec<frame_support::traits::StorageInfo>,795                ) {796                    use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};797                    use frame_support::traits::StorageInfoTrait;798799                    let mut list = Vec::<BenchmarkList>::new();800801                    list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);802                    list_benchmark!(list, extra, pallet_common, Common);803                    list_benchmark!(list, extra, pallet_unique, Unique);804                    list_benchmark!(list, extra, pallet_structure, Structure);805                    list_benchmark!(list, extra, pallet_inflation, Inflation);806                    list_benchmark!(list, extra, pallet_fungible, Fungible);807                    list_benchmark!(list, extra, pallet_refungible, Refungible);808                    list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);809                    // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);810811                    let storage_info = AllPalletsReversedWithSystemFirst::storage_info();812813                    return (list, storage_info)814                }815816                fn dispatch_benchmark(817                    config: frame_benchmarking::BenchmarkConfig818                ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {819                    use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};820821                    let allowlist: Vec<TrackedStorageKey> = vec![822                        // Total Issuance823                        hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),824825                        // Block Number826                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),827                        // Execution Phase828                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),829                        // Event Count830                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),831                        // System Events832                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),833834                        // Evm CurrentLogs835                        hex_literal::hex!("1da53b775b270400e7e61ed5cbc5a146547f210cec367e9af919603343b9cb56").to_vec().into(),836837                        // Transactional depth838                        hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a").to_vec().into(),839                    ];840841                    let mut batches = Vec::<BenchmarkBatch>::new();842                    let params = (&config, &allowlist);843844                    add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);845                    add_benchmark!(params, batches, pallet_common, Common);846                    add_benchmark!(params, batches, pallet_unique, Unique);847                    add_benchmark!(params, batches, pallet_structure, Structure);848                    add_benchmark!(params, batches, pallet_inflation, Inflation);849                    add_benchmark!(params, batches, pallet_fungible, Fungible);850                    add_benchmark!(params, batches, pallet_refungible, Refungible);851                    add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);852                    // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);853854                    if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }855                    Ok(batches)856                }857            }858859            #[cfg(feature = "try-runtime")]860            impl frame_try_runtime::TryRuntime<Block> for Runtime {861                fn on_runtime_upgrade() -> (Weight, Weight) {862                    log::info!("try-runtime::on_runtime_upgrade unique-chain.");863                    let weight = Executive::try_runtime_upgrade().unwrap();864                    (weight, RuntimeBlockWeights::get().max_block)865                }866867                fn execute_block_no_check(block: Block) -> Weight {868                    Executive::execute_block_no_check(block)869                }870            }871        }872    }873}
after · runtime/common/src/runtime_apis.rs
1#[macro_export]2macro_rules! impl_common_runtime_apis {3    (4        $(5            #![custom_apis]67            $($custom_apis:tt)+8        )?9    ) => {10        impl_runtime_apis! {11            $($($custom_apis)+)?1213            impl up_rpc::UniqueApi<Block, CrossAccountId, AccountId> for Runtime {14                fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>, DispatchError> {15                    dispatch_unique_runtime!(collection.account_tokens(account))16                }17                fn collection_tokens(collection: CollectionId) -> Result<Vec<TokenId>, DispatchError> {18                    dispatch_unique_runtime!(collection.collection_tokens())19                }20                fn token_exists(collection: CollectionId, token: TokenId) -> Result<bool, DispatchError> {21                    dispatch_unique_runtime!(collection.token_exists(token))22                }2324                fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {25                    dispatch_unique_runtime!(collection.token_owner(token))26                }27                fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {28                    let budget = up_data_structs::budget::Value::new(10);2930                    Ok(Some(<pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)?))31                }32                fn token_children(collection: CollectionId, token: TokenId) -> Result<Vec<TokenChild>, DispatchError> {33                    Ok(<pallet_nonfungible::Pallet<Runtime>>::token_children_ids(collection, token))34                }35                fn collection_properties(36                    collection: CollectionId,37                    keys: Option<Vec<Vec<u8>>>38                ) -> Result<Vec<Property>, DispatchError> {39                    let keys = keys.map(40                        |keys| Common::bytes_keys_to_property_keys(keys)41                    ).transpose()?;4243                    Common::filter_collection_properties(collection, keys)44                }4546                fn token_properties(47                    collection: CollectionId,48                    token_id: TokenId,49                    keys: Option<Vec<Vec<u8>>>50                ) -> Result<Vec<Property>, DispatchError> {51                    let keys = keys.map(52                        |keys| Common::bytes_keys_to_property_keys(keys)53                    ).transpose()?;5455                    dispatch_unique_runtime!(collection.token_properties(token_id, keys))56                }5758                fn property_permissions(59                    collection: CollectionId,60                    keys: Option<Vec<Vec<u8>>>61                ) -> Result<Vec<PropertyKeyPermission>, DispatchError> {62                    let keys = keys.map(63                        |keys| Common::bytes_keys_to_property_keys(keys)64                    ).transpose()?;6566                    Common::filter_property_permissions(collection, keys)67                }6869                fn token_data(70                    collection: CollectionId,71                    token_id: TokenId,72                    keys: Option<Vec<Vec<u8>>>73                ) -> Result<TokenData<CrossAccountId>, DispatchError> {74                    let token_data = TokenData {75                        properties: Self::token_properties(collection, token_id, keys)?,76                        owner: Self::token_owner(collection, token_id)?77                    };7879                    Ok(token_data)80                }8182                fn total_supply(collection: CollectionId) -> Result<u32, DispatchError> {83                    dispatch_unique_runtime!(collection.total_supply())84                }85                fn account_balance(collection: CollectionId, account: CrossAccountId) -> Result<u32, DispatchError> {86                    dispatch_unique_runtime!(collection.account_balance(account))87                }88                fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<u128, DispatchError> {89                    dispatch_unique_runtime!(collection.balance(account, token))90                }91                fn allowance(92                    collection: CollectionId,93                    sender: CrossAccountId,94                    spender: CrossAccountId,95                    token: TokenId,96                ) -> Result<u128, DispatchError> {97                    dispatch_unique_runtime!(collection.allowance(sender, spender, token))98                }99100                fn adminlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {101                    Ok(<pallet_common::Pallet<Runtime>>::adminlist(collection))102                }103                fn allowlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {104                    Ok(<pallet_common::Pallet<Runtime>>::allowlist(collection))105                }106                fn allowed(collection: CollectionId, user: CrossAccountId) -> Result<bool, DispatchError> {107                    Ok(<pallet_common::Pallet<Runtime>>::allowed(collection, user))108                }109                fn last_token_id(collection: CollectionId) -> Result<TokenId, DispatchError> {110                    dispatch_unique_runtime!(collection.last_token_id())111                }112                fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>, DispatchError> {113                    Ok(<pallet_common::Pallet<Runtime>>::rpc_collection(collection))114                }115                fn collection_stats() -> Result<CollectionStats, DispatchError> {116                    Ok(<pallet_common::Pallet<Runtime>>::collection_stats())117                }118                fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>, DispatchError> {119                    Ok(<$crate::sponsoring::UniqueSponsorshipPredict<Runtime> as120                            $crate::sponsoring::SponsorshipPredict<Runtime>>::predict(121                        collection,122                        account,123                        token))124                }125126                fn effective_collection_limits(collection: CollectionId) -> Result<Option<CollectionLimits>, DispatchError> {127                    Ok(<pallet_common::Pallet<Runtime>>::effective_collection_limits(collection))128                }129            }130131            impl rmrk_rpc::RmrkApi<132                Block,133                AccountId,134                RmrkCollectionInfo<AccountId>,135                RmrkInstanceInfo<AccountId>,136                RmrkResourceInfo,137                RmrkPropertyInfo,138                RmrkBaseInfo<AccountId>,139                RmrkPartType,140                RmrkTheme141            > for Runtime {142                fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {143                    Ok(RmrkCore::last_collection_idx())144                }145146                fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {147                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};148                    use pallet_common::CommonCollectionOperations;149150                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {151                        Ok(id) => id,152                        Err(_) => return Ok(None)153                    };154155                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {156                        Ok(c) => c,157                        Err(_) => return Ok(None),158                    };159160                    let nfts_count = collection.total_supply();161162                    Ok(Some(RmrkCollectionInfo {163                        issuer: collection.owner.clone(),164                        metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?,165                        max: collection.limits.token_limit,166                        symbol: RmrkCore::rebind(&collection.token_prefix)?,167                        nfts_count168                    }))169                }170171                fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {172                    use up_data_structs::mapping::TokenAddressMapping;173                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};174                    use pallet_common::CommonCollectionOperations;175176                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {177                        Ok(id) => id,178                        Err(_) => return Ok(None)179                    };180                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {181                        Ok(c) => c,182                        Err(_) => return Ok(None),183                    };184185                    let nft_id = TokenId(nft_by_id);186                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); }187188                    let owner = match collection.token_owner(nft_id) {189                        Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {190                            Some((col, tok)) => {191                                let rmrk_collection = RmrkCore::rmrk_collection_id(col)?;192193                                RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0)194                            }195                            None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())196                        },197                        None => return Ok(None)198                    };199200                    let allowance = pallet_nonfungible::Allowance::<Runtime>::get((collection_id, nft_id));201202                    Ok(Some(RmrkInstanceInfo {203                        owner: owner,204                        royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,205                        metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,206                        equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,207                        pending: allowance.is_some(),208                    }))209                }210211                fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {212                    use pallet_proxy_rmrk_core::misc::CollectionType;213                    use pallet_common::CommonCollectionOperations;214215                    let cross_account_id = CrossAccountId::from_sub(account_id);216                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {217                        Ok(id) => id,218                        Err(_) => return Ok(Vec::new())219                    };220                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }221222                    Ok(223                        collection.account_tokens(cross_account_id)224                            .into_iter()225                            .map(|token| token.0)226                            .collect()227                    )228                }229230                fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {231                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {232                        Ok(id) => id,233                        Err(_) => return Ok(Vec::new())234                    };235                    let nft_id = TokenId(nft_id);236                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }237238                    Ok(239                        pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))240                            .filter_map(|((child_collection, child_token), _)| {241                                let rmrk_child_collection = RmrkCore::rmrk_collection_id(242                                    child_collection243                                ).ok()?;244245                                Some(RmrkNftChild {246                                    collection_id: rmrk_child_collection,247                                    nft_id: child_token.0,248                                })249                            }).collect()250                    )251                }252253                fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {254                    use pallet_proxy_rmrk_core::misc::CollectionType;255256                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {257                        Ok(id) => id,258                        Err(_) => return Ok(Vec::new())259                    };260                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {261                        return Ok(Vec::new());262                    }263264                    let properties = RmrkCore::filter_user_properties(265                        collection_id,266                        /* token_id = */ None,267                        filter_keys,268                        |key, value| RmrkPropertyInfo {269                            key,270                            value271                        }272                    )?;273274                    Ok(properties)275                }276277                fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {278                    use pallet_proxy_rmrk_core::misc::NftType;279280                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {281                        Ok(id) => id,282                        Err(_) => return Ok(Vec::new())283                    };284                    let token_id = TokenId(nft_id);285286                    if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {287                        return Ok(Vec::new());288                    }289290		            let properties = RmrkCore::filter_user_properties(291                        collection_id,292                        Some(token_id),293                        filter_keys,294                        |key, value| RmrkPropertyInfo {295                            key,296                            value297                        }298                    )?;299300                    Ok(properties)301                }302303                fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {304                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};305                    use pallet_common::CommonCollectionOperations;306307                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {308                        Ok(id) => id,309                        Err(_) => return Ok(Vec::new())310                    };311                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }312313                    let nft_id = TokenId(nft_id);314                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }315316                    let res_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;317                    let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?;318319                    let resources = resource_collection320                        .collection_tokens()321                        .iter()322                        .filter_map(|(res_id)| Some(RmrkResourceInfo {323                            id: res_id.0,324                            pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap(),325                            pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap(),326                            resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap() {327                                ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {328                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),329                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),330                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),331                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),332                                }),333                                ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {334                                    parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).unwrap(),335                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),336                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),337                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),338                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),339                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),340                                }),341                                ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {342                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),343                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),344                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),345                                    slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).unwrap(),346                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),347                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),348                                }),349                            },350                        }))351                        .collect();352353                    Ok(resources)354                }355356                fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {357                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};358359                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {360                        Ok(id) => id,361                        Err(_) => return Ok(Vec::new())362                    };363                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }364365                    let nft_id = TokenId(nft_id);366                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }367368                    /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)369                        .unwrap();370                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }371372                    let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))373                        .filter_map(|(resource_id, properties)| Some((374                            resource_id, // ResourceId property375                            RmrkCore::get_nft_property_decoded(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap(),376                        )))377                        .collect()378                        .sort_by_key(|(_, index)| *index)379                        .into_iter().map(|(resource_id, _)| resource_id)*/380                    let priorities = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?;381382                    Ok(priorities)383                }384385                fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {386                    use pallet_proxy_rmrk_core::{387                        RmrkProperty, misc::{CollectionType},388                    };389390                    let collection_id = match RmrkCore::unique_collection_id(base_id) {391                        Ok(id) => id,392                        Err(_) => return Ok(None)393                    };394                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {395                        Ok(c) => c,396                        Err(_) => return Ok(None),397                    };398399                    Ok(Some(RmrkBaseInfo {400                        issuer: collection.owner.clone(),401                        base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?,402                        symbol: RmrkCore::rebind(&collection.token_prefix)?,403                    }))404                }405406                fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {407                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};408                    use pallet_common::CommonCollectionOperations;409410                    let collection_id = match RmrkCore::unique_collection_id(base_id) {411                        Ok(id) => id,412                        Err(_) => return Ok(Vec::new())413                    };414                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }415416                    let parts = collection.collection_tokens()417                        .into_iter()418                        .filter_map(|token_id| {419                            let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?;420421                            match nft_type {422                                NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {423                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,424                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,425                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,426                                })),427                                NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {428                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,429                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,430                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,431                                    equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?,432                                })),433                                _ => None434                            }435                        })436                        .collect();437438                    Ok(parts)439                }440441                fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {442                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};443                    use pallet_common::CommonCollectionOperations;444445                    let collection_id = match RmrkCore::unique_collection_id(base_id) {446                        Ok(id) => id,447                        Err(_) => return Ok(Vec::new())448                    };449                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {450                        return Ok(Vec::new());451                    }452453454                    let theme_names = collection.collection_tokens()455                        .iter()456                        .filter_map(|token_id| {457                            let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();458459                            match nft_type {460                                Theme => Some(461                                    RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).unwrap()462                                ),463                                _ => None464                            }465                        })466                        .collect();467468                    Ok(theme_names)469                }470471                fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {472                    use pallet_proxy_rmrk_core::{473                        RmrkProperty,474                        misc::{CollectionType, NftType}475                    };476                    use pallet_common::CommonCollectionOperations;477478                    let collection_id = match RmrkCore::unique_collection_id(base_id) {479                        Ok(id) => id,480                        Err(_) => return Ok(None)481                    };482                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {483                        return Ok(None);484                    }485486                    let theme_info = collection.collection_tokens()487                        .into_iter()488                        .find_map(|token_id| {489                            RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;490491                            let name: RmrkString = RmrkCore::get_nft_property_decoded(492                                collection_id, token_id, RmrkProperty::ThemeName493                            ).ok()?;494495                            if name == theme_name {496                                Some((name, token_id))497                            } else {498                                None499                            }500                        });501502                    let (name, theme_id) = match theme_info {503                        Some((name, theme_id)) => (name, theme_id),504                        None => return Ok(None)505                    };506507                    let properties = RmrkCore::filter_user_properties(508                        collection_id,509                        Some(theme_id),510                        filter_keys,511                        |key, value| RmrkThemeProperty {512                            key,513                            value514                        }515                    )?;516517                    let inherit = RmrkCore::get_nft_property_decoded(518                        collection_id,519                        theme_id,520                        RmrkProperty::ThemeInherit521                    )?;522523                    let theme = RmrkTheme {524                        name,525                        properties,526                        inherit,527                    };528529                    Ok(Some(theme))530                }531            }532533            impl sp_api::Core<Block> for Runtime {534                fn version() -> RuntimeVersion {535                    VERSION536                }537538                fn execute_block(block: Block) {539                    Executive::execute_block(block)540                }541542                fn initialize_block(header: &<Block as BlockT>::Header) {543                    Executive::initialize_block(header)544                }545            }546547            impl sp_api::Metadata<Block> for Runtime {548                fn metadata() -> OpaqueMetadata {549                    OpaqueMetadata::new(Runtime::metadata().into())550                }551            }552553            impl sp_block_builder::BlockBuilder<Block> for Runtime {554                fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {555                    Executive::apply_extrinsic(extrinsic)556                }557558                fn finalize_block() -> <Block as BlockT>::Header {559                    Executive::finalize_block()560                }561562                fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {563                    data.create_extrinsics()564                }565566                fn check_inherents(567                    block: Block,568                    data: sp_inherents::InherentData,569                ) -> sp_inherents::CheckInherentsResult {570                    data.check_extrinsics(&block)571                }572573                // fn random_seed() -> <Block as BlockT>::Hash {574                //     RandomnessCollectiveFlip::random_seed().0575                // }576            }577578            impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {579                fn validate_transaction(580                    source: TransactionSource,581                    tx: <Block as BlockT>::Extrinsic,582                    hash: <Block as BlockT>::Hash,583                ) -> TransactionValidity {584                    Executive::validate_transaction(source, tx, hash)585                }586            }587588            impl sp_offchain::OffchainWorkerApi<Block> for Runtime {589                fn offchain_worker(header: &<Block as BlockT>::Header) {590                    Executive::offchain_worker(header)591                }592            }593594            impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {595                fn chain_id() -> u64 {596                    <Runtime as pallet_evm::Config>::ChainId::get()597                }598599                fn account_basic(address: H160) -> EVMAccount {600                    let (account, _) = EVM::account_basic(&address);601                    account602                }603604                fn gas_price() -> U256 {605                    let (price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();606                    price607                }608609                fn account_code_at(address: H160) -> Vec<u8> {610                    EVM::account_codes(address)611                }612613                fn author() -> H160 {614                    <pallet_evm::Pallet<Runtime>>::find_author()615                }616617                fn storage_at(address: H160, index: U256) -> H256 {618                    let mut tmp = [0u8; 32];619                    index.to_big_endian(&mut tmp);620                    EVM::account_storages(address, H256::from_slice(&tmp[..]))621                }622623                #[allow(clippy::redundant_closure)]624                fn call(625                    from: H160,626                    to: H160,627                    data: Vec<u8>,628                    value: U256,629                    gas_limit: U256,630                    max_fee_per_gas: Option<U256>,631                    max_priority_fee_per_gas: Option<U256>,632                    nonce: Option<U256>,633                    estimate: bool,634                    access_list: Option<Vec<(H160, Vec<H256>)>>,635                ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {636                    let config = if estimate {637                        let mut config = <Runtime as pallet_evm::Config>::config().clone();638                        config.estimate = true;639                        Some(config)640                    } else {641                        None642                    };643644                    let is_transactional = false;645                    <Runtime as pallet_evm::Config>::Runner::call(646                        CrossAccountId::from_eth(from),647                        to,648                        data,649                        value,650                        gas_limit.low_u64(),651                        max_fee_per_gas,652                        max_priority_fee_per_gas,653                        nonce,654                        access_list.unwrap_or_default(),655                        is_transactional,656                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),657                    ).map_err(|err| err.error.into())658                }659660                #[allow(clippy::redundant_closure)]661                fn create(662                    from: H160,663                    data: Vec<u8>,664                    value: U256,665                    gas_limit: U256,666                    max_fee_per_gas: Option<U256>,667                    max_priority_fee_per_gas: Option<U256>,668                    nonce: Option<U256>,669                    estimate: bool,670                    access_list: Option<Vec<(H160, Vec<H256>)>>,671                ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {672                    let config = if estimate {673                        let mut config = <Runtime as pallet_evm::Config>::config().clone();674                        config.estimate = true;675                        Some(config)676                    } else {677                        None678                    };679680                    let is_transactional = false;681                    <Runtime as pallet_evm::Config>::Runner::create(682                        CrossAccountId::from_eth(from),683                        data,684                        value,685                        gas_limit.low_u64(),686                        max_fee_per_gas,687                        max_priority_fee_per_gas,688                        nonce,689                        access_list.unwrap_or_default(),690                        is_transactional,691                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),692                    ).map_err(|err| err.error.into())693                }694695                fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {696                    Ethereum::current_transaction_statuses()697                }698699                fn current_block() -> Option<pallet_ethereum::Block> {700                    Ethereum::current_block()701                }702703                fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {704                    Ethereum::current_receipts()705                }706707                fn current_all() -> (708                    Option<pallet_ethereum::Block>,709                    Option<Vec<pallet_ethereum::Receipt>>,710                    Option<Vec<TransactionStatus>>711                ) {712                    (713                        Ethereum::current_block(),714                        Ethereum::current_receipts(),715                        Ethereum::current_transaction_statuses()716                    )717                }718719                fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {720                    xts.into_iter().filter_map(|xt| match xt.0.function {721                        Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),722                        _ => None723                    }).collect()724                }725726                fn elasticity() -> Option<Permill> {727                    None728                }729            }730731            impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {732                fn convert_transaction(transaction: pallet_ethereum::Transaction) -> <Block as BlockT>::Extrinsic  {733                    UncheckedExtrinsic::new_unsigned(734                        pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),735                    )736                }737            }738739            impl sp_session::SessionKeys<Block> for Runtime {740                fn decode_session_keys(741                    encoded: Vec<u8>,742                ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {743                    SessionKeys::decode_into_raw_public_keys(&encoded)744                }745746                fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {747                    SessionKeys::generate(seed)748                }749            }750751            impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {752                fn slot_duration() -> sp_consensus_aura::SlotDuration {753                    sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())754                }755756                fn authorities() -> Vec<AuraId> {757                    Aura::authorities().to_vec()758                }759            }760761            impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {762                fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {763                    ParachainSystem::collect_collation_info(header)764                }765            }766767            impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {768                fn account_nonce(account: AccountId) -> Index {769                    System::account_nonce(account)770                }771            }772773            impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {774                fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {775                    TransactionPayment::query_info(uxt, len)776                }777                fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {778                    TransactionPayment::query_fee_details(uxt, len)779                }780            }781782            /*783            impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>784                for Runtime785            {786                fn call(787                    origin: AccountId,788                    dest: AccountId,789                    value: Balance,790                    gas_limit: u64,791                    input_data: Vec<u8>,792                ) -> pallet_contracts_primitives::ContractExecResult {793                    Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)794                }795796                fn instantiate(797                    origin: AccountId,798                    endowment: Balance,799                    gas_limit: u64,800                    code: pallet_contracts_primitives::Code<Hash>,801                    data: Vec<u8>,802                    salt: Vec<u8>,803                ) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>804                {805                    Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)806                }807808                fn get_storage(809                    address: AccountId,810                    key: [u8; 32],811                ) -> pallet_contracts_primitives::GetStorageResult {812                    Contracts::get_storage(address, key)813                }814815                fn rent_projection(816                    address: AccountId,817                ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {818                    Contracts::rent_projection(address)819                }820            }821            */822823            #[cfg(feature = "runtime-benchmarks")]824            impl frame_benchmarking::Benchmark<Block> for Runtime {825                fn benchmark_metadata(extra: bool) -> (826                    Vec<frame_benchmarking::BenchmarkList>,827                    Vec<frame_support::traits::StorageInfo>,828                ) {829                    use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};830                    use frame_support::traits::StorageInfoTrait;831832                    let mut list = Vec::<BenchmarkList>::new();833834                    list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);835                    list_benchmark!(list, extra, pallet_common, Common);836                    list_benchmark!(list, extra, pallet_unique, Unique);837                    list_benchmark!(list, extra, pallet_structure, Structure);838                    list_benchmark!(list, extra, pallet_inflation, Inflation);839                    list_benchmark!(list, extra, pallet_fungible, Fungible);840                    list_benchmark!(list, extra, pallet_refungible, Refungible);841                    list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);842                    // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);843844                    let storage_info = AllPalletsReversedWithSystemFirst::storage_info();845846                    return (list, storage_info)847                }848849                fn dispatch_benchmark(850                    config: frame_benchmarking::BenchmarkConfig851                ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {852                    use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};853854                    let allowlist: Vec<TrackedStorageKey> = vec![855                        // Total Issuance856                        hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),857858                        // Block Number859                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),860                        // Execution Phase861                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),862                        // Event Count863                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),864                        // System Events865                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),866867                        // Evm CurrentLogs868                        hex_literal::hex!("1da53b775b270400e7e61ed5cbc5a146547f210cec367e9af919603343b9cb56").to_vec().into(),869870                        // Transactional depth871                        hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a").to_vec().into(),872                    ];873874                    let mut batches = Vec::<BenchmarkBatch>::new();875                    let params = (&config, &allowlist);876877                    add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);878                    add_benchmark!(params, batches, pallet_common, Common);879                    add_benchmark!(params, batches, pallet_unique, Unique);880                    add_benchmark!(params, batches, pallet_structure, Structure);881                    add_benchmark!(params, batches, pallet_inflation, Inflation);882                    add_benchmark!(params, batches, pallet_fungible, Fungible);883                    add_benchmark!(params, batches, pallet_refungible, Refungible);884                    add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);885                    // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);886887                    if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }888                    Ok(batches)889                }890            }891892            #[cfg(feature = "try-runtime")]893            impl frame_try_runtime::TryRuntime<Block> for Runtime {894                fn on_runtime_upgrade() -> (Weight, Weight) {895                    log::info!("try-runtime::on_runtime_upgrade unique-chain.");896                    let weight = Executive::try_runtime_upgrade().unwrap();897                    (weight, RuntimeBlockWeights::get().max_block)898                }899900                fn execute_block_no_check(block: Block) -> Weight {901                    Executive::execute_block_no_check(block)902                }903            }904        }905    }906}