From 1062964b42ee1f17621007c25c1363eef7a8c3c3 Mon Sep 17 00:00:00 2001 From: realnimish Date: Thu, 16 Mar 2023 12:53:19 +0530 Subject: [PATCH 01/15] feat: add psp34 standard trait --- azns_registry/lib.rs | 2 + azns_registry/psp34_standard.rs | 96 +++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 azns_registry/psp34_standard.rs diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 2e0f2c7..642f003 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -1,10 +1,12 @@ #![cfg_attr(not(feature = "std"), no_std)] mod address_dict; +mod psp34_standard; #[ink::contract] mod azns_registry { use crate::address_dict::AddressDict; + use crate::psp34_standard::*; use ink::env::call::FromAccountId; use ink::env::hash::CryptoHash; use ink::prelude::string::{String, ToString}; diff --git a/azns_registry/psp34_standard.rs b/azns_registry/psp34_standard.rs new file mode 100644 index 0000000..0d6e0a7 --- /dev/null +++ b/azns_registry/psp34_standard.rs @@ -0,0 +1,96 @@ +use ink::prelude::{string::String, vec::Vec}; +use ink::primitives::AccountId; + +type Balance = u128; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, scale::Encode, scale::Decode)] +#[cfg_attr( + feature = "std", + derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout) +)] +pub enum Id { + U8(u8), + U16(u16), + U32(u32), + U64(u64), + U128(u128), + Bytes(Vec), +} + +/// The PSP34 error type. Contract will throw one of this errors. +#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum PSP34Error { + /// Custom error type for cases if writer of traits added own restrictions + Custom(String), + /// Returned if owner approves self + SelfApprove, + /// Returned if the caller doesn't have allowance for transferring. + NotApproved, + /// Returned if the owner already own the token. + TokenExists, + /// Returned if the token doesn't exist + TokenNotExists, + /// Returned if safe transfer check fails + SafeTransferCheckFailed(String), +} + +#[ink::trait_definition] +pub trait PSP34 { + /// Returns the collection `Id` of the NFT token. + /// + /// This can represents the relationship between tokens/contracts/pallets. + #[ink(message)] + fn collection_id(&self) -> Id; + + /// Returns the balance of the owner. + /// + /// This represents the amount of unique tokens the owner has. + #[ink(message)] + fn balance_of(&self, owner: AccountId) -> u32; + + /// Returns the owner of the token if any. + #[ink(message)] + fn owner_of(&self, id: Id) -> Option; + + /// Returns `true` if the operator is approved by the owner to withdraw `id` token. + /// If `id` is `None`, returns `true` if the operator is approved to withdraw all owner's tokens. + #[ink(message)] + fn allowance(&self, owner: AccountId, operator: AccountId, id: Option) -> bool; + + /// Approves `operator` to withdraw the `id` token from the caller's account. + /// If `id` is `None` approves or disapproves the operator for all tokens of the caller. + /// + /// On success a `Approval` event is emitted. + /// + /// # Errors + /// + /// Returns `SelfApprove` error if it is self approve. + /// + /// Returns `NotApproved` error if caller is not owner of `id`. + #[ink(message)] + fn approve( + &mut self, + operator: AccountId, + id: Option, + approved: bool, + ) -> Result<(), PSP34Error>; + + /// Transfer approved or owned token from caller. + /// + /// On success a `Transfer` event is emitted. + /// + /// # Errors + /// + /// Returns `TokenNotExists` error if `id` does not exist. + /// + /// Returns `NotApproved` error if `from` doesn't have allowance for transferring. + /// + /// Returns `SafeTransferCheckFailed` error if `to` doesn't accept transfer. + #[ink(message)] + fn transfer(&mut self, to: AccountId, id: Id, data: Vec) -> Result<(), PSP34Error>; + + /// Returns current NFT total supply. + #[ink(message)] + fn total_supply(&self) -> Balance; +} From e7088e82360aaded7e33b09078688e8a9feddaba Mon Sep 17 00:00:00 2001 From: realnimish Date: Fri, 17 Mar 2023 15:27:52 +0530 Subject: [PATCH 02/15] wip: implement partial trait of PSP34 standard --- azns_registry/lib.rs | 86 +++++++++++++++++++++++++++++++++ azns_registry/psp34_standard.rs | 19 +++++++- 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 642f003..19dcc1d 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -105,6 +105,8 @@ mod azns_registry { fee_calculator: Option, /// Names which can be claimed only by the specified user reserved_names: Mapping, ManualKey<100>>, + /// Mapping from owner to operator approvals. + operator_approvals: Mapping<(AccountId, AccountId), (), ManualKey<101>>, /// Mapping from name to addresses associated with it name_to_address_dict: Mapping>, @@ -216,6 +218,7 @@ mod azns_registry { resolving_to_address: Default::default(), whitelisted_address_verifier: Default::default(), reserved_names: Default::default(), + operator_approvals: Default::default(), tld, metadata_size_limit, }; @@ -1020,6 +1023,89 @@ mod azns_registry { } } } + + impl PSP34 for DomainNameService { + // TLD is our collection id + #[ink(message)] + fn collection_id(&self) -> Id { + Id::Bytes(self.tld.as_bytes().to_vec()) + } + + #[ink(message)] + fn balance_of(&self, owner: AccountId) -> u32 { + self.get_owned_names_of_address(owner) + .unwrap_or_default() + .len() as u32 + } + + #[ink(message)] + fn owner_of(&self, id: Id) -> Option { + id.try_into().map_or(None, |name| self.get_owner(name).ok()) + } + + #[ink(message)] + fn allowance(&self, owner: AccountId, operator: AccountId, id: Option) -> bool { + if self.operator_approvals.contains((owner, operator)) { + return true; + } + + id.map_or(false, |id| { + id.try_into() + .map_or(false, |name| self.get_controller(name) == Ok(operator)) + }) + } + + #[ink(message)] + fn approve( + &mut self, + operator: AccountId, + id: Option, + approved: bool, + ) -> core::result::Result<(), PSP34Error> { + let mut caller = self.env().caller(); + + match id { + Some(id) => { + let owner = self.owner_of(id).ok_or(PSP34Error::TokenNotExists)?; + + if owner != caller && !self.allowance(owner, caller, None) { + return Err(PSP34Error::NotApproved); + }; + + let name = id.try_into()?; + + match approved { + true => self.set_controller(name, operator)?, + false => self.set_controller(name, owner)?, + } + } + None => match approved { + true => { + self.operator_approvals.insert(&(caller, operator), &()); + } + false => self.operator_approvals.remove(&(caller, operator)), + }, + } + + // Emit event + Ok(()) + } + + #[ink(message)] + fn transfer( + &mut self, + to: AccountId, + id: Id, + data: Vec, + ) -> core::result::Result<(), PSP34Error> { + unimplemented!() + } + + #[ink(message)] + fn total_supply(&self) -> Balance { + unimplemented!() + } + } } #[cfg(test)] diff --git a/azns_registry/psp34_standard.rs b/azns_registry/psp34_standard.rs index 0d6e0a7..6081642 100644 --- a/azns_registry/psp34_standard.rs +++ b/azns_registry/psp34_standard.rs @@ -1,4 +1,7 @@ -use ink::prelude::{string::String, vec::Vec}; +use ink::prelude::{ + string::{String, ToString}, + vec::Vec, +}; use ink::primitives::AccountId; type Balance = u128; @@ -35,6 +38,20 @@ pub enum PSP34Error { SafeTransferCheckFailed(String), } +impl TryFrom for String { + type Error = PSP34Error; + + fn try_from(value: Id) -> core::result::Result { + match value { + Id::Bytes(bytes) => String::from_utf8(bytes) + .map_err(|_| PSP34Error::Custom("Invalid id. Expected UTF8 string".to_string())), + _ => Err(PSP34Error::Custom( + "Invalid id. Expected UTF8 string".to_string(), + )), + } + } +} + #[ink::trait_definition] pub trait PSP34 { /// Returns the collection `Id` of the NFT token. From e898239b51c53878e0767f802b58a47353ba9d78 Mon Sep 17 00:00:00 2001 From: realnimish Date: Mon, 27 Mar 2023 16:47:02 +0530 Subject: [PATCH 03/15] fix: make operator & controller role different --- azns_registry/lib.rs | 63 +++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 19dcc1d..8e58cab 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -81,6 +81,18 @@ mod azns_registry { new_owner: AccountId, } + /// Event emitted when a token approve occurs. + #[ink(event)] + pub struct Approval { + #[ink(topic)] + owner: AccountId, + #[ink(topic)] + operator: AccountId, + #[ink(topic)] + id: Option, + approved: bool, + } + /// Emitted when switching from whitelist-phase to public-phase #[ink(event)] pub struct PublicPhaseActivated; @@ -106,7 +118,7 @@ mod azns_registry { /// Names which can be claimed only by the specified user reserved_names: Mapping, ManualKey<100>>, /// Mapping from owner to operator approvals. - operator_approvals: Mapping<(AccountId, AccountId), (), ManualKey<101>>, + operator_approvals: Mapping<(AccountId, AccountId, Option), (), ManualKey<101>>, /// Mapping from name to addresses associated with it name_to_address_dict: Mapping>, @@ -1045,14 +1057,10 @@ mod azns_registry { #[ink(message)] fn allowance(&self, owner: AccountId, operator: AccountId, id: Option) -> bool { - if self.operator_approvals.contains((owner, operator)) { + if id.is_some() && self.operator_approvals.contains(&(owner, operator, None)) { return true; } - - id.map_or(false, |id| { - id.try_into() - .map_or(false, |name| self.get_controller(name) == Ok(operator)) - }) + self.operator_approvals.contains(&(owner, operator, id)) } #[ink(message)] @@ -1064,30 +1072,37 @@ mod azns_registry { ) -> core::result::Result<(), PSP34Error> { let mut caller = self.env().caller(); - match id { - Some(id) => { - let owner = self.owner_of(id).ok_or(PSP34Error::TokenNotExists)?; + if let Some(id) = &id { + let owner = self + .owner_of(id.clone()) + .ok_or(PSP34Error::TokenNotExists)?; - if owner != caller && !self.allowance(owner, caller, None) { - return Err(PSP34Error::NotApproved); - }; + if approved && owner == operator { + return Err(PSP34Error::SelfApprove); + } - let name = id.try_into()?; + if owner != caller && !self.allowance(owner, caller, None) { + return Err(PSP34Error::NotApproved); + }; + caller = owner; + } - match approved { - true => self.set_controller(name, operator)?, - false => self.set_controller(name, owner)?, - } + match approved { + true => { + self.operator_approvals + .insert((&caller, &operator, &id), &()); } - None => match approved { - true => { - self.operator_approvals.insert(&(caller, operator), &()); - } - false => self.operator_approvals.remove(&(caller, operator)), - }, + false => self.operator_approvals.remove((&caller, &operator, &id)), } // Emit event + self.env().emit_event(Approval { + owner: caller, + operator, + id, + approved, + }); + Ok(()) } From 68d403d67ab0ca230ba779c369171368a40c65e5 Mon Sep 17 00:00:00 2001 From: realnimish Date: Mon, 27 Mar 2023 17:08:02 +0530 Subject: [PATCH 04/15] feat(psp34): implement `total_supply` note: total_supply includes expired names as well unless cleared from state --- azns_registry/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 8e58cab..2f85957 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -144,6 +144,8 @@ mod azns_registry { /// TLD tld: String, + /// Total supply (including expired names) + total_supply: Balance, } /// Errors that can occur upon calling this contract. @@ -233,6 +235,7 @@ mod azns_registry { operator_approvals: Default::default(), tld, metadata_size_limit, + total_supply: 0, }; // Initialize address verifier @@ -891,6 +894,8 @@ mod azns_registry { /* Update convenience mapping for resolved names */ self.add_name_to_resolving(recipient, name); + self.total_supply += 1; + /* Emit register event */ Self::env().emit_event(Register { name: name.to_string(), @@ -912,6 +917,8 @@ mod azns_registry { self.remove_name_from_owner(&address_dict.owner, &name); self.remove_name_from_controller(&address_dict.controller, &name); self.remove_name_from_resolving(&address_dict.resolved, &name); + + self.total_supply -= 1; } /// Adds a name to owners' collection @@ -1118,7 +1125,7 @@ mod azns_registry { #[ink(message)] fn total_supply(&self) -> Balance { - unimplemented!() + self.total_supply } } } From 90709ea509dcf1d00d8201d0ff3b88dc36e4a701 Mon Sep 17 00:00:00 2001 From: realnimish Date: Mon, 27 Mar 2023 23:22:46 +0530 Subject: [PATCH 05/15] feat(psp34-standard): implement `transfer` The custom transfer function now expects bool params to retain previous state --- azns_registry/lib.rs | 144 ++++++++++++++++++++++---------- azns_registry/psp34_standard.rs | 6 ++ 2 files changed, 106 insertions(+), 44 deletions(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 2f85957..1feaa88 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -69,16 +69,15 @@ mod azns_registry { new_address: AccountId, } - /// Emitted whenever a name is transferred. + /// Event emitted when a token transfer occurs. #[ink(event)] pub struct Transfer { #[ink(topic)] - name: String, - from: AccountId, + from: Option, #[ink(topic)] - old_owner: Option, + to: Option, #[ink(topic)] - new_owner: AccountId, + id: Id, } /// Event emitted when a token approve occurs. @@ -395,41 +394,15 @@ mod azns_registry { /// Transfer owner to another address. #[ink(message)] - pub fn transfer(&mut self, name: String, to: AccountId) -> Result<()> { - // Transfer is disabled during the whitelist-phase - if self.is_whitelist_phase() { - return Err(Error::RestrictedDuringWhitelistPhase); - } - - /* Ensure the caller is the owner of the name */ - let caller = Self::env().caller(); - self.ensure_owner(&caller, &name)?; - - /* Transfer control to new owner `to` */ - let address_dict = AddressDict::new(to); - self.name_to_address_dict.insert(&name, &address_dict); - - /* Remove from reverse search */ - self.remove_name_from_owner(&caller, &name); - self.remove_name_from_controller(&caller, &name); - self.remove_name_from_resolving(&caller, &name); - - /* Add to reverse search of owner */ - self.add_name_to_owner(&to, &name); - self.add_name_to_controller(&to, &name); - self.add_name_to_resolving(&to, &name); - - /* Clear metadata */ - self.metadata.remove(&name); - - Self::env().emit_event(Transfer { - name, - from: caller, - old_owner: Some(caller), - new_owner: to, - }); - - Ok(()) + pub fn transfer( + &mut self, + to: AccountId, + name: String, + keep_metadata: bool, + keep_controller: bool, + keep_resolving: bool, + ) -> core::result::Result<(), PSP34Error> { + self.transfer_for(to, &name, keep_metadata, keep_controller, keep_resolving) } /// Removes the associated state of expired-names from storage @@ -902,6 +875,12 @@ mod azns_registry { from: *recipient, }); + self.env().emit_event(Transfer { + from: None, + to: Some(*recipient), + id: name.to_string().into(), + }); + Ok(()) } @@ -919,6 +898,79 @@ mod azns_registry { self.remove_name_from_resolving(&address_dict.resolved, &name); self.total_supply -= 1; + + self.env().emit_event(Transfer { + from: Some(address_dict.owner), + to: None, + id: name.to_string().into(), + }); + } + + fn transfer_for( + &mut self, + to: AccountId, + name: &str, + keep_metadata: bool, + keep_controller: bool, + keep_resolving: bool, + ) -> core::result::Result<(), PSP34Error> { + // Transfer is disabled during the whitelist-phase + if self.is_whitelist_phase() { + return Err(PSP34Error::Custom( + "transfer disabled during whitelist phase".to_string(), + )); + } + + let id: Id = name.to_string().into(); + let mut address_dict = self + .get_address_dict_ref(&name) + .map_err(|_| PSP34Error::TokenNotExists)?; + + let AddressDict { + owner, + controller, + resolved, + } = address_dict; + + // Ensure the caller is authorised to transfer the name + let caller = self.env().caller(); + if caller != owner && !self.allowance(owner, caller, Some(id.clone())) { + return Err(PSP34Error::NotApproved); + } + + address_dict.owner = to; + self.remove_name_from_owner(&owner, &name); + self.add_name_to_owner(&to, &name); + + if !keep_controller { + address_dict.controller = to; + self.remove_name_from_controller(&controller, &name); + self.add_name_to_controller(&to, &name); + } + + if !keep_resolving { + address_dict.resolved = to; + self.remove_name_from_resolving(&resolved, &name); + self.add_name_to_resolving(&to, &name); + } + + if !keep_metadata { + self.metadata.remove(name); + } + + self.name_to_address_dict.insert(name, &address_dict); + self.operator_approvals + .remove((&owner, &caller, &Some(id.clone()))); + + // TODO safe transfer check + + Self::env().emit_event(Transfer { + from: Some(owner), + to: Some(to), + id, + }); + + Ok(()) } /// Adds a name to owners' collection @@ -1047,7 +1099,7 @@ mod azns_registry { // TLD is our collection id #[ink(message)] fn collection_id(&self) -> Id { - Id::Bytes(self.tld.as_bytes().to_vec()) + self.tld.clone().into() } #[ink(message)] @@ -1118,9 +1170,10 @@ mod azns_registry { &mut self, to: AccountId, id: Id, - data: Vec, + _data: Vec, ) -> core::result::Result<(), PSP34Error> { - unimplemented!() + let name: String = id.try_into()?; + self.transfer_for(to, &name, false, false, false) } #[ink(message)] @@ -1750,7 +1803,10 @@ mod tests { ); // Test transfer of owner. - assert_eq!(contract.transfer(name.clone(), accounts.bob), Ok(())); + assert_eq!( + contract.transfer(accounts.bob, name.clone(), false, false, false), + Ok(()) + ); assert_eq!( contract.get_owned_names_of_address(accounts.alice), diff --git a/azns_registry/psp34_standard.rs b/azns_registry/psp34_standard.rs index 6081642..97a2e8a 100644 --- a/azns_registry/psp34_standard.rs +++ b/azns_registry/psp34_standard.rs @@ -52,6 +52,12 @@ impl TryFrom for String { } } +impl From for Id { + fn from(value: String) -> Self { + Self::Bytes(value.as_bytes().to_vec()) + } +} + #[ink::trait_definition] pub trait PSP34 { /// Returns the collection `Id` of the NFT token. From a08254f6de07ce0a856c5e5e12163c308db6dd36 Mon Sep 17 00:00:00 2001 From: realnimish Date: Tue, 28 Mar 2023 16:57:48 +0530 Subject: [PATCH 06/15] feat(psp34-std): add safe-transfer-check --- azns_registry/lib.rs | 86 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 1feaa88..7b20a92 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -401,8 +401,16 @@ mod azns_registry { keep_metadata: bool, keep_controller: bool, keep_resolving: bool, + data: Vec, ) -> core::result::Result<(), PSP34Error> { - self.transfer_for(to, &name, keep_metadata, keep_controller, keep_resolving) + self.transfer_for( + to, + &name, + keep_metadata, + keep_controller, + keep_resolving, + &data, + ) } /// Removes the associated state of expired-names from storage @@ -913,6 +921,7 @@ mod azns_registry { keep_metadata: bool, keep_controller: bool, keep_resolving: bool, + data: &Vec, ) -> core::result::Result<(), PSP34Error> { // Transfer is disabled during the whitelist-phase if self.is_whitelist_phase() { @@ -963,6 +972,7 @@ mod azns_registry { .remove((&owner, &caller, &Some(id.clone()))); // TODO safe transfer check + self.safe_transfer_check(&caller, &owner, &to, &id, &data)?; Self::env().emit_event(Transfer { from: Some(owner), @@ -973,6 +983,76 @@ mod azns_registry { Ok(()) } + fn safe_transfer_check( + &mut self, + operator: &AccountId, + from: &AccountId, + to: &AccountId, + id: &Id, + data: &Vec, + ) -> core::result::Result<(), PSP34Error> { + // @dev This is disabled during tests due to the use of `invoke_contract()` not being + // supported (tests end up panicking). + #[cfg(not(test))] + { + use ink::env::call::{build_call, ExecutionInput, Selector}; + + const BEFORE_RECEIVED_SELECTOR: [u8; 4] = [0xBB, 0x7D, 0xF7, 0x80]; + + let result = build_call::() + .call(*to) + .call_flags(ink::env::CallFlags::default().set_allow_reentry(true)) + .exec_input( + ExecutionInput::new(Selector::new(BEFORE_RECEIVED_SELECTOR)) + .push_arg(operator) + .push_arg(from) + .push_arg(id) + .push_arg::>(data.clone()), + ) + .returns::>() + .params() + .try_invoke(); + + match result { + Ok(v) => { + ink::env::debug_println!( + "Received return value \"{:?}\" from contract {:?}", + v.clone() + .expect("Call should be valid, don't expect a `LangError`."), + from + ); + assert_eq!( + v.clone() + .expect("Call should be valid, don't expect a `LangError`."), + Ok(()), + "The recipient contract at {to:?} does not accept token transfers.\n + Expected: Ok(()), Got {v:?}" + ) + } + Err(e) => { + match e { + ink::env::Error::CodeNotFound | ink::env::Error::NotCallable => { + // Our recipient wasn't a smart contract, so there's nothing more for + // us to do + ink::env::debug_println!( + "Recipient at {:?} from is not a smart contract ({:?})", + from, + e + ); + } + _ => { + // We got some sort of error from the call to our recipient smart + // contract, and as such we must revert this call + panic!("Got error \"{e:?}\" while trying to call {from:?}") + } + } + } + } + } + + Ok(()) + } + /// Adds a name to owners' collection fn add_name_to_owner(&mut self, owner: &AccountId, name: &str) { let mut names = self.owner_to_names.get(owner).unwrap_or_default(); @@ -1170,10 +1250,10 @@ mod azns_registry { &mut self, to: AccountId, id: Id, - _data: Vec, + data: Vec, ) -> core::result::Result<(), PSP34Error> { let name: String = id.try_into()?; - self.transfer_for(to, &name, false, false, false) + self.transfer_for(to, &name, false, false, false, &data) } #[ink(message)] From 613fb16c5e6f0884ff2de187671b86c9cb76003b Mon Sep 17 00:00:00 2001 From: realnimish Date: Tue, 28 Mar 2023 18:15:08 +0530 Subject: [PATCH 07/15] feat: add PSP34Metadata support --- azns_registry/lib.rs | 17 ++++++++++++++++- azns_registry/psp34_standard.rs | 9 +++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 7b20a92..c79fffd 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -1261,6 +1261,21 @@ mod azns_registry { self.total_supply } } + + impl PSP34Metadata for DomainNameService { + #[ink(message)] + fn get_attribute(&self, id: Id, key: Vec) -> Option> { + match id.try_into() { + Ok(name) => { + let Ok(key) = String::from_utf8(key) else { + return None; + }; + self.get_record(name, key).map(|val| val.into_bytes()).ok() + } + Err(_) => None, + } + } + } } #[cfg(test)] @@ -1884,7 +1899,7 @@ mod tests { // Test transfer of owner. assert_eq!( - contract.transfer(accounts.bob, name.clone(), false, false, false), + contract.transfer(accounts.bob, name.clone(), false, false, false, vec![]), Ok(()) ); diff --git a/azns_registry/psp34_standard.rs b/azns_registry/psp34_standard.rs index 97a2e8a..c03056b 100644 --- a/azns_registry/psp34_standard.rs +++ b/azns_registry/psp34_standard.rs @@ -117,3 +117,12 @@ pub trait PSP34 { #[ink(message)] fn total_supply(&self) -> Balance; } + +#[ink::trait_definition] +pub trait PSP34Metadata { + /// Returns the attribute of `id` for the given `key`. + /// + /// If `id` is a collection id of the token, it returns attributes for collection. + #[ink(message)] + fn get_attribute(&self, id: Id, key: Vec) -> Option>; +} From 3875154382ba6673671106babbc582ac0d4f1294 Mon Sep 17 00:00:00 2001 From: realnimish Date: Fri, 7 Apr 2023 21:07:47 +0530 Subject: [PATCH 08/15] feat(psp34): add partial support of `PSP34Enumberable` --- azns_registry/lib.rs | 21 +++++++++++++++++++++ azns_registry/psp34_standard.rs | 17 +++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index c79fffd..8d0da24 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -1262,6 +1262,27 @@ mod azns_registry { } } + impl PSP34Enumerable for DomainNameService { + #[ink(message)] + fn owners_token_by_index( + &self, + owner: AccountId, + index: u128, + ) -> core::result::Result { + let tokens = self.get_owned_names_of_address(owner).unwrap_or_default(); + + match tokens.get(index as usize) { + Some(name) => Ok(name.clone().into()), + None => Err(PSP34Error::TokenNotExists), + } + } + + #[ink(message)] + fn token_by_index(&self, _index: u128) -> core::result::Result { + Err(PSP34Error::Custom("Not Supported".to_string())) + } + } + impl PSP34Metadata for DomainNameService { #[ink(message)] fn get_attribute(&self, id: Id, key: Vec) -> Option> { diff --git a/azns_registry/psp34_standard.rs b/azns_registry/psp34_standard.rs index c03056b..6260c8c 100644 --- a/azns_registry/psp34_standard.rs +++ b/azns_registry/psp34_standard.rs @@ -118,6 +118,23 @@ pub trait PSP34 { fn total_supply(&self) -> Balance; } +#[ink::trait_definition] +pub trait PSP34Enumerable { + /// Returns a token `Id` owned by `owner` at a given `index` of its token list. + /// Use along with `balance_of` to enumerate all of ``owner``'s tokens. + /// + /// The start index is zero. + #[ink(message)] + fn owners_token_by_index(&self, owner: AccountId, index: u128) -> Result; + + /// Returns a token `Id` at a given `index` of all the tokens stored by the contract. + /// Use along with `total_supply` to enumerate all tokens. + /// + /// The start index is zero. + #[ink(message)] + fn token_by_index(&self, index: u128) -> Result; +} + #[ink::trait_definition] pub trait PSP34Metadata { /// Returns the attribute of `id` for the given `key`. From 279e34dfa1e8bf4649557f8e7dd1b79aae63fcf0 Mon Sep 17 00:00:00 2001 From: realnimish Date: Fri, 7 Apr 2023 21:10:05 +0530 Subject: [PATCH 09/15] feat(ArtZero-Integration): add stub for marketplace integration --- azns_registry/art_zero_traits.rs | 44 ++++++++++++++++++++ azns_registry/lib.rs | 70 ++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 azns_registry/art_zero_traits.rs diff --git a/azns_registry/art_zero_traits.rs b/azns_registry/art_zero_traits.rs new file mode 100644 index 0000000..98f363c --- /dev/null +++ b/azns_registry/art_zero_traits.rs @@ -0,0 +1,44 @@ +use crate::psp34_standard::Id; +use ink::prelude::{string::String, vec::Vec}; +use ink::primitives::AccountId; + +#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum ArtZeroError { + Custom(String), +} + +#[ink::trait_definition] +pub trait Psp34Traits { + /// This function sets the baseURI for the NFT contract. Only Contract Owner can perform this function. baseURI is the location of the metadata files if the NFT collection use external source to keep their NFT artwork. ArtZero uses IPFS by default, the baseURI can have format like this: ipfs:/// + #[ink(message)] + fn set_base_uri(&mut self, uri: String) -> Result<(), ArtZeroError>; + + /// This function set the attributes to each NFT. Only Contract Owner can perform this function. The metadata input is an array of [(attribute, value)]. The attributes in ArtZero platform are the NFT traits. + #[ink(message)] + fn set_multiple_attributes( + &mut self, + token_id: Id, + metadata: Vec<(String, String)>, + ) -> Result<(), ArtZeroError>; + + /// This function returns all available attributes of each NFT + #[ink(message)] + fn get_attributes(&self, token_id: Id, attributes: Vec) -> Vec; + + /// This function return how many unique attributes in the contract + #[ink(message)] + fn get_attribute_count(&self) -> u32; + + /// This function return the attribute name using attribute index. Beacause attributes of an NFT can be set to anything by Contract Owner, AztZero uses this function to get all attributes of an NFT + #[ink(message)] + fn get_attribute_name(&self, index: u32) -> String; + + /// This function return the metadata location of an NFT. The format is baseURI/.json + #[ink(message)] + fn token_uri(&self, token_id: Id) -> String; + + /// This function return the owner of the NFT Contract + #[ink(message)] + fn get_owner(&self) -> AccountId; +} diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 8d0da24..6589993 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -1,11 +1,13 @@ #![cfg_attr(not(feature = "std"), no_std)] mod address_dict; +mod art_zero_traits; mod psp34_standard; #[ink::contract] mod azns_registry { use crate::address_dict::AddressDict; + use crate::art_zero_traits::*; use crate::psp34_standard::*; use ink::env::call::FromAccountId; use ink::env::hash::CryptoHash; @@ -1297,6 +1299,74 @@ mod azns_registry { } } } + + impl Psp34Traits for DomainNameService { + #[ink(message)] + fn get_owner(&self) -> AccountId { + self.admin + } + + #[ink(message)] + fn token_uri(&self, _token_id: Id) -> String { + String::new() + } + + #[ink(message)] + fn set_base_uri(&mut self, _uri: String) -> core::result::Result<(), ArtZeroError> { + Err(ArtZeroError::Custom("NotSupported".to_string())) + } + + #[ink(message)] + fn get_attribute_count(&self) -> u32 { + 0 + } + + #[ink(message)] + fn get_attribute_name(&self, _index: u32) -> String { + String::new() + } + + #[ink(message)] + fn get_attributes(&self, token_id: Id, attributes: Vec) -> Vec { + let name: String = match token_id + .try_into() + .map_err(|_| ArtZeroError::Custom("TokenNotFound".to_string())) + { + Ok(name) => name, + _ => return Default::default(), + }; + + use ink::prelude::collections::BTreeMap; + + let mut map = BTreeMap::new(); + self.get_metadata_ref(&name) + .into_iter() + .for_each(|(key, val)| { + map.insert(key, val); + }); + + attributes + .into_iter() + .map(|key| map.get(&key).unwrap_or(&String::new()).clone()) + .collect() + } + + #[ink(message)] + fn set_multiple_attributes( + &mut self, + token_id: Id, + metadata: Vec<(String, String)>, + ) -> core::result::Result<(), ArtZeroError> { + let name: String = token_id + .try_into() + .map_err(|_| ArtZeroError::Custom("TokenNotFound".to_string()))?; + + let records = metadata.into_iter().map(|(k, v)| (k, Some(v))).collect(); + + self.update_records(name, records, false) + .map_err(|_| ArtZeroError::Custom("UpdateFailed".to_string())) + } + } } #[cfg(test)] From 4fcf655e58a66c955d800c469f791dc53b52219b Mon Sep 17 00:00:00 2001 From: realnimish Date: Tue, 11 Apr 2023 20:38:47 +0530 Subject: [PATCH 10/15] feat(ArtZero-Integration): integration complete --- azns_registry/lib.rs | 74 ++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 6589993..094b8b4 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -145,6 +145,8 @@ mod azns_registry { /// TLD tld: String, + /// Base URI + base_uri: String, /// Total supply (including expired names) total_supply: Balance, } @@ -207,6 +209,7 @@ mod azns_registry { merkle_verifier_addr: Option, reserved_names: Option)>>, tld: String, + base_uri: String, metadata_size_limit: Option, ) -> Self { // Initializing NameChecker @@ -235,6 +238,7 @@ mod azns_registry { reserved_names: Default::default(), operator_approvals: Default::default(), tld, + base_uri, metadata_size_limit, total_supply: 0, }; @@ -679,6 +683,11 @@ mod azns_registry { self.tld.clone() } + #[ink(message)] + pub fn get_base_uri(&self) -> String { + self.base_uri.clone() + } + /// Returns `true` when contract is in whitelist-phase /// and `false` when it is in public-phase #[ink(message)] @@ -1307,23 +1316,42 @@ mod azns_registry { } #[ink(message)] - fn token_uri(&self, _token_id: Id) -> String { - String::new() + fn token_uri(&self, token_id: Id) -> String { + let name: core::result::Result = token_id.try_into(); + + match name { + Ok(name) => self.base_uri.clone() + &name + &String::from(".json"), + _ => String::new(), + } } #[ink(message)] - fn set_base_uri(&mut self, _uri: String) -> core::result::Result<(), ArtZeroError> { - Err(ArtZeroError::Custom("NotSupported".to_string())) + fn set_base_uri(&mut self, uri: String) -> core::result::Result<(), ArtZeroError> { + self.ensure_admin() + .map_err(|_| ArtZeroError::Custom("Not Authorised".to_string()))?; + + if uri.len() == 0 { + return Err(ArtZeroError::Custom("Zero length string".to_string())); + } + self.base_uri = uri; + Ok(()) } #[ink(message)] fn get_attribute_count(&self) -> u32 { - 0 + 4 } #[ink(message)] - fn get_attribute_name(&self, _index: u32) -> String { - String::new() + fn get_attribute_name(&self, index: u32) -> String { + let attr = match index { + 0 => "TLD", + 1 => "Length", + 2 => "Registration", + 3 => "Expiration", + _ => "", + }; + attr.into() } #[ink(message)] @@ -1336,35 +1364,25 @@ mod azns_registry { _ => return Default::default(), }; - use ink::prelude::collections::BTreeMap; - - let mut map = BTreeMap::new(); - self.get_metadata_ref(&name) - .into_iter() - .for_each(|(key, val)| { - map.insert(key, val); - }); - attributes .into_iter() - .map(|key| map.get(&key).unwrap_or(&String::new()).clone()) + .map(|key| match key.as_str() { + "TLD" => self.tld.clone(), + "Length" => name.chars().count().to_string(), + "Registration" => "".to_string(), + "Expiration" => "".to_string(), + _ => "".to_string(), + }) .collect() } #[ink(message)] fn set_multiple_attributes( &mut self, - token_id: Id, - metadata: Vec<(String, String)>, + _token_id: Id, + _metadata: Vec<(String, String)>, ) -> core::result::Result<(), ArtZeroError> { - let name: String = token_id - .try_into() - .map_err(|_| ArtZeroError::Custom("TokenNotFound".to_string()))?; - - let records = metadata.into_iter().map(|(k, v)| (k, Some(v))).collect(); - - self.update_records(name, records, false) - .map_err(|_| ArtZeroError::Custom("UpdateFailed".to_string())) + Err(ArtZeroError::Custom("Not Supported".to_string())) } } } @@ -1398,6 +1416,7 @@ mod tests { None, None, "azero".to_string(), + "ipfs://05121999/".to_string(), None, ) } @@ -2339,6 +2358,7 @@ mod tests { None, Some(reserved_list), "azero".to_string(), + "ipfs://05121999/".to_string(), None, ); From 6825ba85c4f71094482080cdd042a19589e955f1 Mon Sep 17 00:00:00 2001 From: realnimish Date: Wed, 12 Apr 2023 15:26:46 +0530 Subject: [PATCH 11/15] feat: store registration timestamp as well --- azns_registry/lib.rs | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 094b8b4..05cba4e 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -123,8 +123,8 @@ mod azns_registry { /// Mapping from name to addresses associated with it name_to_address_dict: Mapping>, - /// Mapping from name to its expiry timestamp - name_to_expiry: Mapping, + /// Mapping from name to its registration period (timestamp) + name_to_period: Mapping, /// Metadata metadata: Mapping, ManualKey<201>>, metadata_size_limit: Option, @@ -228,7 +228,7 @@ mod azns_registry { name_checker, fee_calculator, name_to_address_dict: Mapping::default(), - name_to_expiry: Mapping::default(), + name_to_period: Mapping::default(), owner_to_names: Default::default(), metadata: Default::default(), address_to_primary_name: Default::default(), @@ -578,9 +578,16 @@ mod azns_registry { self.get_address_dict_ref(&name).map(|x| x.resolved) } + #[ink(message)] + pub fn get_registration_date(&self, name: String) -> Result { + self.get_registration_period_ref(&name) + .map(|(registration, _)| registration) + } + #[ink(message)] pub fn get_expiry_date(&self, name: String) -> Result { - self.name_to_expiry.get(&name).ok_or(Error::NameDoesntExist) + self.get_registration_period_ref(&name) + .map(|(_, expiry)| expiry) } /// Gets all records @@ -873,9 +880,11 @@ mod azns_registry { _ => (), // Name is available } + let registration = self.env().block_timestamp(); + let address_dict = AddressDict::new(recipient.clone()); self.name_to_address_dict.insert(name, &address_dict); - self.name_to_expiry.insert(name, &expiry); + self.name_to_period.insert(name, &(registration, expiry)); /* Update convenience mapping for owned names */ self.add_name_to_owner(recipient, name); @@ -909,7 +918,7 @@ mod azns_registry { }; self.name_to_address_dict.remove(name); - self.name_to_expiry.remove(name); + self.name_to_period.remove(name); self.metadata.remove(name); self.remove_name_from_owner(&address_dict.owner, &name); @@ -1178,9 +1187,13 @@ mod azns_registry { .unwrap_or_default() } + fn get_registration_period_ref(&self, name: &str) -> Result<(u64, u64)> { + self.name_to_period.get(name).ok_or(Error::NameDoesntExist) + } + fn has_name_expired(&self, name: &str) -> Result { - match self.name_to_expiry.get(name) { - Some(expiry) => Ok(expiry <= self.env().block_timestamp()), + match self.name_to_period.get(name) { + Some((_, expiry)) => Ok(expiry <= self.env().block_timestamp()), None => Err(Error::NameDoesntExist), } } @@ -1369,8 +1382,14 @@ mod azns_registry { .map(|key| match key.as_str() { "TLD" => self.tld.clone(), "Length" => name.chars().count().to_string(), - "Registration" => "".to_string(), - "Expiration" => "".to_string(), + "Registration" => match self.get_registration_period_ref(&name) { + Ok(period) => period.0.to_string(), + _ => String::new(), + }, + "Expiration" => match self.get_registration_period_ref(&name) { + Ok(period) => period.1.to_string(), + _ => String::new(), + }, _ => "".to_string(), }) .collect() From c64fce2d112744e0b837055c00ec224cabf43262 Mon Sep 17 00:00:00 2001 From: Dennis Zoma Date: Thu, 13 Apr 2023 16:55:33 +0200 Subject: [PATCH 12/15] feat: Add `baseUri` to `deployRegistry` script --- scripts/deploy/deployRegistry.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/deploy/deployRegistry.ts b/scripts/deploy/deployRegistry.ts index 7da7498..6af521a 100644 --- a/scripts/deploy/deployRegistry.ts +++ b/scripts/deploy/deployRegistry.ts @@ -13,6 +13,7 @@ export type RegistryArgs = { merkleVerifierAddress: string reservedNames: [string, string][] // [name, address | null][] tld: string + baseUri: string metadataSizeLimit: BN } export const deployRegistry: DeployFn = async ({ api, account }, customArgs) => { @@ -24,6 +25,7 @@ export const deployRegistry: DeployFn = async ({ api, account }, c merkleVerifierAddress: null, reservedNames: [], tld: 'azero', + baseUri: 'https://dev.azero.domains/api/v1/metadata/', metadataSizeLimit: null, } as RegistryArgs, customArgs, @@ -37,6 +39,7 @@ export const deployRegistry: DeployFn = async ({ api, account }, c args.merkleVerifierAddress, args.reservedNames, args.tld, + args.baseUri, args.metadataSizeLimit, ]) } From de0d0950aa19e9fec1de10ec451f481ca7835c89 Mon Sep 17 00:00:00 2001 From: realnimish Date: Tue, 18 Apr 2023 02:04:53 +0530 Subject: [PATCH 13/15] chore: made the requested changes --- azns_registry/lib.rs | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 05cba4e..1ddc736 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -109,7 +109,7 @@ mod azns_registry { } #[ink(storage)] - pub struct DomainNameService { + pub struct Registry { /// Admin of the contract can perform root operations admin: AccountId, /// Contract which verifies the validity of a name @@ -123,7 +123,7 @@ mod azns_registry { /// Mapping from name to addresses associated with it name_to_address_dict: Mapping>, - /// Mapping from name to its registration period (timestamp) + /// Mapping from name to its registration period (registration_timestamp, expiration_timestamp) name_to_period: Mapping, /// Metadata metadata: Mapping, ManualKey<201>>, @@ -199,7 +199,7 @@ mod azns_registry { FeeError(azns_fee_calculator::Error), } - impl DomainNameService { + impl Registry { /// Creates a new AZNS contract. #[ink(constructor)] pub fn new( @@ -409,7 +409,7 @@ mod azns_registry { keep_resolving: bool, data: Vec, ) -> core::result::Result<(), PSP34Error> { - self.transfer_for( + self.transfer_name( to, &name, keep_metadata, @@ -579,15 +579,8 @@ mod azns_registry { } #[ink(message)] - pub fn get_registration_date(&self, name: String) -> Result { + pub fn get_registration_period(&self, name: String) -> Result<(u64, u64)> { self.get_registration_period_ref(&name) - .map(|(registration, _)| registration) - } - - #[ink(message)] - pub fn get_expiry_date(&self, name: String) -> Result { - self.get_registration_period_ref(&name) - .map(|(_, expiry)| expiry) } /// Gets all records @@ -934,7 +927,7 @@ mod azns_registry { }); } - fn transfer_for( + fn transfer_name( &mut self, to: AccountId, name: &str, @@ -991,7 +984,6 @@ mod azns_registry { self.operator_approvals .remove((&owner, &caller, &Some(id.clone()))); - // TODO safe transfer check self.safe_transfer_check(&caller, &owner, &to, &id, &data)?; Self::env().emit_event(Transfer { @@ -1003,6 +995,7 @@ mod azns_registry { Ok(()) } + #[cfg_attr(test, allow(unused))] fn safe_transfer_check( &mut self, operator: &AccountId, @@ -1199,7 +1192,7 @@ mod azns_registry { } } - impl PSP34 for DomainNameService { + impl PSP34 for Registry { // TLD is our collection id #[ink(message)] fn collection_id(&self) -> Id { @@ -1277,7 +1270,7 @@ mod azns_registry { data: Vec, ) -> core::result::Result<(), PSP34Error> { let name: String = id.try_into()?; - self.transfer_for(to, &name, false, false, false, &data) + self.transfer_name(to, &name, false, false, false, &data) } #[ink(message)] @@ -1286,7 +1279,7 @@ mod azns_registry { } } - impl PSP34Enumerable for DomainNameService { + impl PSP34Enumerable for Registry { #[ink(message)] fn owners_token_by_index( &self, @@ -1307,7 +1300,7 @@ mod azns_registry { } } - impl PSP34Metadata for DomainNameService { + impl PSP34Metadata for Registry { #[ink(message)] fn get_attribute(&self, id: Id, key: Vec) -> Option> { match id.try_into() { @@ -1322,7 +1315,7 @@ mod azns_registry { } } - impl Psp34Traits for DomainNameService { + impl Psp34Traits for Registry { #[ink(message)] fn get_owner(&self) -> AccountId { self.admin @@ -1427,8 +1420,8 @@ mod tests { set_caller::(caller); } - fn get_test_name_service() -> DomainNameService { - DomainNameService::new( + fn get_test_name_service() -> Registry { + Registry::new( default_accounts().alice, None, None, @@ -2370,7 +2363,7 @@ mod tests { let accounts = default_accounts(); let reserved_list = vec![("bob".to_string(), Some(accounts.bob))]; - let mut contract = DomainNameService::new( + let mut contract = Registry::new( default_accounts().alice, None, None, From aa7ec224c6e78da0ec3071b799d58f29298c4a46 Mon Sep 17 00:00:00 2001 From: realnimish Date: Tue, 18 Apr 2023 12:37:36 +0530 Subject: [PATCH 14/15] fix: make `get_attribute` consistent with others --- azns_registry/lib.rs | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 1ddc736..0f7717c 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -1190,6 +1190,22 @@ mod azns_registry { None => Err(Error::NameDoesntExist), } } + + fn get_static_attribute_ref(&self, name: &str, key: &str) -> Option { + match key { + "TLD" => Some(self.tld.clone()), + "Length" => Some(name.chars().count().to_string()), + "Registration" => Some(match self.get_registration_period_ref(&name) { + Ok(period) => period.0.to_string(), + _ => String::new(), + }), + "Expiration" => Some(match self.get_registration_period_ref(&name) { + Ok(period) => period.1.to_string(), + _ => String::new(), + }), + _ => None, + } + } } impl PSP34 for Registry { @@ -1303,12 +1319,14 @@ mod azns_registry { impl PSP34Metadata for Registry { #[ink(message)] fn get_attribute(&self, id: Id, key: Vec) -> Option> { - match id.try_into() { + match TryInto::::try_into(id) { Ok(name) => { let Ok(key) = String::from_utf8(key) else { return None; }; - self.get_record(name, key).map(|val| val.into_bytes()).ok() + + self.get_static_attribute_ref(&name, &key) + .map(|s| s.into_bytes()) } Err(_) => None, } @@ -1372,18 +1390,9 @@ mod azns_registry { attributes .into_iter() - .map(|key| match key.as_str() { - "TLD" => self.tld.clone(), - "Length" => name.chars().count().to_string(), - "Registration" => match self.get_registration_period_ref(&name) { - Ok(period) => period.0.to_string(), - _ => String::new(), - }, - "Expiration" => match self.get_registration_period_ref(&name) { - Ok(period) => period.1.to_string(), - _ => String::new(), - }, - _ => "".to_string(), + .map(|key| { + self.get_static_attribute_ref(&name, &key) + .unwrap_or_default() }) .collect() } From 3cddea5d6e6a83f81e39191a1accf874c59f709e Mon Sep 17 00:00:00 2001 From: realnimish Date: Tue, 18 Apr 2023 21:01:31 +0530 Subject: [PATCH 15/15] refactor: create separate folder for external/shared traits --- Cargo.toml | 2 +- azns_registry/Cargo.toml | 2 ++ azns_registry/lib.rs | 6 ++---- interfaces/Cargo.toml | 17 +++++++++++++++++ .../art_zero_traits.rs | 0 interfaces/lib.rs | 4 ++++ {azns_registry => interfaces}/psp34_standard.rs | 0 7 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 interfaces/Cargo.toml rename {azns_registry => interfaces}/art_zero_traits.rs (100%) create mode 100644 interfaces/lib.rs rename {azns_registry => interfaces}/psp34_standard.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 144d9bc..c0c20dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] -members = ["azns_merkle_verifier", "azns_registry", "azns_name_checker", "azns_fee_calculator", "azns_router"] +members = ["azns_merkle_verifier", "azns_registry", "azns_name_checker", "azns_fee_calculator", "azns_router", "interfaces"] diff --git a/azns_registry/Cargo.toml b/azns_registry/Cargo.toml index 823ec23..f65f425 100755 --- a/azns_registry/Cargo.toml +++ b/azns_registry/Cargo.toml @@ -8,6 +8,7 @@ publish = false [dependencies] ink = { version = "4.0.0", default-features = false } +interfaces = { path = "../interfaces", default-features = false } azns_name_checker = { path = "../azns_name_checker", default-features = false, features = ["ink-as-dependency"] } azns_fee_calculator = { path = "../azns_fee_calculator", default-features = false, features = ["ink-as-dependency"] } azns_merkle_verifier = { path = "../azns_merkle_verifier", default-features = false, features = ["ink-as-dependency"] } @@ -30,6 +31,7 @@ std = [ "ink/std", "scale/std", "scale-info/std", + "interfaces/std", "azns_name_checker/std", "azns_fee_calculator/std", "azns_merkle_verifier/std", diff --git a/azns_registry/lib.rs b/azns_registry/lib.rs index 0f7717c..25314d9 100644 --- a/azns_registry/lib.rs +++ b/azns_registry/lib.rs @@ -1,20 +1,18 @@ #![cfg_attr(not(feature = "std"), no_std)] mod address_dict; -mod art_zero_traits; -mod psp34_standard; #[ink::contract] mod azns_registry { use crate::address_dict::AddressDict; - use crate::art_zero_traits::*; - use crate::psp34_standard::*; use ink::env::call::FromAccountId; use ink::env::hash::CryptoHash; use ink::prelude::string::{String, ToString}; use ink::prelude::vec::Vec; use ink::storage::traits::ManualKey; use ink::storage::{Lazy, Mapping}; + use interfaces::art_zero_traits::*; + use interfaces::psp34_standard::*; use azns_fee_calculator::FeeCalculatorRef; use azns_merkle_verifier::MerkleVerifierRef; diff --git a/interfaces/Cargo.toml b/interfaces/Cargo.toml new file mode 100644 index 0000000..2660908 --- /dev/null +++ b/interfaces/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "interfaces" +version = "0.1.0" +edition = "2021" + +[dependencies] +ink = { version = "4.0.0", default-features = false } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.3", default-features = false, features = ["derive"] } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = ["ink/std", "scale/std", "scale-info/std"] diff --git a/azns_registry/art_zero_traits.rs b/interfaces/art_zero_traits.rs similarity index 100% rename from azns_registry/art_zero_traits.rs rename to interfaces/art_zero_traits.rs diff --git a/interfaces/lib.rs b/interfaces/lib.rs new file mode 100644 index 0000000..090d41d --- /dev/null +++ b/interfaces/lib.rs @@ -0,0 +1,4 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod art_zero_traits; +pub mod psp34_standard; diff --git a/azns_registry/psp34_standard.rs b/interfaces/psp34_standard.rs similarity index 100% rename from azns_registry/psp34_standard.rs rename to interfaces/psp34_standard.rs