Skip to main content

anone_cw721/
state.rs

1use schemars::JsonSchema;
2use serde::de::DeserializeOwned;
3use serde::{Deserialize, Serialize};
4use std::marker::PhantomData;
5
6use cosmwasm_std::{Addr, BlockInfo, Decimal, StdResult, Storage};
7use cw721::Expiration;
8
9use cw_storage_plus::{Index, IndexList, IndexedMap, Item, Map, MultiIndex};
10
11use crate::msg::{ContractInfoResponse};
12
13pub struct AnoneCw721Contract<'a, T, C>
14where
15    T: Serialize + DeserializeOwned + Clone,
16{
17    pub contract_info: Item<'a, ContractInfoResponse>,
18    pub minter: Item<'a, Addr>,
19    pub token_count: Item<'a, u64>,
20    pub model_count: Item<'a, u64>,
21    /// Stored as (granter, operator) giving operator full control over granter's account
22    pub operators: Map<'a, (&'a Addr, &'a Addr), Expiration>,
23    pub tokens: IndexedMap<'a, &'a str, TokenInfo<T>, TokenIndexes<'a, T>>,
24    pub models: IndexedMap<'a, &'a str, ModelInfo<T>, ModelIndexes<'a, T>>,
25
26    pub(crate) _custom_response: PhantomData<C>,
27}
28
29impl<T, C> Default for AnoneCw721Contract<'static, T, C>
30where
31    T: Serialize + DeserializeOwned + Clone,
32{
33    fn default() -> Self {
34        Self::new(
35            "nft_info",
36            "minter",
37            "num_tokens",
38            "num_models",
39            "operators",
40            "tokens",
41            "tokens__owner",
42            "models",
43            "models_owner",
44        )
45    }
46}
47
48impl<'a, T, C> AnoneCw721Contract<'a, T, C>
49where
50    T: Serialize + DeserializeOwned + Clone,
51{
52    fn new(
53        contract_key: &'a str,
54        minter_key: &'a str,
55        token_count_key: &'a str,
56        model_count_key: &'a str,
57        operator_key: &'a str,
58        tokens_key: &'a str,
59        tokens_owner_key: &'a str,
60        models_key: &'a str,
61        models_owner_key: &'a str,
62    ) -> Self {
63        let indexes = TokenIndexes {
64            owner: MultiIndex::new(token_owner_idx, tokens_key, tokens_owner_key),
65        };
66        let model_indexes = ModelIndexes {
67            owner: MultiIndex::new(model_owner_idx, models_key, models_owner_key),
68        };
69        Self {
70            contract_info: Item::new(contract_key),
71            minter: Item::new(minter_key),
72            token_count: Item::new(token_count_key),
73            model_count: Item::new(model_count_key),
74            operators: Map::new(operator_key),
75            tokens: IndexedMap::new(tokens_key, indexes),
76            models: IndexedMap::new(models_key, model_indexes),
77            _custom_response: PhantomData,
78        }
79    }
80
81    pub fn token_count(&self, storage: &dyn Storage) -> StdResult<u64> {
82        Ok(self.token_count.may_load(storage)?.unwrap_or_default())
83    }
84
85    pub fn model_count(&self, storage: &dyn Storage) -> StdResult<u64> {
86        Ok(self.model_count.may_load(storage)?.unwrap_or_default())
87    }
88
89    pub fn increment_tokens(&self, storage: &mut dyn Storage) -> StdResult<u64> {
90        let val = self.token_count(storage)? + 1;
91        self.token_count.save(storage, &val)?;
92        Ok(val)
93    }
94
95    pub fn decrement_tokens(&self, storage: &mut dyn Storage) -> StdResult<u64> {
96        let val = self.token_count(storage)? - 1;
97        self.token_count.save(storage, &val)?;
98        Ok(val)
99    }
100
101    pub fn increment_models(&self, storage: &mut dyn Storage) -> StdResult<u64> {
102        let val = self.model_count(storage)? + 1;
103        self.model_count.save(storage, &val)?;
104        Ok(val)
105    }
106
107    pub fn decrement_models(&self, storage: &mut dyn Storage) -> StdResult<u64> {
108        let val = self.model_count(storage)? - 1;
109        self.model_count.save(storage, &val)?;
110        Ok(val)
111    }
112}
113
114#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
115pub struct CollectionInfo<T> {
116    pub creator: String,
117    pub description: String,
118    pub image: String,
119    pub external_link: Option<String>,
120    pub royalty_info: Option<T>,
121}
122
123#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
124pub struct RoyaltyInfo {
125    pub payment_address: Addr,
126    pub share: Decimal,
127}
128
129#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
130pub struct TokenInfo<T> {
131    /// Id of this token
132    pub token_id: String,
133
134    /// The owner of the newly minted NFT
135    pub owner: Addr,
136
137    /// Approvals are stored here, as we clear them all upon transfer and cannot accumulate much
138    pub approvals: Vec<Approval>,
139
140    /// Id of this token's model
141    pub model_id: String,
142
143    /// Token uri will be the same as model_uri of this token's model
144    pub token_uri: String,
145
146    /// Here is a unique feature of Anone project.
147    pub size: String,
148
149    /// You can add any custom metadata here when you extend cw721-base
150    pub extension: T,
151}
152
153#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
154pub struct ModelInfo<T> {
155    /// Id of this model
156    pub model_id: String,
157    
158    /// The owner of the newly shoe model
159    pub owner: Addr,
160
161    pub model_uri: String,
162
163    pub extension: T,
164}
165
166#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
167pub struct Approval {
168    /// Account that can transfer/send the token
169    pub spender: Addr,
170    /// When the Approval expires (maybe Expiration::never)
171    pub expires: Expiration,
172}
173
174impl Approval {
175    pub fn is_expired(&self, block: &BlockInfo) -> bool {
176        self.expires.is_expired(block)
177    }
178}
179
180pub struct TokenIndexes<'a, T>
181where
182    T: Serialize + DeserializeOwned + Clone,
183{
184    pub owner: MultiIndex<'a, Addr, TokenInfo<T>, Addr>,
185}
186
187impl<'a, T> IndexList<TokenInfo<T>> for TokenIndexes<'a, T>
188where
189    T: Serialize + DeserializeOwned + Clone,
190{
191    fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<TokenInfo<T>>> + '_> {
192        let v: Vec<&dyn Index<TokenInfo<T>>> = vec![&self.owner];
193        Box::new(v.into_iter())
194    }
195}
196
197pub fn token_owner_idx<T>(d: &TokenInfo<T>) -> Addr {
198    d.owner.clone()
199}
200
201pub struct ModelIndexes<'a, T>
202where
203    T: Serialize + DeserializeOwned + Clone,
204{
205    pub owner: MultiIndex<'a, Addr, ModelInfo<T>, Addr>,
206}
207
208impl<'a, T> IndexList<ModelInfo<T>> for ModelIndexes<'a, T>
209where
210    T: Serialize + DeserializeOwned + Clone,
211{
212    fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<ModelInfo<T>>> + '_> {
213        let v: Vec<&dyn Index<ModelInfo<T>>> = vec![&self.owner];
214        Box::new(v.into_iter())
215    }
216}
217
218pub fn model_owner_idx<T>(d: &ModelInfo<T>) -> Addr {
219    d.owner.clone()
220}
221
222pub const COLLECTION_INFO: Item<CollectionInfo<RoyaltyInfo>> = Item::new("collection_info");