frame_support/traits/tokens/
nonfungible.rs1use super::nonfungibles;
28use crate::{dispatch::DispatchResult, traits::Get};
29use alloc::vec::Vec;
30use codec::{Decode, Encode};
31use sp_runtime::TokenError;
32
33pub trait Inspect<AccountId> {
35 type ItemId;
37
38 fn owner(item: &Self::ItemId) -> Option<AccountId>;
41
42 fn attribute(_item: &Self::ItemId, _key: &[u8]) -> Option<Vec<u8>> {
46 None
47 }
48
49 fn typed_attribute<K: Encode, V: Decode>(item: &Self::ItemId, key: &K) -> Option<V> {
53 key.using_encoded(|d| Self::attribute(item, d))
54 .and_then(|v| V::decode(&mut &v[..]).ok())
55 }
56
57 fn can_transfer(_item: &Self::ItemId) -> bool {
61 true
62 }
63}
64
65pub trait InspectEnumerable<AccountId>: Inspect<AccountId> {
68 type ItemsIterator: Iterator<Item = Self::ItemId>;
70 type OwnedIterator: Iterator<Item = Self::ItemId>;
72
73 fn items() -> Self::ItemsIterator;
75
76 fn owned(who: &AccountId) -> Self::OwnedIterator;
78}
79
80pub trait Mutate<AccountId>: Inspect<AccountId> {
83 fn mint_into(_item: &Self::ItemId, _who: &AccountId) -> DispatchResult {
87 Err(TokenError::Unsupported.into())
88 }
89
90 fn burn(_item: &Self::ItemId, _maybe_check_owner: Option<&AccountId>) -> DispatchResult {
94 Err(TokenError::Unsupported.into())
95 }
96
97 fn set_attribute(_item: &Self::ItemId, _key: &[u8], _value: &[u8]) -> DispatchResult {
101 Err(TokenError::Unsupported.into())
102 }
103
104 fn set_typed_attribute<K: Encode, V: Encode>(
108 item: &Self::ItemId,
109 key: &K,
110 value: &V,
111 ) -> DispatchResult {
112 key.using_encoded(|k| value.using_encoded(|v| Self::set_attribute(item, k, v)))
113 }
114}
115
116pub trait Transfer<AccountId>: Inspect<AccountId> {
118 fn transfer(item: &Self::ItemId, destination: &AccountId) -> DispatchResult;
120}
121
122pub struct ItemOf<
125 F: nonfungibles::Inspect<AccountId>,
126 A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
127 AccountId,
128>(core::marker::PhantomData<(F, A, AccountId)>);
129
130impl<
131 F: nonfungibles::Inspect<AccountId>,
132 A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
133 AccountId,
134 > Inspect<AccountId> for ItemOf<F, A, AccountId>
135{
136 type ItemId = <F as nonfungibles::Inspect<AccountId>>::ItemId;
137 fn owner(item: &Self::ItemId) -> Option<AccountId> {
138 <F as nonfungibles::Inspect<AccountId>>::owner(&A::get(), item)
139 }
140 fn attribute(item: &Self::ItemId, key: &[u8]) -> Option<Vec<u8>> {
141 <F as nonfungibles::Inspect<AccountId>>::attribute(&A::get(), item, key)
142 }
143 fn typed_attribute<K: Encode, V: Decode>(item: &Self::ItemId, key: &K) -> Option<V> {
144 <F as nonfungibles::Inspect<AccountId>>::typed_attribute(&A::get(), item, key)
145 }
146 fn can_transfer(item: &Self::ItemId) -> bool {
147 <F as nonfungibles::Inspect<AccountId>>::can_transfer(&A::get(), item)
148 }
149}
150
151impl<
152 F: nonfungibles::InspectEnumerable<AccountId>,
153 A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
154 AccountId,
155 > InspectEnumerable<AccountId> for ItemOf<F, A, AccountId>
156{
157 type ItemsIterator = <F as nonfungibles::InspectEnumerable<AccountId>>::ItemsIterator;
158 type OwnedIterator =
159 <F as nonfungibles::InspectEnumerable<AccountId>>::OwnedInCollectionIterator;
160
161 fn items() -> Self::ItemsIterator {
162 <F as nonfungibles::InspectEnumerable<AccountId>>::items(&A::get())
163 }
164
165 fn owned(who: &AccountId) -> Self::OwnedIterator {
166 <F as nonfungibles::InspectEnumerable<AccountId>>::owned_in_collection(&A::get(), who)
167 }
168}
169
170impl<
171 F: nonfungibles::Mutate<AccountId>,
172 A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
173 AccountId,
174 > Mutate<AccountId> for ItemOf<F, A, AccountId>
175{
176 fn mint_into(item: &Self::ItemId, who: &AccountId) -> DispatchResult {
177 <F as nonfungibles::Mutate<AccountId>>::mint_into(&A::get(), item, who)
178 }
179 fn burn(item: &Self::ItemId, maybe_check_owner: Option<&AccountId>) -> DispatchResult {
180 <F as nonfungibles::Mutate<AccountId>>::burn(&A::get(), item, maybe_check_owner)
181 }
182 fn set_attribute(item: &Self::ItemId, key: &[u8], value: &[u8]) -> DispatchResult {
183 <F as nonfungibles::Mutate<AccountId>>::set_attribute(&A::get(), item, key, value)
184 }
185 fn set_typed_attribute<K: Encode, V: Encode>(
186 item: &Self::ItemId,
187 key: &K,
188 value: &V,
189 ) -> DispatchResult {
190 <F as nonfungibles::Mutate<AccountId>>::set_typed_attribute(&A::get(), item, key, value)
191 }
192}
193
194impl<
195 F: nonfungibles::Transfer<AccountId>,
196 A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
197 AccountId,
198 > Transfer<AccountId> for ItemOf<F, A, AccountId>
199{
200 fn transfer(item: &Self::ItemId, destination: &AccountId) -> DispatchResult {
201 <F as nonfungibles::Transfer<AccountId>>::transfer(&A::get(), item, destination)
202 }
203}