1#![cfg_attr(not(feature = "std"), no_std)]23#[cfg(feature = "serde")]4pub use serde::{Serialize, Deserialize};56use sp_runtime::sp_std::prelude::Vec;7use codec::{Decode, Encode, MaxEncodedLen};8pub use frame_support::{9 BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error,10 dispatch::DispatchResult,11 ensure, fail, parameter_types,12 traits::{13 Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,14 Randomness, IsSubType, WithdrawReasons,15 },16 weights::{17 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},18 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,19 WeightToFeePolynomial, DispatchClass,20 },21 StorageValue, transactional,22};23use derivative::Derivative;2425pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;26pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;27pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;28pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;2930pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {31 10000032} else {33 1034};35pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {36 204837} else {38 1039};40pub const COLLECTION_ADMINS_LIMIT: u64 = 5;41pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {42 100000043} else {44 1045};464748pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;49pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;50pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;515253pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 1024;54pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024;55pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024;5657pub const MAX_COLLECTION_NAME_LENGTH: usize = 64;58pub const MAX_COLLECTION_DESCRIPTION_LENGTH: usize = 256;59pub const MAX_TOKEN_PREFIX_LENGTH: usize = 16;60616263pub const MAX_ITEMS_PER_BATCH: u32 = 200;6465parameter_types! {66 pub const CustomDataLimit: u32 = CUSTOM_DATA_LIMIT;67}6869pub type CollectionId = u32;70pub type TokenId = u32;71pub type DecimalPoints = u8;7273#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]74#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]75pub enum CollectionMode {76 NFT,77 78 Fungible(DecimalPoints),79 ReFungible,80}8182impl CollectionMode {83 pub fn id(&self) -> u8 {84 match self {85 CollectionMode::NFT => 1,86 CollectionMode::Fungible(_) => 2,87 CollectionMode::ReFungible => 3,88 }89 }90}9192pub trait SponsoringResolve<AccountId, Call> {93 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;94}9596#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]97#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]98pub enum AccessMode {99 Normal,100 WhiteList,101}102impl Default for AccessMode {103 fn default() -> Self {104 Self::Normal105 }106}107108#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]109#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]110pub enum SchemaVersion {111 ImageURL,112 Unique,113}114impl Default for SchemaVersion {115 fn default() -> Self {116 Self::ImageURL117 }118}119120#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]121#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]122pub struct Ownership<AccountId> {123 pub owner: AccountId,124 pub fraction: u128,125}126127#[derive(Encode, Decode, Debug, Clone, PartialEq)]128#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]129pub enum SponsorshipState<AccountId> {130 131 Disabled,132 Unconfirmed(AccountId),133 134 Confirmed(AccountId),135}136137impl<AccountId> SponsorshipState<AccountId> {138 pub fn sponsor(&self) -> Option<&AccountId> {139 match self {140 Self::Confirmed(sponsor) => Some(sponsor),141 _ => None,142 }143 }144145 pub fn pending_sponsor(&self) -> Option<&AccountId> {146 match self {147 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),148 _ => None,149 }150 }151152 pub fn confirmed(&self) -> bool {153 matches!(self, Self::Confirmed(_))154 }155}156157impl<T> Default for SponsorshipState<T> {158 fn default() -> Self {159 Self::Disabled160 }161}162163#[derive(Encode, Decode, Clone, PartialEq)]164#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]165pub struct Collection<T: frame_system::Config> {166 pub owner: T::AccountId,167 pub mode: CollectionMode,168 pub access: AccessMode,169 pub decimal_points: DecimalPoints,170 pub name: Vec<u16>, 171 pub description: Vec<u16>, 172 pub token_prefix: Vec<u8>, 173 pub mint_mode: bool,174 pub offchain_schema: Vec<u8>,175 pub schema_version: SchemaVersion,176 pub sponsorship: SponsorshipState<T::AccountId>,177 pub limits: CollectionLimits<T::BlockNumber>, 178 pub variable_on_chain_schema: Vec<u8>, 179 pub const_on_chain_schema: Vec<u8>, 180 pub meta_update_permission: MetaUpdatePermission,181 pub transfers_enabled: bool,182}183184#[derive(Encode, Decode, Debug, Clone, PartialEq)]185#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]186pub struct NftItemType<AccountId> {187 pub owner: AccountId,188 pub const_data: Vec<u8>,189 pub variable_data: Vec<u8>,190}191192#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]193#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]194pub struct FungibleItemType {195 pub value: u128,196}197198#[derive(Encode, Decode, Debug, Clone, PartialEq)]199#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]200pub struct ReFungibleItemType<AccountId> {201 pub owner: Vec<Ownership<AccountId>>,202 pub const_data: Vec<u8>,203 pub variable_data: Vec<u8>,204}205206#[derive(Encode, Decode, Debug, Clone, PartialEq)]207#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]208pub struct CollectionLimits<BlockNumber: Encode + Decode> {209 pub account_token_ownership_limit: u32,210 pub sponsored_data_size: u32,211 212 213 214 pub sponsored_data_rate_limit: Option<BlockNumber>,215 pub token_limit: u32,216217 218 pub sponsor_transfer_timeout: u32,219 pub owner_can_transfer: bool,220 pub owner_can_destroy: bool,221}222223impl<BlockNumber: Encode + Decode> Default for CollectionLimits<BlockNumber> {224 fn default() -> Self {225 Self {226 account_token_ownership_limit: 10_000_000,227 token_limit: u32::max_value(),228 sponsored_data_size: u32::MAX,229 sponsored_data_rate_limit: None,230 sponsor_transfer_timeout: 14400,231 owner_can_transfer: true,232 owner_can_destroy: true,233 }234 }235}236237238#[cfg(feature = "serde1")]239mod bounded_serde {240 use core::convert::TryFrom;241 use frame_support::{BoundedVec, traits::Get};242 use serde::{243 ser::{self, Serialize},244 de::{self, Deserialize, Error},245 };246 use sp_std::vec::Vec;247248 pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>249 where250 D: ser::Serializer,251 V: Serialize,252 {253 let vec: &Vec<_> = &value;254 vec.serialize(serializer)255 }256257 pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>258 where259 D: de::Deserializer<'de>,260 V: de::Deserialize<'de>,261 S: Get<u32>,262 {263 264 let vec = <Vec<V>>::deserialize(deserializer)?;265 let len = vec.len();266 TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))267 }268}269270#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative)]271#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]272#[derivative(Debug)]273pub struct CreateNftData {274 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]275 #[derivative(Debug = "ignore")]276 pub const_data: BoundedVec<u8, CustomDataLimit>,277 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]278 #[derivative(Debug = "ignore")]279 pub variable_data: BoundedVec<u8, CustomDataLimit>,280}281282#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq)]283#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]284pub struct CreateFungibleData {285 pub value: u128,286}287288#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative)]289#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]290#[derivative(Debug)]291pub struct CreateReFungibleData {292 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]293 #[derivative(Debug = "ignore")]294 pub const_data: BoundedVec<u8, CustomDataLimit>,295 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]296 #[derivative(Debug = "ignore")]297 pub variable_data: BoundedVec<u8, CustomDataLimit>,298 pub pieces: u128,299}300301#[derive(Encode, Decode, Debug, Clone, PartialEq)]302#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]303pub enum MetaUpdatePermission {304 ItemOwner,305 Admin,306 None,307}308309impl Default for MetaUpdatePermission {310 fn default() -> Self {311 Self::ItemOwner312 }313}314315#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug)]316#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]317pub enum CreateItemData {318 NFT(CreateNftData),319 Fungible(CreateFungibleData),320 ReFungible(CreateReFungibleData),321}322323impl CreateItemData {324 pub fn data_size(&self) -> usize {325 match self {326 CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),327 CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),328 _ => 0,329 }330 }331}332333impl From<CreateNftData> for CreateItemData {334 fn from(item: CreateNftData) -> Self {335 CreateItemData::NFT(item)336 }337}338339impl From<CreateReFungibleData> for CreateItemData {340 fn from(item: CreateReFungibleData) -> Self {341 CreateItemData::ReFungible(item)342 }343}344345impl From<CreateFungibleData> for CreateItemData {346 fn from(item: CreateFungibleData) -> Self {347 CreateItemData::Fungible(item)348 }349}