difftreelog
Merge pull request #65 from usetech-llc/feature/NFTPAR-288
in: master
Feature/nftpar 288
3 files changed
node/src/chain_spec.rsdiffbeforeafterboth1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56// use nft_runtime::{7// AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig,8// SystemConfig, WASM_BINARY,9// };10// use nft_runtime::{ContractsConfig, ContractsSchedule, NftConfig, CollectionType};11use nft_runtime::*;12use sc_service::ChainType;13use sp_consensus_aura::sr25519::AuthorityId as AuraId;14use sp_core::{sr25519, Pair, Public};15use sp_finality_grandpa::AuthorityId as GrandpaId;16use sp_runtime::traits::{IdentifyAccount, Verify};17use serde_json::map::Map;1819// Note this is the URL for the telemetry server20//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";2122/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.23pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;2425/// Helper function to generate a crypto pair from seed26pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {27 TPublic::Pair::from_string(&format!("//{}", seed), None)28 .expect("static values are valid; qed")29 .public()30}3132type AccountPublic = <Signature as Verify>::Signer;3334/// Helper function to generate an account ID from seed35pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId36where37 AccountPublic: From<<TPublic::Pair as Pair>::Public>,38{39 AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()40}4142/// Helper function to generate an authority key for Aura43pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) {44 (get_from_seed::<AuraId>(s), get_from_seed::<GrandpaId>(s))45}4647pub fn development_config() -> Result<ChainSpec, String> {48 let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?;4950 let mut properties = Map::new();51 properties.insert("tokenSymbol".into(), "UniqueTest".into());52 properties.insert("tokenDecimals".into(), 15.into());53 properties.insert("ss58Format".into(), 42.into()); // Generic Substrate wildcard (SS58 checksum preimage)5455 Ok(ChainSpec::from_genesis(56 // Name57 "Development",58 // ID59 "dev",60 ChainType::Development,61 move || testnet_genesis(62 wasm_binary,63 // Initial PoA authorities64 vec![65 authority_keys_from_seed("Alice"),66 ],67 // Sudo account68 get_account_id_from_seed::<sr25519::Public>("Alice"),69 // Pre-funded accounts70 vec![71 get_account_id_from_seed::<sr25519::Public>("Alice"),72 get_account_id_from_seed::<sr25519::Public>("Bob"),73 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),74 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),75 ],76 true,77 ),78 // Bootnodes79 vec![],80 // Telemetry81 None,82 // Protocol ID83 None,84 // Properties85 Some(properties),86 // Extensions87 None,88 ))89}9091pub fn local_testnet_config() -> Result<ChainSpec, String> {92 let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?;9394 Ok(ChainSpec::from_genesis(95 // Name96 "Local Testnet",97 // ID98 "local_testnet",99 ChainType::Local,100 move || testnet_genesis(101 wasm_binary,102 // Initial PoA authorities103 vec![104 authority_keys_from_seed("Alice"),105 authority_keys_from_seed("Bob"),106 ],107 // Sudo account108 get_account_id_from_seed::<sr25519::Public>("Alice"),109 // Pre-funded accounts110 vec![111 get_account_id_from_seed::<sr25519::Public>("Alice"),112 get_account_id_from_seed::<sr25519::Public>("Bob"),113 get_account_id_from_seed::<sr25519::Public>("Charlie"),114 get_account_id_from_seed::<sr25519::Public>("Dave"),115 get_account_id_from_seed::<sr25519::Public>("Eve"),116 get_account_id_from_seed::<sr25519::Public>("Ferdie"),117 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),118 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),119 get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),120 get_account_id_from_seed::<sr25519::Public>("Dave//stash"),121 get_account_id_from_seed::<sr25519::Public>("Eve//stash"),122 get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),123 ],124 true,125 ),126 // Bootnodes127 vec![],128 // Telemetry129 None,130 // Protocol ID131 None,132 // Properties133 None,134 // Extensions135 None,136 ))137}138139fn testnet_genesis(140 wasm_binary: &[u8],141 initial_authorities: Vec<(AuraId, GrandpaId)>,142 root_key: AccountId,143 endowed_accounts: Vec<AccountId>,144 enable_println: bool,145) -> GenesisConfig {146147 let vested_accounts = vec![148 get_account_id_from_seed::<sr25519::Public>("Bob"),149 ];150151 GenesisConfig {152 system: Some(SystemConfig {153 code: wasm_binary.to_vec(),154 changes_trie_config: Default::default(),155 }),156 pallet_balances: Some(BalancesConfig {157 balances: endowed_accounts158 .iter()159 .cloned()160 .map(|k| (k, 1 << 100))161 .collect(),162 }),163 pallet_aura: Some(AuraConfig {164 authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),165 }),166 pallet_grandpa: Some(GrandpaConfig {167 authorities: initial_authorities168 .iter()169 .map(|x| (x.1.clone(), 1))170 .collect(),171 }),172 pallet_treasury: Some(Default::default()),173 pallet_sudo: Some(SudoConfig { key: root_key }),174 pallet_vesting: Some(VestingConfig {175 vesting: vested_accounts176 .iter()177 .cloned()178 .map(|k| (k, 1000, 100, 1 << 98))179 .collect(),180 }),181 pallet_nft: Some(NftConfig {182 collection: vec![(183 1,184 CollectionType {185 owner: get_account_id_from_seed::<sr25519::Public>("Alice"),186 mode: CollectionMode::NFT,187 access: AccessMode::Normal,188 decimal_points: 0,189 name: vec![],190 description: vec![],191 token_prefix: vec![],192 mint_mode: false,193 offchain_schema: vec![],194 schema_version: SchemaVersion::default(),195 sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),196 sponsor_confirmed: true,197 const_on_chain_schema: vec![],198 variable_on_chain_schema: vec![],199 limits: CollectionLimits::default()200 },201 )],202 nft_item_id: vec![],203 fungible_item_id: vec![],204 refungible_item_id: vec![],205 chain_limit: ChainLimits {206 collection_numbers_limit: 100000,207 account_token_ownership_limit: 1000000,208 collections_admins_limit: 5,209 custom_data_limit: 2048,210 nft_sponsor_transfer_timeout: 15,211 fungible_sponsor_transfer_timeout: 15,212 refungible_sponsor_transfer_timeout: 15,213 },214 }),215 pallet_contracts: Some(ContractsConfig {216 current_schedule: ContractsSchedule {217 enable_println,218 ..Default::default()219 },220 }),221 }222}pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -74,6 +74,12 @@
ReFungible(DecimalPoints),
}
+impl Default for CollectionMode {
+ fn default() -> Self {
+ Self::Invalid
+ }
+}
+
impl Into<u8> for CollectionMode {
fn into(self) -> u8 {
match self {
@@ -97,12 +103,6 @@
}
}
-impl Default for CollectionMode {
- fn default() -> Self {
- Self::Invalid
- }
-}
-
#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum SchemaVersion {
@@ -208,6 +208,11 @@
pub nft_sponsor_transfer_timeout: u32,
pub fungible_sponsor_transfer_timeout: u32,
pub refungible_sponsor_transfer_timeout: u32,
+
+ // Schema limits
+ pub offchain_schema_limit: u32,
+ pub variable_on_chain_schema_limit: u32,
+ pub const_on_chain_schema_limit: u32,
}
pub trait WeightInfo {
@@ -367,7 +372,9 @@
/// Account token limit exceeded per collection
AccountTokenLimitExceeded,
/// Collection limit bounds per collection exceeded
- CollectionLimitBoundsExceeded
+ CollectionLimitBoundsExceeded,
+ /// Schema data size limit bound exceeded
+ SchemaDataLimitExceeded
}
}
@@ -1281,6 +1288,9 @@
let sender = ensure_signed(origin)?;
Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+ // check schema limit
+ ensure!(schema.len() as u32 > ChainLimit::get().offchain_schema_limit, "");
+
let mut target_collection = <Collection<T>>::get(collection_id);
target_collection.offchain_schema = schema;
<Collection<T>>::insert(collection_id, target_collection);
@@ -1309,6 +1319,9 @@
let sender = ensure_signed(origin)?;
Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+ // check schema limit
+ ensure!(schema.len() as u32 > ChainLimit::get().const_on_chain_schema_limit, "");
+
let mut target_collection = <Collection<T>>::get(collection_id);
target_collection.const_on_chain_schema = schema;
<Collection<T>>::insert(collection_id, target_collection);
@@ -1337,6 +1350,9 @@
let sender = ensure_signed(origin)?;
Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+ // check schema limit
+ ensure!(schema.len() as u32 > ChainLimit::get().variable_on_chain_schema_limit, "");
+
let mut target_collection = <Collection<T>>::get(collection_id);
target_collection.variable_on_chain_schema = schema;
<Collection<T>>::insert(collection_id, target_collection);
pallets/nft/src/types.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/nft/src/types.rs
@@ -0,0 +1,234 @@
+#[cfg(feature = "std")]
+pub use std::*;
+
+#[cfg(feature = "std")]
+pub use serde::*;
+
+use codec::{Decode, Encode};
+
+pub type CollectionId = u32;
+pub type TokenId = u32;
+pub type DecimalPoints = u8;
+
+#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub enum CollectionMode {
+ Invalid,
+ NFT,
+ // decimal points
+ Fungible(DecimalPoints),
+ // decimal points
+ ReFungible(DecimalPoints),
+}
+
+impl Into<u8> for CollectionMode {
+ fn into(self) -> u8 {
+ match self {
+ CollectionMode::Invalid => 0,
+ CollectionMode::NFT => 1,
+ CollectionMode::Fungible(_) => 2,
+ CollectionMode::ReFungible(_) => 3,
+ }
+ }
+}
+
+#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub enum AccessMode {
+ Normal,
+ WhiteList,
+}
+impl Default for AccessMode {
+ fn default() -> Self {
+ Self::Normal
+ }
+}
+
+impl Default for CollectionMode {
+ fn default() -> Self {
+ Self::Invalid
+ }
+}
+
+#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub enum SchemaVersion {
+ ImageURL,
+ Unique,
+}
+impl Default for SchemaVersion {
+ fn default() -> Self {
+ Self::ImageURL
+ }
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct Ownership<AccountId> {
+ pub owner: AccountId,
+ pub fraction: u128,
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct CollectionType<AccountId> {
+ pub owner: AccountId,
+ pub mode: CollectionMode,
+ pub access: AccessMode,
+ pub decimal_points: DecimalPoints,
+ pub name: Vec<u16>, // 64 include null escape char
+ pub description: Vec<u16>, // 256 include null escape char
+ pub token_prefix: Vec<u8>, // 16 include null escape char
+ pub mint_mode: bool,
+ pub offchain_schema: Vec<u8>,
+ pub schema_version: SchemaVersion,
+ pub sponsor: AccountId, // Who pays fees. If set to default address, the fees are applied to the transaction sender
+ pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship
+ pub limits: CollectionLimits, // Collection private restrictions
+ pub variable_on_chain_schema: Vec<u8>, //
+ pub const_on_chain_schema: Vec<u8>, //
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct NftItemType<AccountId> {
+ pub collection: CollectionId,
+ pub owner: AccountId,
+ pub const_data: Vec<u8>,
+ pub variable_data: Vec<u8>,
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct FungibleItemType<AccountId> {
+ pub collection: CollectionId,
+ pub owner: AccountId,
+ pub value: u128,
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct ReFungibleItemType<AccountId> {
+ pub collection: CollectionId,
+ pub owner: Vec<Ownership<AccountId>>,
+ pub const_data: Vec<u8>,
+ pub variable_data: Vec<u8>,
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct ApprovePermissions<AccountId> {
+ pub approved: AccountId,
+ pub amount: u128,
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct VestingItem<AccountId, Moment> {
+ pub sender: AccountId,
+ pub recipient: AccountId,
+ pub collection_id: CollectionId,
+ pub item_id: TokenId,
+ pub amount: u64,
+ pub vesting_date: Moment,
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct BasketItem<AccountId, BlockNumber> {
+ pub address: AccountId,
+ pub start_block: BlockNumber,
+}
+
+#[derive(Encode, Decode, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct CollectionLimits {
+ pub account_token_ownership_limit: u32,
+ pub sponsored_data_size: u32,
+ pub token_limit: u32,
+
+ // Timeouts for item types in passed blocks
+ pub sponsor_transfer_timeout: u32,
+}
+
+impl Default for CollectionLimits {
+ fn default() -> CollectionLimits {
+ CollectionLimits {
+ account_token_ownership_limit: 10_000_000,
+ token_limit: u32::max_value(),
+ sponsored_data_size: u32::max_value(),
+ sponsor_transfer_timeout: 14400 }
+ }
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct ChainLimits {
+ pub collection_numbers_limit: u32,
+ pub account_token_ownership_limit: u32,
+ pub collections_admins_limit: u64,
+ pub custom_data_limit: u32,
+
+ // Timeouts for item types in passed blocks
+ pub nft_sponsor_transfer_timeout: u32,
+ pub fungible_sponsor_transfer_timeout: u32,
+ pub refungible_sponsor_transfer_timeout: u32,
+}
+
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct CreateNftData {
+ pub const_data: Vec<u8>,
+ pub variable_data: Vec<u8>,
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct CreateFungibleData {
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct CreateReFungibleData {
+ pub const_data: Vec<u8>,
+ pub variable_data: Vec<u8>,
+}
+
+#[derive(Encode, Decode, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub enum CreateItemData {
+ NFT(CreateNftData),
+ Fungible(CreateFungibleData),
+ ReFungible(CreateReFungibleData),
+}
+
+impl CreateItemData {
+ pub fn len(&self) -> usize {
+ let len = match self {
+ CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),
+ CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),
+ _ => 0
+ };
+
+ return len;
+ }
+}
+
+impl From<CreateNftData> for CreateItemData {
+ fn from(item: CreateNftData) -> Self {
+ CreateItemData::NFT(item)
+ }
+}
+
+impl From<CreateReFungibleData> for CreateItemData {
+ fn from(item: CreateReFungibleData) -> Self {
+ CreateItemData::ReFungible(item)
+ }
+}
+
+impl From<CreateFungibleData> for CreateItemData {
+ fn from(item: CreateFungibleData) -> Self {
+ CreateItemData::Fungible(item)
+ }
+}