difftreelog
add extra genesis
in: master
3 files changed
node/src/chain_spec.rsdiffbeforeafterboth1use nft_runtime::{2 AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig,3 SystemConfig, WASM_BINARY,4};5use nft_runtime::{ContractsConfig, ContractsSchedule};6use sc_service::ChainType;7use sp_consensus_aura::sr25519::AuthorityId as AuraId;8use sp_core::{sr25519, Pair, Public};9use sp_finality_grandpa::AuthorityId as GrandpaId;10use sp_runtime::traits::{IdentifyAccount, Verify};1112// Note this is the URL for the telemetry server13//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";1415/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.16pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;1718/// Helper function to generate a crypto pair from seed19pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {20 TPublic::Pair::from_string(&format!("//{}", seed), None)21 .expect("static values are valid; qed")22 .public()23}2425type AccountPublic = <Signature as Verify>::Signer;2627/// Helper function to generate an account ID from seed28pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId29where30 AccountPublic: From<<TPublic::Pair as Pair>::Public>,31{32 AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()33}3435/// Helper function to generate an authority key for Aura36pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) {37 (get_from_seed::<AuraId>(s), get_from_seed::<GrandpaId>(s))38}3940pub fn development_config() -> ChainSpec {41 ChainSpec::from_genesis(42 "Development",43 "dev",44 ChainType::Development,45 || {46 testnet_genesis(47 vec![authority_keys_from_seed("Alice")],48 get_account_id_from_seed::<sr25519::Public>("Alice"),49 vec![50 get_account_id_from_seed::<sr25519::Public>("Alice"),51 get_account_id_from_seed::<sr25519::Public>("Bob"),52 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),53 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),54 ],55 true,56 )57 },58 vec![],59 None,60 None,61 None,62 None,63 )64}6566pub fn local_testnet_config() -> ChainSpec {67 ChainSpec::from_genesis(68 "Local Testnet",69 "local_testnet",70 ChainType::Local,71 || {72 testnet_genesis(73 vec![74 authority_keys_from_seed("Alice"),75 authority_keys_from_seed("Bob"),76 ],77 get_account_id_from_seed::<sr25519::Public>("Alice"),78 vec![79 get_account_id_from_seed::<sr25519::Public>("Alice"),80 get_account_id_from_seed::<sr25519::Public>("Bob"),81 get_account_id_from_seed::<sr25519::Public>("Charlie"),82 get_account_id_from_seed::<sr25519::Public>("Dave"),83 get_account_id_from_seed::<sr25519::Public>("Eve"),84 get_account_id_from_seed::<sr25519::Public>("Ferdie"),85 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),86 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),87 get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),88 get_account_id_from_seed::<sr25519::Public>("Dave//stash"),89 get_account_id_from_seed::<sr25519::Public>("Eve//stash"),90 get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),91 ],92 true,93 )94 },95 vec![],96 None,97 None,98 None,99 None,100 )101}102103fn testnet_genesis(104 initial_authorities: Vec<(AuraId, GrandpaId)>,105 root_key: AccountId,106 endowed_accounts: Vec<AccountId>,107 enable_println: bool,108) -> GenesisConfig {109 GenesisConfig {110 system: Some(SystemConfig {111 code: WASM_BINARY.to_vec(),112 changes_trie_config: Default::default(),113 }),114 balances: Some(BalancesConfig {115 balances: endowed_accounts116 .iter()117 .cloned()118 .map(|k| (k, 1 << 100))119 .collect(),120 }),121 aura: Some(AuraConfig {122 authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),123 }),124 grandpa: Some(GrandpaConfig {125 authorities: initial_authorities126 .iter()127 .map(|x| (x.1.clone(), 1))128 .collect(),129 }),130 sudo: Some(SudoConfig { key: root_key }),131 contracts: Some(ContractsConfig {132 current_schedule: ContractsSchedule {133 enable_println,134 ..Default::default()135 },136 }),137 }138}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() -> ChainSpec {42 ChainSpec::from_genesis(43 "Development",44 "dev",45 ChainType::Development,46 || {47 testnet_genesis(48 vec![authority_keys_from_seed("Alice")],49 get_account_id_from_seed::<sr25519::Public>("Alice"),50 vec![51 get_account_id_from_seed::<sr25519::Public>("Alice"),52 get_account_id_from_seed::<sr25519::Public>("Bob"),53 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),54 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),55 ],56 true,57 )58 },59 vec![],60 None,61 None,62 None,63 None,64 )65}6667pub fn local_testnet_config() -> ChainSpec {68 ChainSpec::from_genesis(69 "Local Testnet",70 "local_testnet",71 ChainType::Local,72 || {73 testnet_genesis(74 vec![75 authority_keys_from_seed("Alice"),76 authority_keys_from_seed("Bob"),77 ],78 get_account_id_from_seed::<sr25519::Public>("Alice"),79 vec![80 get_account_id_from_seed::<sr25519::Public>("Alice"),81 get_account_id_from_seed::<sr25519::Public>("Bob"),82 get_account_id_from_seed::<sr25519::Public>("Charlie"),83 get_account_id_from_seed::<sr25519::Public>("Dave"),84 get_account_id_from_seed::<sr25519::Public>("Eve"),85 get_account_id_from_seed::<sr25519::Public>("Ferdie"),86 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),87 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),88 get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),89 get_account_id_from_seed::<sr25519::Public>("Dave//stash"),90 get_account_id_from_seed::<sr25519::Public>("Eve//stash"),91 get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),92 ],93 true,94 )95 },96 vec![],97 None,98 None,99 None,100 None,101 )102}103104fn testnet_genesis(105 initial_authorities: Vec<(AuraId, GrandpaId)>,106 root_key: AccountId,107 endowed_accounts: Vec<AccountId>,108 enable_println: bool,109) -> GenesisConfig {110 GenesisConfig {111 system: Some(SystemConfig {112 code: WASM_BINARY.to_vec(),113 changes_trie_config: Default::default(),114 }),115 balances: Some(BalancesConfig {116 balances: endowed_accounts117 .iter()118 .cloned()119 .map(|k| (k, 1 << 100))120 .collect(),121 }),122 aura: Some(AuraConfig {123 authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),124 }),125 grandpa: Some(GrandpaConfig {126 authorities: initial_authorities127 .iter()128 .map(|x| (x.1.clone(), 1))129 .collect(),130 }),131 sudo: Some(SudoConfig { key: root_key }),132 nft: Some(NftConfig {133 collection: vec![(1, CollectionType { 134 owner: get_account_id_from_seed::<sr25519::Public>("Alice"),135 mode: CollectionMode::NFT(50),136 access: AccessMode::Normal,137 decimal_points: 0,138 name: vec!(),139 description: vec!(),140 token_prefix: vec!(),141 custom_data_size: 50,142 mint_mode: false,143 offchain_schema: vec!(),144 sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),145 unconfirmed_sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),146 })],147 nft_item_id: vec!(),148 fungible_item_id: vec!(),149 refungible_item_id: vec!(),150 }),151 contracts: Some(ContractsConfig {152 current_schedule: ContractsSchedule {153 enable_println,154 ..Default::default()155 },156 }),157 }158}pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -1,7 +1,8 @@
#![cfg_attr(not(feature = "std"), no_std)]
-/// For more guidance on Substrate FRAME, see the example pallet
-/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs
+#[cfg(feature = "std")]
+pub use serde::*;
+
use codec::{Decode, Encode};
pub use frame_support::{
construct_runtime, decl_event, decl_module, decl_storage,
@@ -32,7 +33,6 @@
},
FixedPointOperand, FixedU128,
};
-use sp_std::prelude::*;
#[cfg(test)]
mod mock;
@@ -40,7 +40,8 @@
#[cfg(test)]
mod tests;
-#[derive(Encode, Decode, Debug, Eq, Clone, PartialEq)]
+#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum CollectionMode {
Invalid,
// custom data size
@@ -62,7 +63,8 @@
}
}
-#[derive(Encode, Decode, Debug, Clone, PartialEq)]
+#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum AccessMode {
Normal,
WhiteList,
@@ -79,15 +81,15 @@
}
}
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
+#[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, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct CollectionType<AccountId> {
pub owner: AccountId,
pub mode: CollectionMode,
@@ -103,46 +105,46 @@
pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship
}
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct CollectionAdminsType<AccountId> {
pub admin: AccountId,
pub collection_id: u64,
}
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct NftItemType<AccountId> {
pub collection: u64,
pub owner: AccountId,
pub data: Vec<u8>,
}
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct FungibleItemType<AccountId> {
pub collection: u64,
pub owner: AccountId,
pub value: u128,
}
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct ReFungibleItemType<AccountId> {
pub collection: u64,
pub owner: Vec<Ownership<AccountId>>,
pub data: Vec<u8>,
}
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct ApprovePermissions<AccountId> {
pub approved: AccountId,
pub amount: u64,
}
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
+#[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,
@@ -165,7 +167,7 @@
ChainVersion: u64;
ItemListIndex: map hasher(blake2_128_concat) u64 => u64;
- pub Collection get(fn collection): map hasher(identity) u64 => CollectionType<T::AccountId>;
+ pub Collection get(fn collection) config(): map hasher(identity) u64 => CollectionType<T::AccountId>;
pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;
pub WhiteList get(fn white_list): map hasher(identity) u64 => Vec<T::AccountId>;
@@ -176,9 +178,9 @@
pub ApprovedList get(fn approved): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) (u64, T::AccountId) => Vec<ApprovePermissions<T::AccountId>>;
/// Item collections
- pub NftItemList get(fn nft_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType<T::AccountId>;
- pub FungibleItemList get(fn fungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType<T::AccountId>;
- pub ReFungibleItemList get(fn refungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType<T::AccountId>;
+ pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType<T::AccountId>;
+ pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType<T::AccountId>;
+ pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType<T::AccountId>;
/// Index list
pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => Vec<u64>;
@@ -187,6 +189,26 @@
pub ContractSponsor get(fn contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;
pub UnconfirmedContractSponsor get(fn unconfirmed_contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;
}
+ add_extra_genesis {
+ build(|config: &GenesisConfig<T>| {
+ // Modification of storage
+ for (_num, _c) in &config.collection {
+ <Module<T>>::init_collection(_c);
+ }
+
+ for (_num, _q, _i) in &config.nft_item_id {
+ <Module<T>>::init_nft_token(_i);
+ }
+
+ for (_num, _q, _i) in &config.fungible_item_id {
+ <Module<T>>::init_fungible_token(_i);
+ }
+
+ for (_num, _q, _i) in &config.refungible_item_id {
+ <Module<T>>::init_refungible_token(_i);
+ }
+ })
+ }
}
decl_event!(
@@ -567,9 +589,16 @@
pub fn transfer(origin, recipient: T::AccountId, collection_id: u64, item_id: u64, value: u64) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_white_list(collection_id, sender.clone())?;
- Self::check_white_list(collection_id, recipient.clone())?;
+
+ // Check access and mint mode
let target_collection = <Collection<T>>::get(collection_id);
+ if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {
+
+ Self::check_white_list(collection_id, sender.clone())?;
+ Self::check_white_list(collection_id, recipient.clone())?;
+ ensure!(target_collection.access == AccessMode::WhiteList, "Collection must have WhiteList access");
+ ensure!(target_collection.mint_mode == true, "Collection must be in mint mode");
+ }
match target_collection.mode
{
@@ -620,23 +649,28 @@
let sender = ensure_signed(origin)?;
let approved_list_exists = <ApprovedList<T>>::contains_key(collection_id, (item_id, from.clone()));
-
ensure!(approved_list_exists, "Only approved addresses can call this method");
-
- Self::check_white_list(collection_id, from.clone())?;
- Self::check_white_list(collection_id, recipient.clone())?;
let list_itm = <ApprovedList<T>>::get(collection_id, (item_id, from.clone()));
let opt_item = list_itm.iter().find(|i| i.approved == sender.clone());
ensure!(opt_item.is_some(), "No approve found");
ensure!(opt_item.unwrap().amount >= value, "Requested value more than approved");
+ // Check access and mint mode
+ let target_collection = <Collection<T>>::get(collection_id);
+ if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {
+
+ Self::check_white_list(collection_id, sender.clone())?;
+ Self::check_white_list(collection_id, recipient.clone())?;
+ ensure!(target_collection.access == AccessMode::WhiteList, "Collection must have WhiteList access");
+ ensure!(target_collection.mint_mode == true, "Collection must be in mint mode");
+ }
+
// remove approve
let approve_list: Vec<ApprovePermissions<T::AccountId>> = <ApprovedList<T>>::get(collection_id, (item_id, from.clone()))
.into_iter().filter(|i| i.approved != sender.clone()).collect();
<ApprovedList<T>>::insert(collection_id, (item_id, from.clone()), approve_list);
- let target_collection = <Collection<T>>::get(collection_id);
match target_collection.mode
{
@@ -1114,6 +1148,80 @@
Ok(())
}
+ fn init_collection(item: &CollectionType<T::AccountId>){
+
+ // check params
+ assert!(item.decimal_points <= 4, "decimal_points parameter must be lower than 4");
+ assert!(item.name.len() <= 64, "Collection name can not be longer than 63 char");
+ assert!(item.name.len() <= 256, "Collection description can not be longer than 255 char");
+ assert!(item.token_prefix.len() <= 16, "Token prefix can not be longer than 15 char");
+
+ // Generate next collection ID
+ let next_id = CreatedCollectionCount::get()
+ .checked_add(1)
+ .expect("collection id error");
+
+ CreatedCollectionCount::put(next_id);
+ }
+
+ fn init_nft_token(item: &NftItemType<T::AccountId>){
+
+ let current_index = <ItemListIndex>::get(item.collection)
+ .checked_add(1)
+ .expect("Item list index id error");
+
+ let item_owner = item.owner.clone();
+ let collection_id = item.collection.clone();
+ Self::add_token_index(collection_id, current_index, item.owner.clone()).unwrap();
+
+ <ItemListIndex>::insert(collection_id, current_index);
+
+ // Update balance
+ let new_balance = <Balance<T>>::get(collection_id, item_owner.clone())
+ .checked_add(1)
+ .unwrap();
+ <Balance<T>>::insert(collection_id, item_owner.clone(), new_balance);
+ }
+
+ fn init_fungible_token(item: &FungibleItemType<T::AccountId>){
+
+ let current_index = <ItemListIndex>::get(item.collection)
+ .checked_add(1)
+ .expect("Item list index id error");
+ let owner = item.owner.clone();
+ let value = item.value as u64;
+
+ Self::add_token_index(item.collection, current_index, owner.clone()).unwrap();
+
+ <ItemListIndex>::insert(item.collection, current_index);
+
+ // Update balance
+ let new_balance = <Balance<T>>::get(item.collection, owner.clone())
+ .checked_add(value)
+ .unwrap();
+ <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
+ }
+
+ fn init_refungible_token(item: &ReFungibleItemType<T::AccountId>){
+
+ let current_index = <ItemListIndex>::get(item.collection)
+ .checked_add(1)
+ .expect("Item list index id error");
+
+ let value = item.owner.first().unwrap().fraction as u64;
+ let owner = item.owner.first().unwrap().owner.clone();
+
+ Self::add_token_index(item.collection, current_index, owner.clone()).unwrap();
+
+ <ItemListIndex>::insert(item.collection, current_index);
+
+ // Update balance
+ let new_balance = <Balance<T>>::get(item.collection, owner.clone())
+ .checked_add(value)
+ .unwrap();
+ <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
+ }
+
fn add_token_index(collection_id: u64, item_index: u64, owner: T::AccountId) -> DispatchResult {
let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner.clone());
if list_exists {
runtime/src/lib.rsdiffbeforeafterboth--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -53,8 +53,10 @@
pub use timestamp::Call as TimestampCall;
-/// Importing a nft pallet
-pub use nft;
+/// Re-export a nft pallet
+/// TODO: Check this re-export. Is this safe and good style?
+extern crate nft;
+pub use nft::*;
/// An index to a block.
pub type BlockNumber = u32;
@@ -318,7 +320,7 @@
Balances: balances::{Module, Call, Storage, Config<T>, Event<T>},
TransactionPayment: transaction_payment::{Module, Storage},
Sudo: sudo::{Module, Call, Config<T>, Storage, Event<T>},
- Nft: nft::{Module, Call, Storage, Event<T>},
+ Nft: nft::{Module, Call, Config<T>, Storage, Event<T>},
}
);