difftreelog
NFTPAR-164. Schema version
in: master
4 files changed
node/Cargo.tomldiffbeforeafterboth--- a/node/Cargo.toml
+++ b/node/Cargo.toml
@@ -23,6 +23,7 @@
[dependencies]
futures = '0.3.4'
log = '0.4.8'
+flexi_logger = "0.15.7"
parking_lot = '0.10.0'
structopt = '0.3.8'
jsonrpc-core = '15.0.0'
node/src/chain_spec.rsdiffbeforeafterboth1// use nft_runtime::{2// AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig,3// SystemConfig, WASM_BINARY,4// };5// use nft_runtime::{ContractsConfig, ContractsSchedule, NftConfig, CollectionType};6use nft_runtime::*;7use sc_service::ChainType;8use sp_consensus_aura::sr25519::AuthorityId as AuraId;9use sp_core::{sr25519, Pair, Public};10use sp_finality_grandpa::AuthorityId as GrandpaId;11use sp_runtime::traits::{IdentifyAccount, Verify};1213// Note this is the URL for the telemetry server14//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";1516/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.17pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;1819/// Helper function to generate a crypto pair from seed20pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {21 TPublic::Pair::from_string(&format!("//{}", seed), None)22 .expect("static values are valid; qed")23 .public()24}2526type AccountPublic = <Signature as Verify>::Signer;2728/// Helper function to generate an account ID from seed29pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId30where31 AccountPublic: From<<TPublic::Pair as Pair>::Public>,32{33 AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()34}3536/// Helper function to generate an authority key for Aura37pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) {38 (get_from_seed::<AuraId>(s), get_from_seed::<GrandpaId>(s))39}4041pub fn development_config() -> Result<ChainSpec, String> {42 let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?;4344 Ok(ChainSpec::from_genesis(45 // Name46 "Development",47 // ID48 "dev",49 ChainType::Development,50 move || testnet_genesis(51 wasm_binary,52 // Initial PoA authorities53 vec![54 authority_keys_from_seed("Alice"),55 ],56 // Sudo account57 get_account_id_from_seed::<sr25519::Public>("Alice"),58 // Pre-funded accounts59 vec![60 get_account_id_from_seed::<sr25519::Public>("Alice"),61 get_account_id_from_seed::<sr25519::Public>("Bob"),62 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),63 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),64 ],65 true,66 ),67 // Bootnodes68 vec![],69 // Telemetry70 None,71 // Protocol ID72 None,73 // Properties74 None,75 // Extensions76 None,77 ))78}7980pub fn local_testnet_config() -> Result<ChainSpec, String> {81 let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?;8283 Ok(ChainSpec::from_genesis(84 // Name85 "Local Testnet",86 // ID87 "local_testnet",88 ChainType::Local,89 move || testnet_genesis(90 wasm_binary,91 // Initial PoA authorities92 vec![93 authority_keys_from_seed("Alice"),94 authority_keys_from_seed("Bob"),95 ],96 // Sudo account97 get_account_id_from_seed::<sr25519::Public>("Alice"),98 // Pre-funded accounts99 vec![100 get_account_id_from_seed::<sr25519::Public>("Alice"),101 get_account_id_from_seed::<sr25519::Public>("Bob"),102 get_account_id_from_seed::<sr25519::Public>("Charlie"),103 get_account_id_from_seed::<sr25519::Public>("Dave"),104 get_account_id_from_seed::<sr25519::Public>("Eve"),105 get_account_id_from_seed::<sr25519::Public>("Ferdie"),106 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),107 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),108 get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),109 get_account_id_from_seed::<sr25519::Public>("Dave//stash"),110 get_account_id_from_seed::<sr25519::Public>("Eve//stash"),111 get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),112 ],113 true,114 ),115 // Bootnodes116 vec![],117 // Telemetry118 None,119 // Protocol ID120 None,121 // Properties122 None,123 // Extensions124 None,125 ))126}127128fn testnet_genesis(129 wasm_binary: &[u8],130 initial_authorities: Vec<(AuraId, GrandpaId)>,131 root_key: AccountId,132 endowed_accounts: Vec<AccountId>,133 enable_println: bool,134) -> GenesisConfig {135 GenesisConfig {136 system: Some(SystemConfig {137 code: wasm_binary.to_vec(),138 changes_trie_config: Default::default(),139 }),140 pallet_balances: Some(BalancesConfig {141 balances: endowed_accounts142 .iter()143 .cloned()144 .map(|k| (k, 1 << 100))145 .collect(),146 }),147 pallet_aura: Some(AuraConfig {148 authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),149 }),150 pallet_grandpa: Some(GrandpaConfig {151 authorities: initial_authorities152 .iter()153 .map(|x| (x.1.clone(), 1))154 .collect(),155 }),156 pallet_treasury: Some(Default::default()),157 pallet_sudo: Some(SudoConfig { key: root_key }),158 pallet_nft: Some(NftConfig {159 collection: vec![(160 1,161 CollectionType {162 owner: get_account_id_from_seed::<sr25519::Public>("Alice"),163 mode: CollectionMode::NFT,164 access: AccessMode::Normal,165 decimal_points: 0,166 name: vec![],167 description: vec![],168 token_prefix: vec![],169 mint_mode: false,170 offchain_schema: vec![],171 sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),172 unconfirmed_sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),173 const_on_chain_schema: vec![],174 variable_on_chain_schema: vec![],175 limits: CollectionLimits::default()176 },177 )],178 nft_item_id: vec![],179 fungible_item_id: vec![],180 refungible_item_id: vec![],181 chain_limit: ChainLimits {182 collection_numbers_limit: 10,183 account_token_ownership_limit: 10,184 collections_admins_limit: 5,185 custom_data_limit: 2048,186 nft_sponsor_transfer_timeout: 15,187 fungible_sponsor_transfer_timeout: 15,188 refungible_sponsor_transfer_timeout: 15,189 },190 }),191 pallet_contracts: Some(ContractsConfig {192 current_schedule: ContractsSchedule {193 enable_println,194 ..Default::default()195 },196 }),197 }198}1// use nft_runtime::{2// AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig,3// SystemConfig, WASM_BINARY,4// };5// use nft_runtime::{ContractsConfig, ContractsSchedule, NftConfig, CollectionType};6use nft_runtime::*;7use sc_service::ChainType;8use sp_consensus_aura::sr25519::AuthorityId as AuraId;9use sp_core::{sr25519, Pair, Public};10use sp_finality_grandpa::AuthorityId as GrandpaId;11use sp_runtime::traits::{IdentifyAccount, Verify};1213// Note this is the URL for the telemetry server14//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";1516/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.17pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;1819/// Helper function to generate a crypto pair from seed20pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {21 TPublic::Pair::from_string(&format!("//{}", seed), None)22 .expect("static values are valid; qed")23 .public()24}2526type AccountPublic = <Signature as Verify>::Signer;2728/// Helper function to generate an account ID from seed29pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId30where31 AccountPublic: From<<TPublic::Pair as Pair>::Public>,32{33 AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()34}3536/// Helper function to generate an authority key for Aura37pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) {38 (get_from_seed::<AuraId>(s), get_from_seed::<GrandpaId>(s))39}4041pub fn development_config() -> Result<ChainSpec, String> {42 let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?;4344 Ok(ChainSpec::from_genesis(45 // Name46 "Development",47 // ID48 "dev",49 ChainType::Development,50 move || testnet_genesis(51 wasm_binary,52 // Initial PoA authorities53 vec![54 authority_keys_from_seed("Alice"),55 ],56 // Sudo account57 get_account_id_from_seed::<sr25519::Public>("Alice"),58 // Pre-funded accounts59 vec![60 get_account_id_from_seed::<sr25519::Public>("Alice"),61 get_account_id_from_seed::<sr25519::Public>("Bob"),62 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),63 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),64 ],65 true,66 ),67 // Bootnodes68 vec![],69 // Telemetry70 None,71 // Protocol ID72 None,73 // Properties74 None,75 // Extensions76 None,77 ))78}7980pub fn local_testnet_config() -> Result<ChainSpec, String> {81 let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?;8283 Ok(ChainSpec::from_genesis(84 // Name85 "Local Testnet",86 // ID87 "local_testnet",88 ChainType::Local,89 move || testnet_genesis(90 wasm_binary,91 // Initial PoA authorities92 vec![93 authority_keys_from_seed("Alice"),94 authority_keys_from_seed("Bob"),95 ],96 // Sudo account97 get_account_id_from_seed::<sr25519::Public>("Alice"),98 // Pre-funded accounts99 vec![100 get_account_id_from_seed::<sr25519::Public>("Alice"),101 get_account_id_from_seed::<sr25519::Public>("Bob"),102 get_account_id_from_seed::<sr25519::Public>("Charlie"),103 get_account_id_from_seed::<sr25519::Public>("Dave"),104 get_account_id_from_seed::<sr25519::Public>("Eve"),105 get_account_id_from_seed::<sr25519::Public>("Ferdie"),106 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),107 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),108 get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),109 get_account_id_from_seed::<sr25519::Public>("Dave//stash"),110 get_account_id_from_seed::<sr25519::Public>("Eve//stash"),111 get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),112 ],113 true,114 ),115 // Bootnodes116 vec![],117 // Telemetry118 None,119 // Protocol ID120 None,121 // Properties122 None,123 // Extensions124 None,125 ))126}127128fn testnet_genesis(129 wasm_binary: &[u8],130 initial_authorities: Vec<(AuraId, GrandpaId)>,131 root_key: AccountId,132 endowed_accounts: Vec<AccountId>,133 enable_println: bool,134) -> GenesisConfig {135 GenesisConfig {136 system: Some(SystemConfig {137 code: wasm_binary.to_vec(),138 changes_trie_config: Default::default(),139 }),140 pallet_balances: Some(BalancesConfig {141 balances: endowed_accounts142 .iter()143 .cloned()144 .map(|k| (k, 1 << 100))145 .collect(),146 }),147 pallet_aura: Some(AuraConfig {148 authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),149 }),150 pallet_grandpa: Some(GrandpaConfig {151 authorities: initial_authorities152 .iter()153 .map(|x| (x.1.clone(), 1))154 .collect(),155 }),156 pallet_treasury: Some(Default::default()),157 pallet_sudo: Some(SudoConfig { key: root_key }),158 pallet_nft: Some(NftConfig {159 collection: vec![(160 1,161 CollectionType {162 owner: get_account_id_from_seed::<sr25519::Public>("Alice"),163 mode: CollectionMode::NFT,164 access: AccessMode::Normal,165 decimal_points: 0,166 name: vec![],167 description: vec![],168 token_prefix: vec![],169 mint_mode: false,170 offchain_schema: vec![],171 schema_version: SchemaVersion::default(),172 sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),173 unconfirmed_sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),174 const_on_chain_schema: vec![],175 variable_on_chain_schema: vec![],176 limits: CollectionLimits::default()177 },178 )],179 nft_item_id: vec![],180 fungible_item_id: vec![],181 refungible_item_id: vec![],182 chain_limit: ChainLimits {183 collection_numbers_limit: 10,184 account_token_ownership_limit: 10,185 collections_admins_limit: 5,186 custom_data_limit: 2048,187 nft_sponsor_transfer_timeout: 15,188 fungible_sponsor_transfer_timeout: 15,189 refungible_sponsor_transfer_timeout: 15,190 },191 }),192 pallet_contracts: Some(ContractsConfig {193 current_schedule: ContractsSchedule {194 enable_println,195 ..Default::default()196 },197 }),198 }199}pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -1,3 +1,5 @@
+#![recursion_limit = "1024"]
+
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
@@ -54,7 +56,6 @@
pub type CollectionId = u32;
pub type TokenId = u32;
-
pub type DecimalPoints = u8;
#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
@@ -97,6 +98,18 @@
}
}
+#[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> {
@@ -116,6 +129,7 @@
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
@@ -258,7 +272,7 @@
pub enum CreateItemData {
NFT(CreateNftData),
Fungible(CreateFungibleData),
- ReFungible(CreateReFungibleData)
+ ReFungible(CreateReFungibleData),
}
impl CreateItemData {
@@ -570,6 +584,7 @@
decimal_points: decimal_points,
token_prefix: prefix,
offchain_schema: Vec::new(),
+ schema_version: SchemaVersion::ImageURL,
sponsor: T::AccountId::default(),
unconfirmed_sponsor: T::AccountId::default(),
variable_on_chain_schema: Vec::new(),
@@ -1200,7 +1215,6 @@
Ok(())
}
- ///
#[weight = 0]
pub fn safe_transfer_from(origin, collection_id: CollectionId, item_id: TokenId, new_owner: T::AccountId) -> DispatchResult {
@@ -1259,7 +1273,35 @@
Ok(())
}
-
+
+ /// Set schema standard
+ /// ImageURL
+ /// Unique
+ ///
+ /// # Permissions
+ ///
+ /// * Collection Owner
+ /// * Collection Admin
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id.
+ ///
+ /// * schema: SchemaVersion: enum
+ #[weight = 0]
+ pub fn set_schema_version(
+ origin,
+ collection_id: CollectionId,
+ version: SchemaVersion
+ ) -> DispatchResult {
+ let sender = ensure_signed(origin)?;
+ Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+ let mut target_collection = <Collection<T>>::get(collection_id);
+ target_collection.schema_version = version;
+ <Collection<T>>::insert(collection_id, target_collection);
+
+ Ok(())
+ }
/// Set off-chain data schema.
///
@@ -1458,7 +1500,7 @@
impl<T: Trait> Module<T> {
fn is_correct_transfer(collection_id: CollectionId, collection: &CollectionType<T::AccountId>, recipient: &T::AccountId) -> DispatchResult {
-
+
// check token limit and account token limit
let account_items: u32 = <AddressTokens<T>>::get(collection_id, recipient).len() as u32;
ensure!(collection.limits.account_token_ownership_limit > account_items, Error::<T>::AccountTokenLimitExceeded);
pallets/nft/src/tests.rsdiffbeforeafterboth--- a/pallets/nft/src/tests.rs
+++ b/pallets/nft/src/tests.rs
@@ -77,6 +77,19 @@
// Use cases tests region
// #region
+
+#[test]
+fn set_version_schema() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+ let origin1 = Origin::signed(1);
+ let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+ assert_ok!(TemplateModule::set_schema_version(origin1, collection_id, SchemaVersion::Unique));
+ assert_eq!(TemplateModule::collection(collection_id).schema_version, SchemaVersion::Unique);
+ });
+}
+
#[test]
fn create_fungible_collection_fails_with_large_decimal_numbers() {
new_test_ext().execute_with(|| {