use schemars::JsonSchema;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use cosmwasm_std::{Addr, BlockInfo, Decimal, StdResult, Storage};
use cw721::Expiration;
use cw_storage_plus::{Index, IndexList, IndexedMap, Item, Map, MultiIndex};
use crate::msg::{ContractInfoResponse};
pub struct AnoneCw721Contract<'a, T, C>
where
T: Serialize + DeserializeOwned + Clone,
{
pub contract_info: Item<'a, ContractInfoResponse>,
pub minter: Item<'a, Addr>,
pub token_count: Item<'a, u64>,
pub model_count: Item<'a, u64>,
pub operators: Map<'a, (&'a Addr, &'a Addr), Expiration>,
pub tokens: IndexedMap<'a, &'a str, TokenInfo<T>, TokenIndexes<'a, T>>,
pub models: IndexedMap<'a, &'a str, ModelInfo<T>, ModelIndexes<'a, T>>,
pub(crate) _custom_response: PhantomData<C>,
}
impl<T, C> Default for AnoneCw721Contract<'static, T, C>
where
T: Serialize + DeserializeOwned + Clone,
{
fn default() -> Self {
Self::new(
"nft_info",
"minter",
"num_tokens",
"num_models",
"operators",
"tokens",
"tokens__owner",
"models",
"models_owner",
)
}
}
impl<'a, T, C> AnoneCw721Contract<'a, T, C>
where
T: Serialize + DeserializeOwned + Clone,
{
fn new(
contract_key: &'a str,
minter_key: &'a str,
token_count_key: &'a str,
model_count_key: &'a str,
operator_key: &'a str,
tokens_key: &'a str,
tokens_owner_key: &'a str,
models_key: &'a str,
models_owner_key: &'a str,
) -> Self {
let indexes = TokenIndexes {
owner: MultiIndex::new(token_owner_idx, tokens_key, tokens_owner_key),
};
let model_indexes = ModelIndexes {
owner: MultiIndex::new(model_owner_idx, models_key, models_owner_key),
};
Self {
contract_info: Item::new(contract_key),
minter: Item::new(minter_key),
token_count: Item::new(token_count_key),
model_count: Item::new(model_count_key),
operators: Map::new(operator_key),
tokens: IndexedMap::new(tokens_key, indexes),
models: IndexedMap::new(models_key, model_indexes),
_custom_response: PhantomData,
}
}
pub fn token_count(&self, storage: &dyn Storage) -> StdResult<u64> {
Ok(self.token_count.may_load(storage)?.unwrap_or_default())
}
pub fn model_count(&self, storage: &dyn Storage) -> StdResult<u64> {
Ok(self.model_count.may_load(storage)?.unwrap_or_default())
}
pub fn increment_tokens(&self, storage: &mut dyn Storage) -> StdResult<u64> {
let val = self.token_count(storage)? + 1;
self.token_count.save(storage, &val)?;
Ok(val)
}
pub fn decrement_tokens(&self, storage: &mut dyn Storage) -> StdResult<u64> {
let val = self.token_count(storage)? - 1;
self.token_count.save(storage, &val)?;
Ok(val)
}
pub fn increment_models(&self, storage: &mut dyn Storage) -> StdResult<u64> {
let val = self.model_count(storage)? + 1;
self.model_count.save(storage, &val)?;
Ok(val)
}
pub fn decrement_models(&self, storage: &mut dyn Storage) -> StdResult<u64> {
let val = self.model_count(storage)? - 1;
self.model_count.save(storage, &val)?;
Ok(val)
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct CollectionInfo<T> {
pub creator: String,
pub description: String,
pub image: String,
pub external_link: Option<String>,
pub royalty_info: Option<T>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct RoyaltyInfo {
pub payment_address: Addr,
pub share: Decimal,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct TokenInfo<T> {
pub token_id: String,
pub owner: Addr,
pub approvals: Vec<Approval>,
pub model_id: String,
pub token_uri: String,
pub size: String,
pub extension: T,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct ModelInfo<T> {
pub model_id: String,
pub owner: Addr,
pub model_uri: String,
pub extension: T,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct Approval {
pub spender: Addr,
pub expires: Expiration,
}
impl Approval {
pub fn is_expired(&self, block: &BlockInfo) -> bool {
self.expires.is_expired(block)
}
}
pub struct TokenIndexes<'a, T>
where
T: Serialize + DeserializeOwned + Clone,
{
pub owner: MultiIndex<'a, Addr, TokenInfo<T>, Addr>,
}
impl<'a, T> IndexList<TokenInfo<T>> for TokenIndexes<'a, T>
where
T: Serialize + DeserializeOwned + Clone,
{
fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<TokenInfo<T>>> + '_> {
let v: Vec<&dyn Index<TokenInfo<T>>> = vec![&self.owner];
Box::new(v.into_iter())
}
}
pub fn token_owner_idx<T>(d: &TokenInfo<T>) -> Addr {
d.owner.clone()
}
pub struct ModelIndexes<'a, T>
where
T: Serialize + DeserializeOwned + Clone,
{
pub owner: MultiIndex<'a, Addr, ModelInfo<T>, Addr>,
}
impl<'a, T> IndexList<ModelInfo<T>> for ModelIndexes<'a, T>
where
T: Serialize + DeserializeOwned + Clone,
{
fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<ModelInfo<T>>> + '_> {
let v: Vec<&dyn Index<ModelInfo<T>>> = vec![&self.owner];
Box::new(v.into_iter())
}
}
pub fn model_owner_idx<T>(d: &ModelInfo<T>) -> Addr {
d.owner.clone()
}
pub const COLLECTION_INFO: Item<CollectionInfo<RoyaltyInfo>> = Item::new("collection_info");