pallet_uniques/asset_ops/
collection.rs1use core::marker::PhantomData;
19
20use crate::{
21 asset_strategies::{Attribute, WithCollectionConfig},
22 Collection as CollectionStorage, *,
23};
24use frame_support::{
25 ensure,
26 traits::{
27 tokens::asset_ops::{
28 common_strategies::{
29 Bytes, CheckOrigin, CheckState, ConfigValue, IfOwnedBy, Owner, WithConfig,
30 WithWitness,
31 },
32 AssetDefinition, Create, Destroy, Inspect,
33 },
34 EnsureOrigin, Get,
35 },
36 BoundedSlice,
37};
38use frame_system::ensure_signed;
39use sp_runtime::{DispatchError, DispatchResult};
40
41pub struct Collection<PalletInstance>(PhantomData<PalletInstance>);
42
43impl<T: Config<I>, I: 'static> AssetDefinition for Collection<Pallet<T, I>> {
44 type Id = T::CollectionId;
45}
46
47impl<T: Config<I>, I: 'static> Inspect<Owner<T::AccountId>> for Collection<Pallet<T, I>> {
48 fn inspect(
49 collection: &Self::Id,
50 _ownership: Owner<T::AccountId>,
51 ) -> Result<T::AccountId, DispatchError> {
52 CollectionStorage::<T, I>::get(collection)
53 .map(|a| a.owner)
54 .ok_or(Error::<T, I>::UnknownCollection.into())
55 }
56}
57
58impl<T: Config<I>, I: 'static> Inspect<Bytes> for Collection<Pallet<T, I>> {
59 fn inspect(collection: &Self::Id, _bytes: Bytes) -> Result<Vec<u8>, DispatchError> {
60 CollectionMetadataOf::<T, I>::get(collection)
61 .map(|m| m.data.into())
62 .ok_or(Error::<T, I>::NoMetadata.into())
63 }
64}
65
66impl<'a, T: Config<I>, I: 'static> Inspect<Bytes<Attribute<'a>>> for Collection<Pallet<T, I>> {
67 fn inspect(
68 collection: &Self::Id,
69 strategy: Bytes<Attribute>,
70 ) -> Result<Vec<u8>, DispatchError> {
71 let Bytes(Attribute(attribute)) = strategy;
72
73 let attribute =
74 BoundedSlice::try_from(attribute).map_err(|_| Error::<T, I>::WrongAttribute)?;
75 crate::Attribute::<T, I>::get((collection, Option::<T::ItemId>::None, attribute))
76 .map(|a| a.0.into())
77 .ok_or(Error::<T, I>::AttributeNotFound.into())
78 }
79}
80
81impl<T: Config<I>, I: 'static> Create<WithCollectionConfig<T, I>> for Collection<Pallet<T, I>> {
82 fn create(strategy: WithCollectionConfig<T, I>) -> Result<T::CollectionId, DispatchError> {
83 let WithConfig { config, extra: id_assignment } = strategy;
84 let collection = id_assignment.params;
85 let (ConfigValue(owner), ConfigValue(admin)) = config;
86
87 <Pallet<T, I>>::do_create_collection(
88 collection.clone(),
89 owner.clone(),
90 admin.clone(),
91 T::CollectionDeposit::get(),
92 false,
93 Event::Created { collection: collection.clone(), creator: owner, owner: admin },
94 )?;
95
96 Ok(collection)
97 }
98}
99
100impl<T: Config<I>, I: 'static> Create<CheckOrigin<T::RuntimeOrigin, WithCollectionConfig<T, I>>>
101 for Collection<Pallet<T, I>>
102{
103 fn create(
104 strategy: CheckOrigin<T::RuntimeOrigin, WithCollectionConfig<T, I>>,
105 ) -> Result<T::CollectionId, DispatchError> {
106 let CheckOrigin(origin, creation) = strategy;
107
108 let WithConfig { config, extra: id_assignment } = &creation;
109 let collection = &id_assignment.params;
110 let (ConfigValue(owner), ..) = config;
111
112 let maybe_check_signer =
113 T::ForceOrigin::try_origin(origin).map(|_| None).or_else(|origin| {
114 T::CreateOrigin::ensure_origin(origin, collection)
115 .map(Some)
116 .map_err(DispatchError::from)
117 })?;
118
119 if let Some(signer) = maybe_check_signer {
120 ensure!(signer == *owner, Error::<T, I>::NoPermission);
121 }
122
123 Self::create(creation)
124 }
125}
126
127impl<T: Config<I>, I: 'static> Destroy<WithWitness<DestroyWitness>> for Collection<Pallet<T, I>> {
128 fn destroy(collection: &Self::Id, strategy: WithWitness<DestroyWitness>) -> DispatchResult {
129 let CheckState(witness, _) = strategy;
130
131 <Pallet<T, I>>::do_destroy_collection(collection.clone(), witness, None).map(|_witness| ())
132 }
133}
134
135impl<T: Config<I>, I: 'static> Destroy<IfOwnedBy<T::AccountId, WithWitness<DestroyWitness>>>
136 for Collection<Pallet<T, I>>
137{
138 fn destroy(
139 collection: &Self::Id,
140 strategy: IfOwnedBy<T::AccountId, WithWitness<DestroyWitness>>,
141 ) -> DispatchResult {
142 let CheckState(owner, CheckState(witness, _)) = strategy;
143
144 <Pallet<T, I>>::do_destroy_collection(collection.clone(), witness, Some(owner))
145 .map(|_witness| ())
146 }
147}
148
149impl<T: Config<I>, I: 'static> Destroy<CheckOrigin<T::RuntimeOrigin, WithWitness<DestroyWitness>>>
150 for Collection<Pallet<T, I>>
151{
152 fn destroy(
153 collection: &Self::Id,
154 strategy: CheckOrigin<T::RuntimeOrigin, WithWitness<DestroyWitness>>,
155 ) -> DispatchResult {
156 let CheckOrigin(origin, CheckState(witness, _)) = strategy;
157
158 let maybe_check_owner = match T::ForceOrigin::try_origin(origin) {
159 Ok(_) => None,
160 Err(origin) => Some(ensure_signed(origin)?),
161 };
162
163 <Pallet<T, I>>::do_destroy_collection(collection.clone(), witness, maybe_check_owner)
164 .map(|_witness| ())
165 }
166}