difftreelog
CORE-386 Add methodt to evm
in: master
11 files changed
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -21,8 +21,9 @@
};
pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};
use pallet_evm_coder_substrate::dispatch_to_evm;
+use sp_core::{H160, U256, H256};
use sp_std::vec::Vec;
-use up_data_structs::{Property, SponsoringRateLimit};
+use up_data_structs::{Property, SponsoringRateLimit, NestingRule, OwnerRestrictedSet};
use alloc::format;
use crate::{Pallet, CollectionHandle, Config, CollectionProperties};
@@ -46,7 +47,10 @@
}
#[solidity_interface(name = "Collection")]
-impl<T: Config> CollectionHandle<T> {
+impl<T: Config> CollectionHandle<T>
+// where
+// T::AccountId: From<H256>
+{
fn set_collection_property(&mut self, caller: caller, key: string, value: bytes) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let key = <Vec<u8>>::from(key)
@@ -165,6 +169,89 @@
fn contract_address(&self, _caller: caller) -> Result<address> {
Ok(crate::eth::collection_id_to_address(self.id))
}
+
+ // fn add_admin_substrate(&self, caller: caller, new_admin: uint256) -> Result<void> {
+ // let mut new_admin_h256 = H256::default();
+ // new_admin.to_little_endian(&mut new_admin_h256.0);
+ // let account_id = T::AccountId::from(new_admin_h256);
+ // let caller = T::CrossAccountId::from_eth(caller);
+ // let new_admin = T::CrossAccountId::from_sub(account_id);
+ // <Pallet<T>>::toggle_admin(&self, &caller, &new_admin, true)
+ // .map_err(dispatch_to_evm::<T>)?;
+ // Ok(())
+ // }
+
+ // fn remove_admin_substrate(&self, caller: caller, new_admin: uint256) -> Result<void> {
+ // let mut new_admin_h256 = H256::default();
+ // new_admin.to_little_endian(&mut new_admin_h256.0);
+ // let account_id = T::AccountId::from(new_admin_h256);
+ // let caller = T::CrossAccountId::from_eth(caller);
+ // let new_admin = T::CrossAccountId::from_sub(account_id);
+ // <Pallet<T>>::toggle_admin(&self, &caller, &new_admin, false)
+ // .map_err(dispatch_to_evm::<T>)?;
+ // Ok(())
+ // }
+
+ fn add_admin(&self, caller: caller, new_admin: address) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ self.check_is_owner_or_admin(&caller)
+ .map_err(dispatch_to_evm::<T>)?;
+ let new_admin = T::CrossAccountId::from_eth(new_admin);
+ <Pallet<T>>::toggle_admin(&self, &caller, &new_admin, true)
+ .map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
+
+ fn remove_admin(&self, caller: caller, admin: address) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ self.check_is_owner_or_admin(&caller)
+ .map_err(dispatch_to_evm::<T>)?;
+ let admin = T::CrossAccountId::from_eth(admin);
+ <Pallet<T>>::toggle_admin(&self, &caller, &admin, false)
+ .map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
+
+ #[solidity(rename_selector = "setNesting")]
+ fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ self.check_is_owner_or_admin(&caller)
+ .map_err(dispatch_to_evm::<T>)?;
+ self.collection.permissions.nesting = Some(match enable {
+ false => NestingRule::Disabled,
+ true => NestingRule::Owner,
+ });
+ save(self);
+ Ok(())
+ }
+
+ #[solidity(rename_selector = "setNesting")]
+ fn set_nesting(&mut self, caller: caller, enable: bool, collections: Vec<address>) -> Result<void> {
+ if collections.is_empty() {
+ return Err("No addresses provided".into());
+ }
+ if collections.len() >= OwnerRestrictedSet::bound() {
+ return Err(Error::Revert(format!("Out of bound: {} >= {}", collections.len(), OwnerRestrictedSet::bound())));
+ }
+ let caller = T::CrossAccountId::from_eth(caller);
+ self.check_is_owner_or_admin(&caller)
+ .map_err(dispatch_to_evm::<T>)?;
+ self.collection.permissions.nesting = Some(match enable {
+ false => NestingRule::Disabled,
+ true => {
+ let mut bv = OwnerRestrictedSet::new();
+ for i in collections {
+ bv.try_insert(
+ crate::eth::map_eth_to_id(&i)
+ .ok_or(Error::Revert("Can't convert address into collection id".into()))?
+ ).map_err(|e| Error::Revert(format!("{:?}", e)))?;
+ }
+ NestingRule::OwnerRestricted (bv)
+ }
+ });
+ save(self);
+ Ok(())
+ }
}
fn check_is_owner<T: Config>(caller: caller, collection: &CollectionHandle<T>) -> Result<()> {
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -126,9 +126,11 @@
pub fn new(id: CollectionId) -> Option<Self> {
Self::new_with_gas_limit(id, u64::MAX)
}
+
pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {
Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)
}
+
pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {
self.recorder
.consume_gas(T::GasWeightMapping::weight_to_gas(
@@ -137,6 +139,7 @@
.saturating_mul(reads),
))
}
+
pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {
self.recorder
.consume_gas(T::GasWeightMapping::weight_to_gas(
@@ -145,6 +148,7 @@
.saturating_mul(writes),
))
}
+
pub fn save(self) -> DispatchResult {
<CollectionById<T>>::insert(self.id, self.collection);
Ok(())
@@ -163,6 +167,7 @@
true
}
}
+
impl<T: Config> Deref for CollectionHandle<T> {
type Target = Collection<T::AccountId>;
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -51,6 +51,105 @@
event MintingFinished();
}
+// Selector: 3a54513b
+contract Collection is Dummy, ERC165 {
+ // Selector: setCollectionProperty(string,bytes) 2f073f66
+ function setCollectionProperty(string memory key, bytes memory value)
+ public
+ {
+ require(false, stub_error);
+ key;
+ value;
+ dummy = 0;
+ }
+
+ // Selector: deleteCollectionProperty(string) 7b7debce
+ function deleteCollectionProperty(string memory key) public {
+ require(false, stub_error);
+ key;
+ dummy = 0;
+ }
+
+ // Throws error if key not found
+ //
+ // Selector: collectionProperty(string) cf24fd6d
+ function collectionProperty(string memory key)
+ public
+ view
+ returns (bytes memory)
+ {
+ require(false, stub_error);
+ key;
+ dummy;
+ return hex"";
+ }
+
+ // Selector: ethSetSponsor(address) 8f9af356
+ function ethSetSponsor(address sponsor) public {
+ require(false, stub_error);
+ sponsor;
+ dummy = 0;
+ }
+
+ // Selector: ethConfirmSponsorship() a8580d1a
+ function ethConfirmSponsorship() public {
+ require(false, stub_error);
+ dummy = 0;
+ }
+
+ // Selector: setLimit(string,uint32) 68db30ca
+ function setLimit(string memory limit, uint32 value) public {
+ require(false, stub_error);
+ limit;
+ value;
+ dummy = 0;
+ }
+
+ // Selector: setLimit(string,bool) ea67e4c2
+ function setLimit(string memory limit, bool value) public {
+ require(false, stub_error);
+ limit;
+ value;
+ dummy = 0;
+ }
+
+ // Selector: contractAddress() f6b4dfb4
+ function contractAddress() public view returns (address) {
+ require(false, stub_error);
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
+
+ // Selector: addAdmin(address) 70480275
+ function addAdmin(address newAdmin) public view {
+ require(false, stub_error);
+ newAdmin;
+ dummy;
+ }
+
+ // Selector: removeAdmin(address) 1785f53c
+ function removeAdmin(address admin) public view {
+ require(false, stub_error);
+ admin;
+ dummy;
+ }
+
+ // Selector: setNesting(bool) e8fc50dd
+ function setNesting(bool enable) public {
+ require(false, stub_error);
+ enable;
+ dummy = 0;
+ }
+
+ // Selector: setNesting(bool,address[]) 7df12a9a
+ function setNesting(bool enable, address[] memory collections) public {
+ require(false, stub_error);
+ enable;
+ collections;
+ dummy = 0;
+ }
+}
+
// Selector: 41369377
contract TokenProperties is Dummy, ERC165 {
// Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
@@ -327,76 +426,6 @@
require(false, stub_error);
dummy;
return 0;
- }
-}
-
-// Selector: c894dc35
-contract Collection is Dummy, ERC165 {
- // Selector: setCollectionProperty(string,bytes) 2f073f66
- function setCollectionProperty(string memory key, bytes memory value)
- public
- {
- require(false, stub_error);
- key;
- value;
- dummy = 0;
- }
-
- // Selector: deleteCollectionProperty(string) 7b7debce
- function deleteCollectionProperty(string memory key) public {
- require(false, stub_error);
- key;
- dummy = 0;
- }
-
- // Throws error if key not found
- //
- // Selector: collectionProperty(string) cf24fd6d
- function collectionProperty(string memory key)
- public
- view
- returns (bytes memory)
- {
- require(false, stub_error);
- key;
- dummy;
- return hex"";
- }
-
- // Selector: ethSetSponsor(address) 8f9af356
- function ethSetSponsor(address sponsor) public {
- require(false, stub_error);
- sponsor;
- dummy = 0;
- }
-
- // Selector: ethConfirmSponsorship() a8580d1a
- function ethConfirmSponsorship() public {
- require(false, stub_error);
- dummy = 0;
- }
-
- // Selector: setLimit(string,uint32) 68db30ca
- function setLimit(string memory limit, uint32 value) public {
- require(false, stub_error);
- limit;
- value;
- dummy = 0;
- }
-
- // Selector: setLimit(string,bool) ea67e4c2
- function setLimit(string memory limit, bool value) public {
- require(false, stub_error);
- limit;
- value;
- dummy = 0;
- }
-
- // Selector: contractAddress() f6b4dfb4
- function contractAddress() public view returns (address) {
- require(false, stub_error);
- dummy;
- return 0x0000000000000000000000000000000000000000;
}
}
primitives/data-structs/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![cfg_attr(not(feature = "std"), no_std)]1819use core::{20 convert::{TryFrom, TryInto},21 fmt,22};23use frame_support::{24 storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},25 traits::Get,26 parameter_types,27};2829#[cfg(feature = "serde")]30use serde::{Serialize, Deserialize};3132use sp_core::U256;33use sp_runtime::{ArithmeticError, sp_std::prelude::Vec, Permill};34use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};35use frame_support::{BoundedVec, traits::ConstU32};36use derivative::Derivative;37use scale_info::TypeInfo;3839pub mod rmrk;4041// RMRK42use rmrk::{43 CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme, ThemeProperty,44 ResourceTypes, BasicResource, ComposableResource, SlotResource,45};46pub use rmrk::{47 primitives::{48 CollectionId as RmrkCollectionId, NftId as RmrkNftId, BaseId as RmrkBaseId,49 PartId as RmrkPartId, ResourceId as RmrkResourceId,50 },51 NftChild as RmrkNftChild, AccountIdOrCollectionNftTuple as RmrkAccountIdOrCollectionNftTuple,52 FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart, EquippableList as RmrkEquippableList,53};5455mod bounded;56pub mod budget;57pub mod mapping;58mod migration;5960pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;61pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;62pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;6364pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {65 100_00066} else {67 1068};69pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {70 100_00071} else {72 1073};74pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {75 204876} else {77 1078};79pub const COLLECTION_ADMINS_LIMIT: u32 = 5;80pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;81pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {82 1_000_00083} else {84 1085};8687// Timeouts for item types in passed blocks88pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;89pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;90pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;9192pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;9394// Schema limits95pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;96pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;97pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;9899pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;100101pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;102pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;103pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;104105pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;106pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;107pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;108109pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;110pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;111112// RMRK constants113pub const RMRK_STRING_LIMIT: u32 = 128;114pub const RMRK_COLLECTION_SYMBOL_LIMIT: u32 = 100;115pub const RMRK_RESOURCE_SYMBOL_LIMIT: u32 = 10;116pub const RMRK_KEY_LIMIT: u32 = 32;117pub const RMRK_VALUE_LIMIT: u32 = 256;118119/// How much items can be created per single120/// create_many call121pub const MAX_ITEMS_PER_BATCH: u32 = 200;122123pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;124125#[derive(126 Encode,127 Decode,128 PartialEq,129 Eq,130 PartialOrd,131 Ord,132 Clone,133 Copy,134 Debug,135 Default,136 TypeInfo,137 MaxEncodedLen,138)]139#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]140pub struct CollectionId(pub u32);141impl EncodeLike<u32> for CollectionId {}142impl EncodeLike<CollectionId> for u32 {}143144#[derive(145 Encode,146 Decode,147 PartialEq,148 Eq,149 PartialOrd,150 Ord,151 Clone,152 Copy,153 Debug,154 Default,155 TypeInfo,156 MaxEncodedLen,157)]158#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]159pub struct TokenId(pub u32);160impl EncodeLike<u32> for TokenId {}161impl EncodeLike<TokenId> for u32 {}162163impl TokenId {164 pub fn try_next(self) -> Result<TokenId, ArithmeticError> {165 self.0166 .checked_add(1)167 .ok_or(ArithmeticError::Overflow)168 .map(Self)169 }170}171172impl From<TokenId> for U256 {173 fn from(t: TokenId) -> Self {174 t.0.into()175 }176}177178impl TryFrom<U256> for TokenId {179 type Error = &'static str;180181 fn try_from(value: U256) -> Result<Self, Self::Error> {182 Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))183 }184}185186#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]187#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]188pub struct TokenData<CrossAccountId> {189 pub properties: Vec<Property>,190 pub owner: Option<CrossAccountId>,191}192193pub struct OverflowError;194impl From<OverflowError> for &'static str {195 fn from(_: OverflowError) -> Self {196 "overflow occured"197 }198}199200pub type DecimalPoints = u8;201202#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]203#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]204pub enum CollectionMode {205 NFT,206 // decimal points207 Fungible(DecimalPoints),208 ReFungible,209}210211impl CollectionMode {212 pub fn id(&self) -> u8 {213 match self {214 CollectionMode::NFT => 1,215 CollectionMode::Fungible(_) => 2,216 CollectionMode::ReFungible => 3,217 }218 }219}220221pub trait SponsoringResolve<AccountId, Call> {222 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;223}224225#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]226#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]227pub enum AccessMode {228 Normal,229 AllowList,230}231impl Default for AccessMode {232 fn default() -> Self {233 Self::Normal234 }235}236237#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]238#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]239pub enum SchemaVersion {240 ImageURL,241 Unique,242}243impl Default for SchemaVersion {244 fn default() -> Self {245 Self::ImageURL246 }247}248249#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]250#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]251pub struct Ownership<AccountId> {252 pub owner: AccountId,253 pub fraction: u128,254}255256#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]257#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]258pub enum SponsorshipState<AccountId> {259 /// The fees are applied to the transaction sender260 Disabled,261 Unconfirmed(AccountId),262 /// Transactions are sponsored by specified account263 Confirmed(AccountId),264}265266impl<AccountId> SponsorshipState<AccountId> {267 pub fn sponsor(&self) -> Option<&AccountId> {268 match self {269 Self::Confirmed(sponsor) => Some(sponsor),270 _ => None,271 }272 }273274 pub fn pending_sponsor(&self) -> Option<&AccountId> {275 match self {276 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),277 _ => None,278 }279 }280281 pub fn confirmed(&self) -> bool {282 matches!(self, Self::Confirmed(_))283 }284}285286impl<T> Default for SponsorshipState<T> {287 fn default() -> Self {288 Self::Disabled289 }290}291292/// Used in storage293#[struct_versioning::versioned(version = 2, upper)]294#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]295pub struct Collection<AccountId> {296 pub owner: AccountId,297 pub mode: CollectionMode,298 #[version(..2)]299 pub access: AccessMode,300 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,301 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,302 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,303304 #[version(..2)]305 pub mint_mode: bool,306307 #[version(..2)]308 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,309310 #[version(..2)]311 pub schema_version: SchemaVersion,312 pub sponsorship: SponsorshipState<AccountId>,313314 pub limits: CollectionLimits,315316 #[version(2.., upper(Default::default()))]317 pub permissions: CollectionPermissions,318319 #[version(..2)]320 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,321322 #[version(..2)]323 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,324325 #[version(..2)]326 pub meta_update_permission: MetaUpdatePermission,327}328329/// Used in RPC calls330#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]331#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]332pub struct RpcCollection<AccountId> {333 pub owner: AccountId,334 pub mode: CollectionMode,335 pub name: Vec<u16>,336 pub description: Vec<u16>,337 pub token_prefix: Vec<u8>,338 pub sponsorship: SponsorshipState<AccountId>,339 pub limits: CollectionLimits,340 pub permissions: CollectionPermissions,341 pub token_property_permissions: Vec<PropertyKeyPermission>,342 pub properties: Vec<Property>,343}344345#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]346#[derivative(Debug, Default(bound = ""))]347pub struct CreateCollectionData<AccountId> {348 #[derivative(Default(value = "CollectionMode::NFT"))]349 pub mode: CollectionMode,350 pub access: Option<AccessMode>,351 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,352 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,353 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,354 pub pending_sponsor: Option<AccountId>,355 pub limits: Option<CollectionLimits>,356 pub permissions: Option<CollectionPermissions>,357 pub token_property_permissions: CollectionPropertiesPermissionsVec,358 pub properties: CollectionPropertiesVec,359}360361pub type CollectionPropertiesPermissionsVec =362 BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;363364pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;365366/// All fields are wrapped in `Option`s, where None means chain default367// When adding/removing fields from this struct - don't forget to also update clamp_limits368#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]369#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]370pub struct CollectionLimits {371 pub account_token_ownership_limit: Option<u32>,372 pub sponsored_data_size: Option<u32>,373374 /// FIXME should we delete this or repurpose it?375 /// None - setVariableMetadata is not sponsored376 /// Some(v) - setVariableMetadata is sponsored377 /// if there is v block between txs378 pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,379 pub token_limit: Option<u32>,380381 // Timeouts for item types in passed blocks382 pub sponsor_transfer_timeout: Option<u32>,383 pub sponsor_approve_timeout: Option<u32>,384 pub owner_can_transfer: Option<bool>,385 pub owner_can_destroy: Option<bool>,386 pub transfers_enabled: Option<bool>,387}388389impl CollectionLimits {390 pub fn account_token_ownership_limit(&self) -> u32 {391 self.account_token_ownership_limit392 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)393 .min(MAX_TOKEN_OWNERSHIP)394 }395 pub fn sponsored_data_size(&self) -> u32 {396 self.sponsored_data_size397 .unwrap_or(CUSTOM_DATA_LIMIT)398 .min(CUSTOM_DATA_LIMIT)399 }400 pub fn token_limit(&self) -> u32 {401 self.token_limit402 .unwrap_or(COLLECTION_TOKEN_LIMIT)403 .min(COLLECTION_TOKEN_LIMIT)404 }405 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {406 self.sponsor_transfer_timeout407 .unwrap_or(default)408 .min(MAX_SPONSOR_TIMEOUT)409 }410 pub fn sponsor_approve_timeout(&self) -> u32 {411 self.sponsor_approve_timeout412 .unwrap_or(SPONSOR_APPROVE_TIMEOUT)413 .min(MAX_SPONSOR_TIMEOUT)414 }415 pub fn owner_can_transfer(&self) -> bool {416 self.owner_can_transfer.unwrap_or(true)417 }418 pub fn owner_can_destroy(&self) -> bool {419 self.owner_can_destroy.unwrap_or(true)420 }421 pub fn transfers_enabled(&self) -> bool {422 self.transfers_enabled.unwrap_or(true)423 }424 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {425 match self426 .sponsored_data_rate_limit427 .unwrap_or(SponsoringRateLimit::SponsoringDisabled)428 {429 SponsoringRateLimit::SponsoringDisabled => None,430 SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),431 }432 }433}434435// When adding/removing fields from this struct - don't forget to also update clamp_limits436#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]437#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]438pub struct CollectionPermissions {439 pub access: Option<AccessMode>,440 pub mint_mode: Option<bool>,441 pub nesting: Option<NestingRule>,442}443444impl CollectionPermissions {445 pub fn access(&self) -> AccessMode {446 self.access.unwrap_or(AccessMode::Normal)447 }448 pub fn mint_mode(&self) -> bool {449 self.mint_mode.unwrap_or(false)450 }451 pub fn nesting(&self) -> &NestingRule {452 static DEFAULT: NestingRule = NestingRule::Disabled;453 self.nesting.as_ref().unwrap_or(&DEFAULT)454 }455}456457#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]458#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]459#[derivative(Debug)]460pub enum NestingRule {461 /// No one can nest tokens462 Disabled,463 /// Owner can nest any tokens464 Owner,465 /// Owner can nest tokens from specified collections466 OwnerRestricted(467 #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]468 #[derivative(Debug(format_with = "bounded::set_debug"))]469 BoundedBTreeSet<CollectionId, ConstU32<16>>,470 ),471 /// Used for tests472 Permissive,473}474475#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]476#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]477pub enum SponsoringRateLimit {478 SponsoringDisabled,479 Blocks(u32),480}481482#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]483#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]484#[derivative(Debug)]485pub struct CreateNftData {486 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]487 #[derivative(Debug(format_with = "bounded::vec_debug"))]488 pub properties: CollectionPropertiesVec,489}490491#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]492#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]493pub struct CreateFungibleData {494 pub value: u128,495}496497#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]498#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]499#[derivative(Debug)]500pub struct CreateReFungibleData {501 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]502 #[derivative(Debug(format_with = "bounded::vec_debug"))]503 pub const_data: BoundedVec<u8, CustomDataLimit>,504 pub pieces: u128,505}506507#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]508#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]509pub enum MetaUpdatePermission {510 ItemOwner,511 Admin,512 None,513}514515#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]516#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]517pub enum CreateItemData {518 NFT(CreateNftData),519 Fungible(CreateFungibleData),520 ReFungible(CreateReFungibleData),521}522523#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]524#[derivative(Debug)]525pub struct CreateNftExData<CrossAccountId> {526 #[derivative(Debug(format_with = "bounded::vec_debug"))]527 pub properties: CollectionPropertiesVec,528 pub owner: CrossAccountId,529}530531#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]532#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]533pub struct CreateRefungibleExData<CrossAccountId> {534 #[derivative(Debug(format_with = "bounded::vec_debug"))]535 pub const_data: BoundedVec<u8, CustomDataLimit>,536 #[derivative(Debug(format_with = "bounded::map_debug"))]537 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,538}539540#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]541#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]542pub enum CreateItemExData<CrossAccountId> {543 NFT(544 #[derivative(Debug(format_with = "bounded::vec_debug"))]545 BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,546 ),547 Fungible(548 #[derivative(Debug(format_with = "bounded::map_debug"))]549 BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,550 ),551 /// Many tokens, each may have only one owner552 RefungibleMultipleItems(553 #[derivative(Debug(format_with = "bounded::vec_debug"))]554 BoundedVec<CreateRefungibleExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,555 ),556 /// Single token, which may have many owners557 RefungibleMultipleOwners(CreateRefungibleExData<CrossAccountId>),558}559560impl CreateItemData {561 pub fn data_size(&self) -> usize {562 match self {563 CreateItemData::ReFungible(data) => data.const_data.len(),564 _ => 0,565 }566 }567}568569impl From<CreateNftData> for CreateItemData {570 fn from(item: CreateNftData) -> Self {571 CreateItemData::NFT(item)572 }573}574575impl From<CreateReFungibleData> for CreateItemData {576 fn from(item: CreateReFungibleData) -> Self {577 CreateItemData::ReFungible(item)578 }579}580581impl From<CreateFungibleData> for CreateItemData {582 fn from(item: CreateFungibleData) -> Self {583 CreateItemData::Fungible(item)584 }585}586587#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]588#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]589// todo possibly rename to be used generally as an address pair590pub struct TokenChild {591 pub token: TokenId,592 pub collection: CollectionId,593}594595#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]596#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]597pub struct CollectionStats {598 pub created: u32,599 pub destroyed: u32,600 pub alive: u32,601}602603#[derive(Encode, Decode, Clone, Debug)]604#[cfg_attr(feature = "std", derive(PartialEq))]605pub struct PhantomType<T>(core::marker::PhantomData<T>);606607impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {608 type Identity = PhantomType<T>;609610 fn type_info() -> scale_info::Type {611 use scale_info::{612 Type, Path,613 build::{FieldsBuilder, UnnamedFields},614 type_params,615 };616 Type::builder()617 .path(Path::new("up_data_structs", "PhantomType"))618 .type_params(type_params!(T))619 .composite(<FieldsBuilder<UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()))620 }621}622impl<T> MaxEncodedLen for PhantomType<T> {623 fn max_encoded_len() -> usize {624 0625 }626}627628pub type PropertyKey = BoundedVec<u8, ConstU32<MAX_PROPERTY_KEY_LENGTH>>;629pub type PropertyValue = BoundedVec<u8, ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;630631#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]632#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]633pub struct PropertyPermission {634 pub mutable: bool,635 pub collection_admin: bool,636 pub token_owner: bool,637}638639impl PropertyPermission {640 pub fn none() -> Self {641 Self {642 mutable: true,643 collection_admin: false,644 token_owner: false,645 }646 }647}648649#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]650#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]651pub struct Property {652 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]653 pub key: PropertyKey,654655 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]656 pub value: PropertyValue,657}658659impl Into<(PropertyKey, PropertyValue)> for Property {660 fn into(self) -> (PropertyKey, PropertyValue) {661 (self.key, self.value)662 }663}664665#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]666#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]667pub struct PropertyKeyPermission {668 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]669 pub key: PropertyKey,670671 pub permission: PropertyPermission,672}673674impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {675 fn into(self) -> (PropertyKey, PropertyPermission) {676 (self.key, self.permission)677 }678}679680#[derive(Debug)]681pub enum PropertiesError {682 NoSpaceForProperty,683 PropertyLimitReached,684 InvalidCharacterInPropertyKey,685 PropertyKeyIsTooLong,686 EmptyPropertyKey,687}688689#[derive(Clone, Copy)]690pub enum PropertyScope {691 None,692 Rmrk,693}694695impl PropertyScope {696 pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {697 let scope_str: &[u8] = match self {698 Self::None => return Ok(key),699 Self::Rmrk => b"rmrk",700 };701702 [scope_str, b":", key.as_slice()]703 .concat()704 .try_into()705 .map_err(|_| PropertiesError::PropertyKeyIsTooLong)706 }707}708709pub trait TrySetProperty: Sized {710 type Value;711712 fn try_scoped_set(713 &mut self,714 scope: PropertyScope,715 key: PropertyKey,716 value: Self::Value,717 ) -> Result<(), PropertiesError>;718719 fn try_scoped_set_from_iter<I, KV>(720 &mut self,721 scope: PropertyScope,722 iter: I,723 ) -> Result<(), PropertiesError>724 where725 I: Iterator<Item = KV>,726 KV: Into<(PropertyKey, Self::Value)>,727 {728 for kv in iter {729 let (key, value) = kv.into();730 self.try_scoped_set(scope, key, value)?;731 }732733 Ok(())734 }735736 fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {737 self.try_scoped_set(PropertyScope::None, key, value)738 }739740 fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>741 where742 I: Iterator<Item = KV>,743 KV: Into<(PropertyKey, Self::Value)>,744 {745 self.try_scoped_set_from_iter(PropertyScope::None, iter)746 }747}748749#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]750#[derivative(Default(bound = ""))]751pub struct PropertiesMap<Value>(752 BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,753);754755impl<Value> PropertiesMap<Value> {756 pub fn new() -> Self {757 Self(BoundedBTreeMap::new())758 }759760 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {761 Self::check_property_key(key)?;762763 Ok(self.0.remove(key))764 }765766 pub fn get(&self, key: &PropertyKey) -> Option<&Value> {767 self.0.get(key)768 }769770 pub fn contains_key(&self, key: &PropertyKey) -> bool {771 self.0.contains_key(key)772 }773774 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {775 if key.is_empty() {776 return Err(PropertiesError::EmptyPropertyKey);777 }778779 for byte in key.as_slice().iter() {780 let byte = *byte;781782 if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' {783 return Err(PropertiesError::InvalidCharacterInPropertyKey);784 }785 }786787 Ok(())788 }789}790791impl<Value> IntoIterator for PropertiesMap<Value> {792 type Item = (PropertyKey, Value);793 type IntoIter = <794 BoundedBTreeMap<795 PropertyKey,796 Value,797 ConstU32<MAX_PROPERTIES_PER_ITEM>798 > as IntoIterator799 >::IntoIter;800801 fn into_iter(self) -> Self::IntoIter {802 self.0.into_iter()803 }804}805806impl<Value> TrySetProperty for PropertiesMap<Value> {807 type Value = Value;808809 fn try_scoped_set(810 &mut self,811 scope: PropertyScope,812 key: PropertyKey,813 value: Self::Value,814 ) -> Result<(), PropertiesError> {815 Self::check_property_key(&key)?;816817 let key = scope.apply(key)?;818 self.0819 .try_insert(key, value)820 .map_err(|_| PropertiesError::PropertyLimitReached)?;821822 Ok(())823 }824}825826pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;827828#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, MaxEncodedLen)]829pub struct Properties {830 map: PropertiesMap<PropertyValue>,831 consumed_space: u32,832 space_limit: u32,833}834835impl Properties {836 pub fn new(space_limit: u32) -> Self {837 Self {838 map: PropertiesMap::new(),839 consumed_space: 0,840 space_limit,841 }842 }843844 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {845 let value = self.map.remove(key)?;846847 if let Some(ref value) = value {848 let value_len = value.len() as u32;849 self.consumed_space -= value_len;850 }851852 Ok(value)853 }854855 pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {856 self.map.get(key)857 }858}859860impl IntoIterator for Properties {861 type Item = (PropertyKey, PropertyValue);862 type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;863864 fn into_iter(self) -> Self::IntoIter {865 self.map.into_iter()866 }867}868869impl TrySetProperty for Properties {870 type Value = PropertyValue;871872 fn try_scoped_set(873 &mut self,874 scope: PropertyScope,875 key: PropertyKey,876 value: Self::Value,877 ) -> Result<(), PropertiesError> {878 let value_len = value.len();879880 if self.consumed_space as usize + value_len > self.space_limit as usize881 && !cfg!(feature = "runtime-benchmarks")882 {883 return Err(PropertiesError::NoSpaceForProperty);884 }885886 self.map.try_scoped_set(scope, key, value)?;887888 self.consumed_space += value_len as u32;889890 Ok(())891 }892}893894pub struct CollectionProperties;895896impl Get<Properties> for CollectionProperties {897 fn get() -> Properties {898 Properties::new(MAX_COLLECTION_PROPERTIES_SIZE)899 }900}901902pub struct TokenProperties;903904impl Get<Properties> for TokenProperties {905 fn get() -> Properties {906 Properties::new(MAX_TOKEN_PROPERTIES_SIZE)907 }908}909910// RMRK911// todo document?912parameter_types! {913 #[derive(PartialEq, TypeInfo)]914 pub const RmrkStringLimit: u32 = 128;915 #[derive(PartialEq)]916 pub const RmrkCollectionSymbolLimit: u32 = 100;917 #[derive(PartialEq)]918 pub const RmrkResourceSymbolLimit: u32 = 10;919 #[derive(PartialEq)]920 pub const RmrkKeyLimit: u32 = 32;921 #[derive(PartialEq)]922 pub const RmrkValueLimit: u32 = 256;923 #[derive(PartialEq)]924 pub const RmrkMaxCollectionsEquippablePerPart: u32 = 100;925 #[derive(PartialEq)]926 pub const RmrkPartsLimit: u32 = 3;927}928929impl From<RmrkCollectionId> for CollectionId {930 fn from(id: RmrkCollectionId) -> Self {931 Self(id)932 }933}934935impl From<RmrkNftId> for TokenId {936 fn from(id: RmrkNftId) -> Self {937 Self(id)938 }939}940941pub type RmrkCollectionInfo<AccountId> =942 CollectionInfo<RmrkString, RmrkCollectionSymbol, AccountId>;943pub type RmrkInstanceInfo<AccountId> = NftInfo<AccountId, Permill, RmrkString>;944pub type RmrkResourceInfo = ResourceInfo<RmrkString, RmrkBoundedParts>;945pub type RmrkPropertyInfo = PropertyInfo<RmrkKeyString, RmrkValueString>;946pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;947pub type RmrkPartType =948 PartType<RmrkString, BoundedVec<RmrkCollectionId, RmrkMaxCollectionsEquippablePerPart>>;949pub type RmrkThemeProperty = ThemeProperty<RmrkString>;950pub type RmrkTheme = Theme<RmrkString, Vec<RmrkThemeProperty>>;951pub type RmrkResourceTypes = ResourceTypes<RmrkString, RmrkBoundedParts>;952953pub type RmrkBasicResource = BasicResource<RmrkString>;954pub type RmrkComposableResource = ComposableResource<RmrkString, RmrkBoundedParts>;955pub type RmrkSlotResource = SlotResource<RmrkString>;956957pub type RmrkString = BoundedVec<u8, RmrkStringLimit>;958pub type RmrkCollectionSymbol = BoundedVec<u8, RmrkCollectionSymbolLimit>;959pub type RmrkKeyString = BoundedVec<u8, RmrkKeyLimit>;960pub type RmrkValueString = BoundedVec<u8, RmrkValueLimit>;961pub type RmrkBoundedResource = BoundedVec<u8, RmrkResourceSymbolLimit>;962pub type RmrkBoundedParts = BoundedVec<RmrkPartId, RmrkPartsLimit>; // todo make sure it is needed963964pub type RmrkRpcString = Vec<u8>;965pub type RmrkThemeName = RmrkRpcString;966pub type RmrkPropertyKey = RmrkRpcString;1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![cfg_attr(not(feature = "std"), no_std)]1819use core::{20 convert::{TryFrom, TryInto},21 fmt,22};23use frame_support::{24 storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},25 traits::Get,26 parameter_types,27};2829#[cfg(feature = "serde")]30use serde::{Serialize, Deserialize};3132use sp_core::U256;33use sp_runtime::{ArithmeticError, sp_std::prelude::Vec, Permill};34use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};35use frame_support::{BoundedVec, traits::ConstU32};36use derivative::Derivative;37use scale_info::TypeInfo;3839pub mod rmrk;4041// RMRK42use rmrk::{43 CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme, ThemeProperty,44 ResourceTypes, BasicResource, ComposableResource, SlotResource,45};46pub use rmrk::{47 primitives::{48 CollectionId as RmrkCollectionId, NftId as RmrkNftId, BaseId as RmrkBaseId,49 PartId as RmrkPartId, ResourceId as RmrkResourceId,50 },51 NftChild as RmrkNftChild, AccountIdOrCollectionNftTuple as RmrkAccountIdOrCollectionNftTuple,52 FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart, EquippableList as RmrkEquippableList,53};5455mod bounded;56pub mod budget;57pub mod mapping;58mod migration;5960pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;61pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;62pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;6364pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {65 100_00066} else {67 1068};69pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {70 100_00071} else {72 1073};74pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {75 204876} else {77 1078};79pub const COLLECTION_ADMINS_LIMIT: u32 = 5;80pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;81pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {82 1_000_00083} else {84 1085};8687// Timeouts for item types in passed blocks88pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;89pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;90pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;9192pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;9394// Schema limits95pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;96pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;97pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;9899pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;100101pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;102pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;103pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;104105pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;106pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;107pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;108109pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;110pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;111112// RMRK constants113pub const RMRK_STRING_LIMIT: u32 = 128;114pub const RMRK_COLLECTION_SYMBOL_LIMIT: u32 = 100;115pub const RMRK_RESOURCE_SYMBOL_LIMIT: u32 = 10;116pub const RMRK_KEY_LIMIT: u32 = 32;117pub const RMRK_VALUE_LIMIT: u32 = 256;118119/// How much items can be created per single120/// create_many call121pub const MAX_ITEMS_PER_BATCH: u32 = 200;122123pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;124125#[derive(126 Encode,127 Decode,128 PartialEq,129 Eq,130 PartialOrd,131 Ord,132 Clone,133 Copy,134 Debug,135 Default,136 TypeInfo,137 MaxEncodedLen,138)]139#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]140pub struct CollectionId(pub u32);141impl EncodeLike<u32> for CollectionId {}142impl EncodeLike<CollectionId> for u32 {}143144#[derive(145 Encode,146 Decode,147 PartialEq,148 Eq,149 PartialOrd,150 Ord,151 Clone,152 Copy,153 Debug,154 Default,155 TypeInfo,156 MaxEncodedLen,157)]158#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]159pub struct TokenId(pub u32);160impl EncodeLike<u32> for TokenId {}161impl EncodeLike<TokenId> for u32 {}162163impl TokenId {164 pub fn try_next(self) -> Result<TokenId, ArithmeticError> {165 self.0166 .checked_add(1)167 .ok_or(ArithmeticError::Overflow)168 .map(Self)169 }170}171172impl From<TokenId> for U256 {173 fn from(t: TokenId) -> Self {174 t.0.into()175 }176}177178impl TryFrom<U256> for TokenId {179 type Error = &'static str;180181 fn try_from(value: U256) -> Result<Self, Self::Error> {182 Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))183 }184}185186#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]187#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]188pub struct TokenData<CrossAccountId> {189 pub properties: Vec<Property>,190 pub owner: Option<CrossAccountId>,191}192193pub struct OverflowError;194impl From<OverflowError> for &'static str {195 fn from(_: OverflowError) -> Self {196 "overflow occured"197 }198}199200pub type DecimalPoints = u8;201202#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]203#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]204pub enum CollectionMode {205 NFT,206 // decimal points207 Fungible(DecimalPoints),208 ReFungible,209}210211impl CollectionMode {212 pub fn id(&self) -> u8 {213 match self {214 CollectionMode::NFT => 1,215 CollectionMode::Fungible(_) => 2,216 CollectionMode::ReFungible => 3,217 }218 }219}220221pub trait SponsoringResolve<AccountId, Call> {222 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;223}224225#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]226#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]227pub enum AccessMode {228 Normal,229 AllowList,230}231impl Default for AccessMode {232 fn default() -> Self {233 Self::Normal234 }235}236237#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]238#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]239pub enum SchemaVersion {240 ImageURL,241 Unique,242}243impl Default for SchemaVersion {244 fn default() -> Self {245 Self::ImageURL246 }247}248249#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]250#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]251pub struct Ownership<AccountId> {252 pub owner: AccountId,253 pub fraction: u128,254}255256#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]257#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]258pub enum SponsorshipState<AccountId> {259 /// The fees are applied to the transaction sender260 Disabled,261 Unconfirmed(AccountId),262 /// Transactions are sponsored by specified account263 Confirmed(AccountId),264}265266impl<AccountId> SponsorshipState<AccountId> {267 pub fn sponsor(&self) -> Option<&AccountId> {268 match self {269 Self::Confirmed(sponsor) => Some(sponsor),270 _ => None,271 }272 }273274 pub fn pending_sponsor(&self) -> Option<&AccountId> {275 match self {276 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),277 _ => None,278 }279 }280281 pub fn confirmed(&self) -> bool {282 matches!(self, Self::Confirmed(_))283 }284}285286impl<T> Default for SponsorshipState<T> {287 fn default() -> Self {288 Self::Disabled289 }290}291292/// Used in storage293#[struct_versioning::versioned(version = 2, upper)]294#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]295pub struct Collection<AccountId> {296 pub owner: AccountId,297 pub mode: CollectionMode,298 #[version(..2)]299 pub access: AccessMode,300 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,301 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,302 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,303304 #[version(..2)]305 pub mint_mode: bool,306307 #[version(..2)]308 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,309310 #[version(..2)]311 pub schema_version: SchemaVersion,312 pub sponsorship: SponsorshipState<AccountId>,313314 pub limits: CollectionLimits,315316 #[version(2.., upper(Default::default()))]317 pub permissions: CollectionPermissions,318319 #[version(..2)]320 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,321322 #[version(..2)]323 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,324325 #[version(..2)]326 pub meta_update_permission: MetaUpdatePermission,327}328329/// Used in RPC calls330#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]331#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]332pub struct RpcCollection<AccountId> {333 pub owner: AccountId,334 pub mode: CollectionMode,335 pub name: Vec<u16>,336 pub description: Vec<u16>,337 pub token_prefix: Vec<u8>,338 pub sponsorship: SponsorshipState<AccountId>,339 pub limits: CollectionLimits,340 pub permissions: CollectionPermissions,341 pub token_property_permissions: Vec<PropertyKeyPermission>,342 pub properties: Vec<Property>,343}344345#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]346#[derivative(Debug, Default(bound = ""))]347pub struct CreateCollectionData<AccountId> {348 #[derivative(Default(value = "CollectionMode::NFT"))]349 pub mode: CollectionMode,350 pub access: Option<AccessMode>,351 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,352 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,353 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,354 pub pending_sponsor: Option<AccountId>,355 pub limits: Option<CollectionLimits>,356 pub permissions: Option<CollectionPermissions>,357 pub token_property_permissions: CollectionPropertiesPermissionsVec,358 pub properties: CollectionPropertiesVec,359}360361pub type CollectionPropertiesPermissionsVec =362 BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;363364pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;365366/// All fields are wrapped in `Option`s, where None means chain default367// When adding/removing fields from this struct - don't forget to also update clamp_limits368#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]369#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]370pub struct CollectionLimits {371 pub account_token_ownership_limit: Option<u32>,372 pub sponsored_data_size: Option<u32>,373374 /// FIXME should we delete this or repurpose it?375 /// None - setVariableMetadata is not sponsored376 /// Some(v) - setVariableMetadata is sponsored377 /// if there is v block between txs378 pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,379 pub token_limit: Option<u32>,380381 // Timeouts for item types in passed blocks382 pub sponsor_transfer_timeout: Option<u32>,383 pub sponsor_approve_timeout: Option<u32>,384 pub owner_can_transfer: Option<bool>,385 pub owner_can_destroy: Option<bool>,386 pub transfers_enabled: Option<bool>,387}388389impl CollectionLimits {390 pub fn account_token_ownership_limit(&self) -> u32 {391 self.account_token_ownership_limit392 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)393 .min(MAX_TOKEN_OWNERSHIP)394 }395 pub fn sponsored_data_size(&self) -> u32 {396 self.sponsored_data_size397 .unwrap_or(CUSTOM_DATA_LIMIT)398 .min(CUSTOM_DATA_LIMIT)399 }400 pub fn token_limit(&self) -> u32 {401 self.token_limit402 .unwrap_or(COLLECTION_TOKEN_LIMIT)403 .min(COLLECTION_TOKEN_LIMIT)404 }405 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {406 self.sponsor_transfer_timeout407 .unwrap_or(default)408 .min(MAX_SPONSOR_TIMEOUT)409 }410 pub fn sponsor_approve_timeout(&self) -> u32 {411 self.sponsor_approve_timeout412 .unwrap_or(SPONSOR_APPROVE_TIMEOUT)413 .min(MAX_SPONSOR_TIMEOUT)414 }415 pub fn owner_can_transfer(&self) -> bool {416 self.owner_can_transfer.unwrap_or(true)417 }418 pub fn owner_can_destroy(&self) -> bool {419 self.owner_can_destroy.unwrap_or(true)420 }421 pub fn transfers_enabled(&self) -> bool {422 self.transfers_enabled.unwrap_or(true)423 }424 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {425 match self426 .sponsored_data_rate_limit427 .unwrap_or(SponsoringRateLimit::SponsoringDisabled)428 {429 SponsoringRateLimit::SponsoringDisabled => None,430 SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),431 }432 }433}434435// When adding/removing fields from this struct - don't forget to also update clamp_limits436#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]437#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]438pub struct CollectionPermissions {439 pub access: Option<AccessMode>,440 pub mint_mode: Option<bool>,441 pub nesting: Option<NestingRule>,442}443444impl CollectionPermissions {445 pub fn access(&self) -> AccessMode {446 self.access.unwrap_or(AccessMode::Normal)447 }448 pub fn mint_mode(&self) -> bool {449 self.mint_mode.unwrap_or(false)450 }451 pub fn nesting(&self) -> &NestingRule {452 static DEFAULT: NestingRule = NestingRule::Disabled;453 self.nesting.as_ref().unwrap_or(&DEFAULT)454 }455}456457pub type OwnerRestrictedSet = BoundedBTreeSet<CollectionId, ConstU32<16>>;458459#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]460#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]461#[derivative(Debug)]462pub enum NestingRule {463 /// No one can nest tokens464 Disabled,465 /// Owner can nest any tokens466 Owner,467 /// Owner can nest tokens from specified collections468 OwnerRestricted(469 #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]470 #[derivative(Debug(format_with = "bounded::set_debug"))]471 OwnerRestrictedSet,472 ),473 /// Used for tests474 Permissive,475}476477#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]478#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]479pub enum SponsoringRateLimit {480 SponsoringDisabled,481 Blocks(u32),482}483484#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]485#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]486#[derivative(Debug)]487pub struct CreateNftData {488 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]489 #[derivative(Debug(format_with = "bounded::vec_debug"))]490 pub properties: CollectionPropertiesVec,491}492493#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]494#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]495pub struct CreateFungibleData {496 pub value: u128,497}498499#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]500#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]501#[derivative(Debug)]502pub struct CreateReFungibleData {503 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]504 #[derivative(Debug(format_with = "bounded::vec_debug"))]505 pub const_data: BoundedVec<u8, CustomDataLimit>,506 pub pieces: u128,507}508509#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]510#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]511pub enum MetaUpdatePermission {512 ItemOwner,513 Admin,514 None,515}516517#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]518#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]519pub enum CreateItemData {520 NFT(CreateNftData),521 Fungible(CreateFungibleData),522 ReFungible(CreateReFungibleData),523}524525#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]526#[derivative(Debug)]527pub struct CreateNftExData<CrossAccountId> {528 #[derivative(Debug(format_with = "bounded::vec_debug"))]529 pub properties: CollectionPropertiesVec,530 pub owner: CrossAccountId,531}532533#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]534#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]535pub struct CreateRefungibleExData<CrossAccountId> {536 #[derivative(Debug(format_with = "bounded::vec_debug"))]537 pub const_data: BoundedVec<u8, CustomDataLimit>,538 #[derivative(Debug(format_with = "bounded::map_debug"))]539 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,540}541542#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]543#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]544pub enum CreateItemExData<CrossAccountId> {545 NFT(546 #[derivative(Debug(format_with = "bounded::vec_debug"))]547 BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,548 ),549 Fungible(550 #[derivative(Debug(format_with = "bounded::map_debug"))]551 BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,552 ),553 /// Many tokens, each may have only one owner554 RefungibleMultipleItems(555 #[derivative(Debug(format_with = "bounded::vec_debug"))]556 BoundedVec<CreateRefungibleExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,557 ),558 /// Single token, which may have many owners559 RefungibleMultipleOwners(CreateRefungibleExData<CrossAccountId>),560}561562impl CreateItemData {563 pub fn data_size(&self) -> usize {564 match self {565 CreateItemData::ReFungible(data) => data.const_data.len(),566 _ => 0,567 }568 }569}570571impl From<CreateNftData> for CreateItemData {572 fn from(item: CreateNftData) -> Self {573 CreateItemData::NFT(item)574 }575}576577impl From<CreateReFungibleData> for CreateItemData {578 fn from(item: CreateReFungibleData) -> Self {579 CreateItemData::ReFungible(item)580 }581}582583impl From<CreateFungibleData> for CreateItemData {584 fn from(item: CreateFungibleData) -> Self {585 CreateItemData::Fungible(item)586 }587}588589#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]590#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]591// todo possibly rename to be used generally as an address pair592pub struct TokenChild {593 pub token: TokenId,594 pub collection: CollectionId,595}596597#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]598#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]599pub struct CollectionStats {600 pub created: u32,601 pub destroyed: u32,602 pub alive: u32,603}604605#[derive(Encode, Decode, Clone, Debug)]606#[cfg_attr(feature = "std", derive(PartialEq))]607pub struct PhantomType<T>(core::marker::PhantomData<T>);608609impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {610 type Identity = PhantomType<T>;611612 fn type_info() -> scale_info::Type {613 use scale_info::{614 Type, Path,615 build::{FieldsBuilder, UnnamedFields},616 type_params,617 };618 Type::builder()619 .path(Path::new("up_data_structs", "PhantomType"))620 .type_params(type_params!(T))621 .composite(<FieldsBuilder<UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()))622 }623}624impl<T> MaxEncodedLen for PhantomType<T> {625 fn max_encoded_len() -> usize {626 0627 }628}629630pub type PropertyKey = BoundedVec<u8, ConstU32<MAX_PROPERTY_KEY_LENGTH>>;631pub type PropertyValue = BoundedVec<u8, ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;632633#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]634#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]635pub struct PropertyPermission {636 pub mutable: bool,637 pub collection_admin: bool,638 pub token_owner: bool,639}640641impl PropertyPermission {642 pub fn none() -> Self {643 Self {644 mutable: true,645 collection_admin: false,646 token_owner: false,647 }648 }649}650651#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]652#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]653pub struct Property {654 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]655 pub key: PropertyKey,656657 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]658 pub value: PropertyValue,659}660661impl Into<(PropertyKey, PropertyValue)> for Property {662 fn into(self) -> (PropertyKey, PropertyValue) {663 (self.key, self.value)664 }665}666667#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]668#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]669pub struct PropertyKeyPermission {670 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]671 pub key: PropertyKey,672673 pub permission: PropertyPermission,674}675676impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {677 fn into(self) -> (PropertyKey, PropertyPermission) {678 (self.key, self.permission)679 }680}681682#[derive(Debug)]683pub enum PropertiesError {684 NoSpaceForProperty,685 PropertyLimitReached,686 InvalidCharacterInPropertyKey,687 PropertyKeyIsTooLong,688 EmptyPropertyKey,689}690691#[derive(Clone, Copy)]692pub enum PropertyScope {693 None,694 Rmrk,695}696697impl PropertyScope {698 pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {699 let scope_str: &[u8] = match self {700 Self::None => return Ok(key),701 Self::Rmrk => b"rmrk",702 };703704 [scope_str, b":", key.as_slice()]705 .concat()706 .try_into()707 .map_err(|_| PropertiesError::PropertyKeyIsTooLong)708 }709}710711pub trait TrySetProperty: Sized {712 type Value;713714 fn try_scoped_set(715 &mut self,716 scope: PropertyScope,717 key: PropertyKey,718 value: Self::Value,719 ) -> Result<(), PropertiesError>;720721 fn try_scoped_set_from_iter<I, KV>(722 &mut self,723 scope: PropertyScope,724 iter: I,725 ) -> Result<(), PropertiesError>726 where727 I: Iterator<Item = KV>,728 KV: Into<(PropertyKey, Self::Value)>,729 {730 for kv in iter {731 let (key, value) = kv.into();732 self.try_scoped_set(scope, key, value)?;733 }734735 Ok(())736 }737738 fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {739 self.try_scoped_set(PropertyScope::None, key, value)740 }741742 fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>743 where744 I: Iterator<Item = KV>,745 KV: Into<(PropertyKey, Self::Value)>,746 {747 self.try_scoped_set_from_iter(PropertyScope::None, iter)748 }749}750751#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]752#[derivative(Default(bound = ""))]753pub struct PropertiesMap<Value>(754 BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,755);756757impl<Value> PropertiesMap<Value> {758 pub fn new() -> Self {759 Self(BoundedBTreeMap::new())760 }761762 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {763 Self::check_property_key(key)?;764765 Ok(self.0.remove(key))766 }767768 pub fn get(&self, key: &PropertyKey) -> Option<&Value> {769 self.0.get(key)770 }771772 pub fn contains_key(&self, key: &PropertyKey) -> bool {773 self.0.contains_key(key)774 }775776 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {777 if key.is_empty() {778 return Err(PropertiesError::EmptyPropertyKey);779 }780781 for byte in key.as_slice().iter() {782 let byte = *byte;783784 if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' {785 return Err(PropertiesError::InvalidCharacterInPropertyKey);786 }787 }788789 Ok(())790 }791}792793impl<Value> IntoIterator for PropertiesMap<Value> {794 type Item = (PropertyKey, Value);795 type IntoIter = <796 BoundedBTreeMap<797 PropertyKey,798 Value,799 ConstU32<MAX_PROPERTIES_PER_ITEM>800 > as IntoIterator801 >::IntoIter;802803 fn into_iter(self) -> Self::IntoIter {804 self.0.into_iter()805 }806}807808impl<Value> TrySetProperty for PropertiesMap<Value> {809 type Value = Value;810811 fn try_scoped_set(812 &mut self,813 scope: PropertyScope,814 key: PropertyKey,815 value: Self::Value,816 ) -> Result<(), PropertiesError> {817 Self::check_property_key(&key)?;818819 let key = scope.apply(key)?;820 self.0821 .try_insert(key, value)822 .map_err(|_| PropertiesError::PropertyLimitReached)?;823824 Ok(())825 }826}827828pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;829830#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, MaxEncodedLen)]831pub struct Properties {832 map: PropertiesMap<PropertyValue>,833 consumed_space: u32,834 space_limit: u32,835}836837impl Properties {838 pub fn new(space_limit: u32) -> Self {839 Self {840 map: PropertiesMap::new(),841 consumed_space: 0,842 space_limit,843 }844 }845846 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {847 let value = self.map.remove(key)?;848849 if let Some(ref value) = value {850 let value_len = value.len() as u32;851 self.consumed_space -= value_len;852 }853854 Ok(value)855 }856857 pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {858 self.map.get(key)859 }860}861862impl IntoIterator for Properties {863 type Item = (PropertyKey, PropertyValue);864 type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;865866 fn into_iter(self) -> Self::IntoIter {867 self.map.into_iter()868 }869}870871impl TrySetProperty for Properties {872 type Value = PropertyValue;873874 fn try_scoped_set(875 &mut self,876 scope: PropertyScope,877 key: PropertyKey,878 value: Self::Value,879 ) -> Result<(), PropertiesError> {880 let value_len = value.len();881882 if self.consumed_space as usize + value_len > self.space_limit as usize883 && !cfg!(feature = "runtime-benchmarks")884 {885 return Err(PropertiesError::NoSpaceForProperty);886 }887888 self.map.try_scoped_set(scope, key, value)?;889890 self.consumed_space += value_len as u32;891892 Ok(())893 }894}895896pub struct CollectionProperties;897898impl Get<Properties> for CollectionProperties {899 fn get() -> Properties {900 Properties::new(MAX_COLLECTION_PROPERTIES_SIZE)901 }902}903904pub struct TokenProperties;905906impl Get<Properties> for TokenProperties {907 fn get() -> Properties {908 Properties::new(MAX_TOKEN_PROPERTIES_SIZE)909 }910}911912// RMRK913// todo document?914parameter_types! {915 #[derive(PartialEq, TypeInfo)]916 pub const RmrkStringLimit: u32 = 128;917 #[derive(PartialEq)]918 pub const RmrkCollectionSymbolLimit: u32 = 100;919 #[derive(PartialEq)]920 pub const RmrkResourceSymbolLimit: u32 = 10;921 #[derive(PartialEq)]922 pub const RmrkKeyLimit: u32 = 32;923 #[derive(PartialEq)]924 pub const RmrkValueLimit: u32 = 256;925 #[derive(PartialEq)]926 pub const RmrkMaxCollectionsEquippablePerPart: u32 = 100;927 #[derive(PartialEq)]928 pub const RmrkPartsLimit: u32 = 3;929}930931impl From<RmrkCollectionId> for CollectionId {932 fn from(id: RmrkCollectionId) -> Self {933 Self(id)934 }935}936937impl From<RmrkNftId> for TokenId {938 fn from(id: RmrkNftId) -> Self {939 Self(id)940 }941}942943pub type RmrkCollectionInfo<AccountId> =944 CollectionInfo<RmrkString, RmrkCollectionSymbol, AccountId>;945pub type RmrkInstanceInfo<AccountId> = NftInfo<AccountId, Permill, RmrkString>;946pub type RmrkResourceInfo = ResourceInfo<RmrkString, RmrkBoundedParts>;947pub type RmrkPropertyInfo = PropertyInfo<RmrkKeyString, RmrkValueString>;948pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;949pub type RmrkPartType =950 PartType<RmrkString, BoundedVec<RmrkCollectionId, RmrkMaxCollectionsEquippablePerPart>>;951pub type RmrkThemeProperty = ThemeProperty<RmrkString>;952pub type RmrkTheme = Theme<RmrkString, Vec<RmrkThemeProperty>>;953pub type RmrkResourceTypes = ResourceTypes<RmrkString, RmrkBoundedParts>;954955pub type RmrkBasicResource = BasicResource<RmrkString>;956pub type RmrkComposableResource = ComposableResource<RmrkString, RmrkBoundedParts>;957pub type RmrkSlotResource = SlotResource<RmrkString>;958959pub type RmrkString = BoundedVec<u8, RmrkStringLimit>;960pub type RmrkCollectionSymbol = BoundedVec<u8, RmrkCollectionSymbolLimit>;961pub type RmrkKeyString = BoundedVec<u8, RmrkKeyLimit>;962pub type RmrkValueString = BoundedVec<u8, RmrkValueLimit>;963pub type RmrkBoundedResource = BoundedVec<u8, RmrkResourceSymbolLimit>;964pub type RmrkBoundedParts = BoundedVec<RmrkPartId, RmrkPartsLimit>; // todo make sure it is needed965966pub type RmrkRpcString = Vec<u8>;967pub type RmrkThemeName = RmrkRpcString;968pub type RmrkPropertyKey = RmrkRpcString;tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -42,6 +42,51 @@
event MintingFinished();
}
+// Selector: 3a54513b
+interface Collection is Dummy, ERC165 {
+ // Selector: setCollectionProperty(string,bytes) 2f073f66
+ function setCollectionProperty(string memory key, bytes memory value)
+ external;
+
+ // Selector: deleteCollectionProperty(string) 7b7debce
+ function deleteCollectionProperty(string memory key) external;
+
+ // Throws error if key not found
+ //
+ // Selector: collectionProperty(string) cf24fd6d
+ function collectionProperty(string memory key)
+ external
+ view
+ returns (bytes memory);
+
+ // Selector: ethSetSponsor(address) 8f9af356
+ function ethSetSponsor(address sponsor) external;
+
+ // Selector: ethConfirmSponsorship() a8580d1a
+ function ethConfirmSponsorship() external;
+
+ // Selector: setLimit(string,uint32) 68db30ca
+ function setLimit(string memory limit, uint32 value) external;
+
+ // Selector: setLimit(string,bool) ea67e4c2
+ function setLimit(string memory limit, bool value) external;
+
+ // Selector: contractAddress() f6b4dfb4
+ function contractAddress() external view returns (address);
+
+ // Selector: addAdmin(address) 70480275
+ function addAdmin(address newAdmin) external view;
+
+ // Selector: removeAdmin(address) 1785f53c
+ function removeAdmin(address admin) external view;
+
+ // Selector: setNesting(bool) e8fc50dd
+ function setNesting(bool enable) external;
+
+ // Selector: setNesting(bool,address[]) 7df12a9a
+ function setNesting(bool enable, address[] memory collections) external;
+}
+
// Selector: 41369377
interface TokenProperties is Dummy, ERC165 {
// Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
@@ -189,39 +234,6 @@
// Selector: totalSupply() 18160ddd
function totalSupply() external view returns (uint256);
-}
-
-// Selector: c894dc35
-interface Collection is Dummy, ERC165 {
- // Selector: setCollectionProperty(string,bytes) 2f073f66
- function setCollectionProperty(string memory key, bytes memory value)
- external;
-
- // Selector: deleteCollectionProperty(string) 7b7debce
- function deleteCollectionProperty(string memory key) external;
-
- // Throws error if key not found
- //
- // Selector: collectionProperty(string) cf24fd6d
- function collectionProperty(string memory key)
- external
- view
- returns (bytes memory);
-
- // Selector: ethSetSponsor(address) 8f9af356
- function ethSetSponsor(address sponsor) external;
-
- // Selector: ethConfirmSponsorship() a8580d1a
- function ethConfirmSponsorship() external;
-
- // Selector: setLimit(string,uint32) 68db30ca
- function setLimit(string memory limit, uint32 value) external;
-
- // Selector: setLimit(string,bool) ea67e4c2
- function setLimit(string memory limit, bool value) external;
-
- // Selector: contractAddress() f6b4dfb4
- function contractAddress() external view returns (address);
}
// Selector: d74d154f
tests/src/eth/createCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createCollection.test.ts
+++ b/tests/src/eth/createCollection.test.ts
@@ -30,13 +30,13 @@
describe('Create collection from EVM', () => {
itWeb3('Create collection', async ({api, web3}) => {
const owner = await createEthAccountWithBalance(api, web3);
- const helper = evmCollectionHelpers(web3, owner);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
const collectionName = 'CollectionEVM';
const description = 'Some description';
const tokenPrefix = 'token prefix';
const collectionCountBefore = await getCreatedCollectionCount(api);
- const result = await helper.methods
+ const result = await collectionHelper.methods
.createNonfungibleCollection(collectionName, description, tokenPrefix)
.send();
const collectionCountAfter = await getCreatedCollectionCount(api);
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -82,6 +82,15 @@
},
{
"inputs": [
+ { "internalType": "address", "name": "newAdmin", "type": "address" }
+ ],
+ "name": "addAdmin",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "approved", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
],
@@ -282,6 +291,15 @@
},
{
"inputs": [
+ { "internalType": "address", "name": "admin", "type": "address" }
+ ],
+ "name": "removeAdmin",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
@@ -345,6 +363,27 @@
},
{
"inputs": [
+ { "internalType": "bool", "name": "enable", "type": "bool" },
+ {
+ "internalType": "address[]",
+ "name": "collections",
+ "type": "address[]"
+ }
+ ],
+ "name": "setNesting",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],
+ "name": "setNesting",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" },
{ "internalType": "string", "name": "key", "type": "string" },
{ "internalType": "bytes", "name": "value", "type": "bytes" }
tests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth--- a/tests/src/eth/proxy/nonFungibleProxy.test.ts
+++ b/tests/src/eth/proxy/nonFungibleProxy.test.ts
@@ -15,7 +15,7 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {createCollectionExpectSuccess, createItemExpectSuccess} from '../../util/helpers';
-import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents} from '../util/helpers';
+import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents} from '../util/helpers';
import nonFungibleAbi from '../nonFungibleAbi.json';
import {expect} from 'chai';
import {submitTransactionAsync} from '../../substrate/substrate-api';
@@ -87,20 +87,19 @@
});
describe('NFT (Via EVM proxy): Plain calls', () => {
- //TODO: CORE-302 add eth methods
- itWeb3.skip('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
+ itWeb3('Can perform mint()', async ({web3, api}) => {
+ const owner = await createEthAccountWithBalance(api, web3);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'A', 'A')
+ .send();
+ const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const caller = await createEthAccountWithBalance(api, web3);
const receiver = createEthAccount(web3);
-
- const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
-
- const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
- await submitTransactionAsync(alice, changeAdminTx);
+ const collectionEvmOwned = evmCollection(web3, owner, collectionIdAddress);
+ const collectionEvm = evmCollection(web3, caller, collectionIdAddress);
+ const contract = await proxyWrap(api, web3, collectionEvm);
+ await collectionEvmOwned.methods.addAdmin(contract.options.address).send();
{
const nextTokenId = await contract.methods.nextTokenId().call();
@@ -111,10 +110,11 @@
'Test URI',
).send({from: caller});
const events = normalizeEvents(result.events);
+ events[0].address = events[0].address.toLocaleLowerCase();
expect(events).to.be.deep.equal([
{
- address,
+ address: collectionIdAddress.toLocaleLowerCase(),
event: 'Transfer',
args: {
from: '0x0000000000000000000000000000000000000000',
tests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-rpc.ts
+++ b/tests/src/interfaces/augment-api-rpc.ts
@@ -18,7 +18,7 @@
import type { EthAccount, EthCallRequest, EthFilter, EthFilterChanges, EthLog, EthReceipt, EthRichBlock, EthSubKind, EthSubParams, EthSyncStatus, EthTransaction, EthTransactionRequest, EthWork } from '@polkadot/types/interfaces/eth';
import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics';
import type { EncodedFinalityProofs, JustificationNotification, ReportedRoundStates } from '@polkadot/types/interfaces/grandpa';
-import type { MmrLeafBatchProof, MmrLeafProof } from '@polkadot/types/interfaces/mmr';
+import type { MmrLeafProof } from '@polkadot/types/interfaces/mmr';
import type { StorageKind } from '@polkadot/types/interfaces/offchain';
import type { FeeDetails, RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment';
import type { RpcMethods } from '@polkadot/types/interfaces/rpc';
@@ -354,14 +354,10 @@
subscribeJustifications: AugmentedRpc<() => Observable<JustificationNotification>>;
};
mmr: {
- /**
- * Generate MMR proof for the given leaf indices.
- **/
- generateBatchProof: AugmentedRpc<(leafIndices: Vec<u64> | (u64 | AnyNumber | Uint8Array)[], at?: BlockHash | string | Uint8Array) => Observable<MmrLeafProof>>;
/**
* Generate MMR proof for given leaf index.
**/
- generateProof: AugmentedRpc<(leafIndex: u64 | AnyNumber | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<MmrLeafBatchProof>>;
+ generateProof: AugmentedRpc<(leafIndex: u64 | AnyNumber | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<MmrLeafProof>>;
};
net: {
/**
tests/src/interfaces/augment-types.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -3,7 +3,7 @@
import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletXcmCall, PalletXcmError, PalletXcmEvent, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingRule, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRmrkAccountIdOrCollectionNftTuple, UpDataStructsRmrkBaseInfo, UpDataStructsRmrkBasicResource, UpDataStructsRmrkCollectionInfo, UpDataStructsRmrkComposableResource, UpDataStructsRmrkEquippableList, UpDataStructsRmrkFixedPart, UpDataStructsRmrkNftChild, UpDataStructsRmrkNftInfo, UpDataStructsRmrkPartType, UpDataStructsRmrkPropertyInfo, UpDataStructsRmrkResourceInfo, UpDataStructsRmrkResourceTypes, UpDataStructsRmrkRoyaltyInfo, UpDataStructsRmrkSlotPart, UpDataStructsRmrkSlotResource, UpDataStructsRmrkTheme, UpDataStructsRmrkThemeProperty, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
import type { Data, StorageKey } from '@polkadot/types';
-import type { BitVec, Bool, Bytes, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec';
+import type { BitVec, Bool, Bytes, I128, I16, I256, I32, I64, I8, Json, Null, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec';
import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';
import type { BlockAttestations, IncludedBlocks, MoreAttestations } from '@polkadot/types/interfaces/attestations';
import type { RawAuraPreDigest } from '@polkadot/types/interfaces/aura';
@@ -36,7 +36,7 @@
import type { AuthIndex, AuthoritySignature, Heartbeat, HeartbeatTo244, OpaqueMultiaddr, OpaqueNetworkState, OpaquePeerId } from '@polkadot/types/interfaces/imOnline';
import type { CallIndex, LotteryConfig } from '@polkadot/types/interfaces/lottery';
import type { ErrorMetadataLatest, ErrorMetadataV10, ErrorMetadataV11, ErrorMetadataV12, ErrorMetadataV13, ErrorMetadataV14, ErrorMetadataV9, EventMetadataLatest, EventMetadataV10, EventMetadataV11, EventMetadataV12, EventMetadataV13, EventMetadataV14, EventMetadataV9, ExtrinsicMetadataLatest, ExtrinsicMetadataV11, ExtrinsicMetadataV12, ExtrinsicMetadataV13, ExtrinsicMetadataV14, FunctionArgumentMetadataLatest, FunctionArgumentMetadataV10, FunctionArgumentMetadataV11, FunctionArgumentMetadataV12, FunctionArgumentMetadataV13, FunctionArgumentMetadataV14, FunctionArgumentMetadataV9, FunctionMetadataLatest, FunctionMetadataV10, FunctionMetadataV11, FunctionMetadataV12, FunctionMetadataV13, FunctionMetadataV14, FunctionMetadataV9, MetadataAll, MetadataLatest, MetadataV10, MetadataV11, MetadataV12, MetadataV13, MetadataV14, MetadataV9, ModuleConstantMetadataV10, ModuleConstantMetadataV11, ModuleConstantMetadataV12, ModuleConstantMetadataV13, ModuleConstantMetadataV9, ModuleMetadataV10, ModuleMetadataV11, ModuleMetadataV12, ModuleMetadataV13, ModuleMetadataV9, PalletCallMetadataLatest, PalletCallMetadataV14, PalletConstantMetadataLatest, PalletConstantMetadataV14, PalletErrorMetadataLatest, PalletErrorMetadataV14, PalletEventMetadataLatest, PalletEventMetadataV14, PalletMetadataLatest, PalletMetadataV14, PalletStorageMetadataLatest, PalletStorageMetadataV14, PortableType, PortableTypeV14, SignedExtensionMetadataLatest, SignedExtensionMetadataV14, StorageEntryMetadataLatest, StorageEntryMetadataV10, StorageEntryMetadataV11, StorageEntryMetadataV12, StorageEntryMetadataV13, StorageEntryMetadataV14, StorageEntryMetadataV9, StorageEntryModifierLatest, StorageEntryModifierV10, StorageEntryModifierV11, StorageEntryModifierV12, StorageEntryModifierV13, StorageEntryModifierV14, StorageEntryModifierV9, StorageEntryTypeLatest, StorageEntryTypeV10, StorageEntryTypeV11, StorageEntryTypeV12, StorageEntryTypeV13, StorageEntryTypeV14, StorageEntryTypeV9, StorageHasher, StorageHasherV10, StorageHasherV11, StorageHasherV12, StorageHasherV13, StorageHasherV14, StorageHasherV9, StorageMetadataV10, StorageMetadataV11, StorageMetadataV12, StorageMetadataV13, StorageMetadataV9 } from '@polkadot/types/interfaces/metadata';
-import type { MmrLeafBatchProof, MmrLeafProof } from '@polkadot/types/interfaces/mmr';
+import type { MmrLeafProof } from '@polkadot/types/interfaces/mmr';
import type { StorageKind } from '@polkadot/types/interfaces/offchain';
import type { DeferredOffenceOf, Kind, OffenceDetails, Offender, OpaqueTimeSlot, ReportIdOf, Reporter } from '@polkadot/types/interfaces/offences';
import type { AbridgedCandidateReceipt, AbridgedHostConfiguration, AbridgedHrmpChannel, AssignmentId, AssignmentKind, AttestedCandidate, AuctionIndex, AuthorityDiscoveryId, AvailabilityBitfield, AvailabilityBitfieldRecord, BackedCandidate, Bidder, BufferedSessionChange, CandidateCommitments, CandidateDescriptor, CandidateHash, CandidateInfo, CandidatePendingAvailability, CandidateReceipt, CollatorId, CollatorSignature, CommittedCandidateReceipt, CoreAssignment, CoreIndex, CoreOccupied, DisputeLocation, DisputeResult, DisputeState, DisputeStatement, DisputeStatementSet, DoubleVoteReport, DownwardMessage, ExplicitDisputeStatement, GlobalValidationData, GlobalValidationSchedule, GroupIndex, HeadData, HostConfiguration, HrmpChannel, HrmpChannelId, HrmpOpenChannelRequest, InboundDownwardMessage, InboundHrmpMessage, InboundHrmpMessages, IncomingParachain, IncomingParachainDeploy, IncomingParachainFixed, InvalidDisputeStatementKind, LeasePeriod, LeasePeriodOf, LocalValidationData, MessageIngestionType, MessageQueueChain, MessagingStateSnapshot, MessagingStateSnapshotEgressEntry, MultiDisputeStatementSet, NewBidder, OutboundHrmpMessage, ParaGenesisArgs, ParaId, ParaInfo, ParaLifecycle, ParaPastCodeMeta, ParaScheduling, ParaValidatorIndex, ParachainDispatchOrigin, ParachainInherentData, ParachainProposal, ParachainsInherentData, ParathreadClaim, ParathreadClaimQueue, ParathreadEntry, PersistedValidationData, QueuedParathread, RegisteredParachainInfo, RelayBlockNumber, RelayChainBlockNumber, RelayChainHash, RelayHash, Remark, ReplacementTimes, Retriable, Scheduling, ServiceQuality, SessionInfo, SessionInfoValidatorGroup, SignedAvailabilityBitfield, SignedAvailabilityBitfields, SigningContext, SlotRange, SlotRange10, Statement, SubId, SystemInherentData, TransientValidationData, UpgradeGoAhead, UpgradeRestriction, UpwardMessage, ValidDisputeStatementKind, ValidationCode, ValidationCodeHash, ValidationData, ValidationDataType, ValidationFunctionParams, ValidatorSignature, ValidityAttestation, VecInboundHrmpMessage, WinnersData, WinnersData10, WinnersDataTuple, WinnersDataTuple10, WinningData, WinningData10, WinningDataEntry } from '@polkadot/types/interfaces/parachains';
@@ -661,7 +661,6 @@
MetadataV14: MetadataV14;
MetadataV9: MetadataV9;
MigrationStatusResult: MigrationStatusResult;
- MmrLeafBatchProof: MmrLeafBatchProof;
MmrLeafProof: MmrLeafProof;
MmrRootHash: MmrRootHash;
ModuleConstantMetadataV10: ModuleConstantMetadataV10;
@@ -728,7 +727,6 @@
OpenTipTip: OpenTipTip;
OpenTipTo225: OpenTipTo225;
OperatingMode: OperatingMode;
- OptionBool: OptionBool;
Origin: Origin;
OriginCaller: OriginCaller;
OriginKindV0: OriginKindV0;