12345678use codec::{Decode, Encode};9use max_encoded_len::MaxEncodedLen;10use derivative::Derivative;1112pub use pallet_contracts::chain_extension::RetVal;13use pallet_contracts::chain_extension::{14 ChainExtension, Environment, Ext, InitState, SysConfig, UncheckedFrom,15};1617pub use frame_support::debug;18use frame_support::dispatch::DispatchError;1920extern crate pallet_nft;21pub use pallet_nft::*;22use pallet_nft::CrossAccountId;23use nft_data_structs::*;242526#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]27pub struct NFTExtCreateItem<AccountId> {28 pub owner: AccountId,29 pub collection_id: u32,30 pub data: CreateItemData,31}323334#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]35pub struct NFTExtTransfer<AccountId> {36 pub recipient: AccountId,37 pub collection_id: u32,38 pub token_id: u32,39 pub amount: u128,40}4142#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)]43#[derivative(Debug)]44pub struct NFTExtCreateMultipleItems<AccountId> {45 pub owner: AccountId,46 pub collection_id: u32,47 #[derivative(Debug = "ignore")]48 pub data: BoundedVec<CreateItemData, MaxItemsPerBatch>,49}5051#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]52pub struct NFTExtApprove<AccountId> {53 pub spender: AccountId,54 pub collection_id: u32,55 pub item_id: u32,56 pub amount: u128,57}5859#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]60pub struct NFTExtTransferFrom<AccountId> {61 pub owner: AccountId,62 pub recipient: AccountId,63 pub collection_id: u32,64 pub item_id: u32,65 pub amount: u128,66}6768#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)]69#[derivative(Debug)]70pub struct NFTExtSetVariableMetaData {71 pub collection_id: u32,72 pub item_id: u32,73 #[derivative(Debug = "ignore")]74 pub data: BoundedVec<u8, MaxDataSize>,75}7677#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]78pub struct NFTExtToggleAllowList<AccountId> {79 pub collection_id: u32,80 pub address: AccountId,81 pub allowlisted: bool,82}838485pub struct NFTExtension;8687pub type NftWeightInfoOf<C> = <C as pallet_nft::Config>::WeightInfo;8889pub type AccountIdOf<C> = <C as SysConfig>::AccountId;9091impl<C: Config + pallet_contracts::Config> ChainExtension<C> for NFTExtension {92 fn call<E: Ext>(func_id: u32, env: Environment<E, InitState>) -> Result<RetVal, DispatchError>93 where94 E: Ext<T = C>,95 C: pallet_nft::Config,96 <E::T as SysConfig>::AccountId: UncheckedFrom<<E::T as SysConfig>::Hash> + AsRef<[u8]>,97 {98 99 match func_id {100 0 => {101 let mut env = env.buf_in_buf_out();102 let input: NFTExtTransfer<AccountIdOf<C>> = env.read_as()?;103 env.charge_weight(NftWeightInfoOf::<C>::transfer())?;104105 let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;106107 pallet_nft::Module::<C>::transfer_internal(108 &C::CrossAccountId::from_sub(env.ext().address().clone()),109 &C::CrossAccountId::from_sub(input.recipient),110 &collection,111 input.token_id,112 input.amount,113 )?;114115 collection.submit_logs()?;116 Ok(RetVal::Converging(0))117 }118 1 => {119 120 let mut env = env.buf_in_buf_out();121 let input: NFTExtCreateItem<AccountIdOf<C>> = env.read_as()?;122 env.charge_weight(NftWeightInfoOf::<C>::create_item(input.data.data_size()))?;123124 let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;125126 pallet_nft::Module::<C>::create_item_internal(127 &C::CrossAccountId::from_sub(env.ext().address().clone()),128 &collection,129 &C::CrossAccountId::from_sub(input.owner),130 input.data,131 )?;132133 collection.submit_logs()?;134 Ok(RetVal::Converging(0))135 }136 2 => {137 138 let mut env = env.buf_in_buf_out();139 let input: NFTExtCreateMultipleItems<AccountIdOf<C>> = env.read_as()?;140 env.charge_weight(NftWeightInfoOf::<C>::create_item(141 input.data.iter().map(|i| i.data_size()).sum(),142 ))?;143144 let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;145146 pallet_nft::Module::<C>::create_multiple_items_internal(147 &C::CrossAccountId::from_sub(env.ext().address().clone()),148 &collection,149 &C::CrossAccountId::from_sub(input.owner),150 input.data.into_inner(),151 )?;152153 collection.submit_logs()?;154 Ok(RetVal::Converging(0))155 }156 3 => {157 158 let mut env = env.buf_in_buf_out();159 let input: NFTExtApprove<AccountIdOf<C>> = env.read_as()?;160 env.charge_weight(NftWeightInfoOf::<C>::approve())?;161162 let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;163164 pallet_nft::Module::<C>::approve_internal(165 &C::CrossAccountId::from_sub(env.ext().address().clone()),166 &C::CrossAccountId::from_sub(input.spender),167 &collection,168 input.item_id,169 input.amount,170 )?;171172 collection.submit_logs()?;173 Ok(RetVal::Converging(0))174 }175 4 => {176 177 let mut env = env.buf_in_buf_out();178 let input: NFTExtTransferFrom<AccountIdOf<C>> = env.read_as()?;179 env.charge_weight(NftWeightInfoOf::<C>::transfer_from())?;180181 let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;182183 pallet_nft::Module::<C>::transfer_from_internal(184 &C::CrossAccountId::from_sub(env.ext().address().clone()),185 &C::CrossAccountId::from_sub(input.owner),186 &C::CrossAccountId::from_sub(input.recipient),187 &collection,188 input.item_id,189 input.amount,190 )?;191192 collection.submit_logs()?;193 Ok(RetVal::Converging(0))194 }195 5 => {196 197 let mut env = env.buf_in_buf_out();198 let input: NFTExtSetVariableMetaData = env.read_as()?;199 env.charge_weight(NftWeightInfoOf::<C>::set_variable_meta_data())?;200201 let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;202203 pallet_nft::Module::<C>::set_variable_meta_data_internal(204 &C::CrossAccountId::from_sub(env.ext().address().clone()),205 &collection,206 input.item_id,207 input.data.into_inner(),208 )?;209210 collection.submit_logs()?;211 Ok(RetVal::Converging(0))212 }213 6 => {214 215 let mut env = env.buf_in_buf_out();216 let input: NFTExtToggleAllowList<AccountIdOf<C>> = env.read_as()?;217 env.charge_weight(NftWeightInfoOf::<C>::add_to_allow_list())?;218219 let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;220221 pallet_nft::Module::<C>::toggle_white_list_internal(222 &C::CrossAccountId::from_sub(env.ext().address().clone()),223 &collection,224 &C::CrossAccountId::from_sub(input.address),225 input.allowlisted,226 )?;227228 collection.submit_logs()?;229 Ok(RetVal::Converging(0))230 }231 _ => Err(DispatchError::Other("unknown chain_extension func_id")),232 }233 }234}