diff --git a/pop-api/primitives/src/storage_keys.rs b/pop-api/primitives/src/storage_keys.rs index 8b107eecf..c90851ab6 100644 --- a/pop-api/primitives/src/storage_keys.rs +++ b/pop-api/primitives/src/storage_keys.rs @@ -2,6 +2,7 @@ use scale::{Decode, Encode, MaxEncodedLen}; #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum RuntimeStateKeys { + Nfts(NftsKeys), ParachainSystem(ParachainSystemKeys), } @@ -9,3 +10,14 @@ pub enum RuntimeStateKeys { pub enum ParachainSystemKeys { LastRelayChainBlockNumber, } + +// https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/nfts/src/impl_nonfungibles.rs +#[derive(Encode, Decode, Debug, MaxEncodedLen)] +pub enum NftsKeys { + Owner, + CollectionOwner, + Attribute, + CustomAttribute, + SystemAttribute, + CollectionAttribute, +} diff --git a/runtime/src/extensions.rs b/runtime/src/extensions.rs index c76b048ac..bc6257d36 100644 --- a/runtime/src/extensions.rs +++ b/runtime/src/extensions.rs @@ -2,12 +2,13 @@ use cumulus_primitives_core::relay_chain::BlockNumber; use frame_support::{ dispatch::{GetDispatchInfo, PostDispatchInfo, RawOrigin}, pallet_prelude::*, + traits::nonfungibles_v2::Inspect, }; use log; use pallet_contracts::chain_extension::{ - ChainExtension, Environment, Ext, InitState, RetVal, SysConfig, + BufInBufOutState, ChainExtension, Environment, Ext, InitState, RetVal, SysConfig, }; -use pop_api_primitives::storage_keys::ParachainSystemKeys; +use pop_api_primitives::storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys}; use sp_core::crypto::UncheckedFrom; use sp_runtime::{traits::Dispatchable, DispatchError}; @@ -20,7 +21,7 @@ pub struct PopApiExtension; impl ChainExtension for PopApiExtension where - T: pallet_contracts::Config + cumulus_pallet_parachain_system::Config, + T: pallet_contracts::Config + pallet_nfts::Config + cumulus_pallet_parachain_system::Config, ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>, ::RuntimeCall: Parameter + Dispatchable::RuntimeOrigin, PostInfo = PostDispatchInfo> @@ -137,9 +138,96 @@ where Ok(()) } +fn read_nfts_state( + key: NftsKeys, + env: &mut Environment, +) -> Result, DispatchError> +where + T: pallet_contracts::Config + pallet_nfts::Config + frame_system::Config, + E: Ext, +{ + match key { + NftsKeys::Owner => { + let (collection, item): ( + ::CollectionId, + ::ItemId, + ) = env.read_as()?; + + let maybe_owner = pallet_nfts::Pallet::::owner(collection, item); + Ok(maybe_owner.encode()) + }, + NftsKeys::CollectionOwner => { + let collection: ::CollectionId = env.read_as()?; + + let maybe_owner = pallet_nfts::Pallet::::collection_owner(collection); + + Ok(maybe_owner.encode()) + }, + NftsKeys::Attribute => { + // TODO: charge weight + let len = env.in_len(); + + let (collection, item, key): ( + ::CollectionId, + ::ItemId, + Vec, + ) = env.read_as_unbounded(len)?; + + let maybe_attribute = pallet_nfts::Pallet::::attribute(&collection, &item, &key); + + Ok(maybe_attribute.encode()) + }, + NftsKeys::CustomAttribute => { + // TODO: charge weight + let len = env.in_len(); + + let (account, collection, item, key): ( + ::AccountId, + ::CollectionId, + ::ItemId, + Vec, + ) = env.read_as_unbounded(len)?; + + let maybe_attribute = + pallet_nfts::Pallet::::custom_attribute(&account, &collection, &item, &key); + + Ok(maybe_attribute.encode()) + }, + NftsKeys::SystemAttribute => { + // TODO: charge weight + let len = env.in_len(); + + let (collection, maybe_item, key): ( + ::CollectionId, + Option<::ItemId>, + Vec, + ) = env.read_as_unbounded(len)?; + + let maybe_attribute = + pallet_nfts::Pallet::::system_attribute(&collection, maybe_item.as_ref(), &key); + + Ok(maybe_attribute.encode()) + }, + NftsKeys::CollectionAttribute => { + // TODO: charge weight + let len = env.in_len(); + + let (collection, key): (::CollectionId, Vec) = + env.read_as_unbounded(len)?; + + let maybe_attribute = pallet_nfts::Pallet::::collection_attribute(&collection, &key); + + Ok(maybe_attribute.encode()) + }, + } +} + fn read_state(env: Environment) -> Result<(), DispatchError> where - T: pallet_contracts::Config + cumulus_pallet_parachain_system::Config + frame_system::Config, + T: pallet_contracts::Config + + pallet_nfts::Config + + cumulus_pallet_parachain_system::Config + + frame_system::Config, E: Ext, { const LOG_PREFIX: &str = " read_state |"; @@ -157,23 +245,25 @@ where log::debug!(target:LOG_TARGET, "{} charged weight: {:?}", LOG_PREFIX, charged_weight); - let key: ParachainSystemKeys = env.read_as()?; + let key: RuntimeStateKeys = env.read_as()?; let result = match key { - ParachainSystemKeys::LastRelayChainBlockNumber => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - let relay_block_num: BlockNumber = - cumulus_pallet_parachain_system::Pallet::::last_relay_block_number(); - log::debug!( - target:LOG_TARGET, - "{} last relay chain block number is: {:?}.", LOG_PREFIX, relay_block_num - ); - relay_block_num + RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, &mut env), + RuntimeStateKeys::ParachainSystem(key) => match key { + ParachainSystemKeys::LastRelayChainBlockNumber => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + let relay_block_num: BlockNumber = + cumulus_pallet_parachain_system::Pallet::::last_relay_block_number(); + log::debug!( + target:LOG_TARGET, + "{} last relay chain block number is: {:?}.", LOG_PREFIX, relay_block_num + ); + Ok(relay_block_num.encode()) + }, }, } - .encode() - // Double-encode result for extension return type of bytes .encode(); + log::trace!( target:LOG_TARGET, "{} result: {:?}.", LOG_PREFIX, result