diff --git a/.all-contributorsrc b/.all-contributorsrc
index 7a465d22..8c7caac1 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -63,6 +63,15 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "mubarak23",
+ "name": "Mubarak Muhammad Aminu",
+ "avatar_url": "https://avatars.githubusercontent.com/u/7858376?v=4",
+ "profile": "http://mubarak23.github.io/",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/README.md b/README.md
index b42059f4..b14f42ff 100644
--- a/README.md
+++ b/README.md
@@ -114,6 +114,7 @@ Thanks goes to these wonderful people. Follow the [contributors guide](https://g
Abdulhakeem Abdulazeez Ayodeji 💻 |
Trunks @ Carbonable 💻 |
ptisserand 💻 |
+ Mubarak Muhammad Aminu 💻 |
diff --git a/onchain/src/lib.cairo b/onchain/src/lib.cairo
index 158e7378..5c6a3325 100644
--- a/onchain/src/lib.cairo
+++ b/onchain/src/lib.cairo
@@ -3,6 +3,7 @@ pub mod interfaces;
use art_peace::ArtPeace;
use interfaces::{IArtPeace, IArtPeaceDispatcher, IArtPeaceDispatcherTrait, Pixel};
+
mod quests {
pub mod interfaces;
pub mod pixel_quest;
@@ -33,6 +34,14 @@ mod nfts {
};
}
+mod username_store {
+ pub mod interfaces;
+ pub mod username_store;
+
+ use interfaces::{IUsernameStore, IUsernameStoreDispatcher, IUsernameStoreDispatcherTrait};
+ use username_store::UsernameStore;
+}
+
mod mocks {
pub mod erc20_mock;
}
@@ -40,5 +49,7 @@ mod mocks {
#[cfg(test)]
mod tests {
mod art_peace;
+ mod username_store;
pub(crate) mod utils;
}
+
diff --git a/onchain/src/tests/username_store.cairo b/onchain/src/tests/username_store.cairo
new file mode 100644
index 00000000..f4f4ee38
--- /dev/null
+++ b/onchain/src/tests/username_store.cairo
@@ -0,0 +1,36 @@
+use snforge_std::{declare, ContractClassTrait};
+use art_peace::username_store::interfaces::{
+ IUsernameStoreDispatcher, IUsernameStoreDispatcherTrait
+};
+use starknet::{ContractAddress, get_caller_address, get_contract_address, contract_address_const};
+
+fn deploy_contract() -> ContractAddress {
+ let contract = declare("UsernameStore");
+
+ return contract.deploy(@ArrayTrait::new()).unwrap();
+}
+
+#[test]
+fn test_claim_username() {
+ let contract_address = deploy_contract();
+ let dispatcher = IUsernameStoreDispatcher { contract_address };
+ dispatcher.claim_username('deal');
+
+ let username_address = dispatcher.get_username('deal');
+
+ assert(contract_address != username_address, 'Username not claimed');
+}
+#[test]
+fn test_transfer_username() {
+ let contract_address = deploy_contract();
+ let dispatcher = IUsernameStoreDispatcher { contract_address };
+ dispatcher.claim_username('devsweet');
+
+ let second_contract_address = contract_address_const::<1>();
+
+ dispatcher.transfer_username('devsweet', second_contract_address);
+
+ let username_address = dispatcher.get_username('devsweet');
+
+ assert(username_address == second_contract_address, 'Username not Transferred');
+}
diff --git a/onchain/src/username_store/interfaces.cairo b/onchain/src/username_store/interfaces.cairo
new file mode 100644
index 00000000..04ea5850
--- /dev/null
+++ b/onchain/src/username_store/interfaces.cairo
@@ -0,0 +1,8 @@
+use starknet::ContractAddress;
+
+#[starknet::interface]
+pub trait IUsernameStore {
+ fn claim_username(ref self: TContractState, key: felt252);
+ fn transfer_username(ref self: TContractState, key: felt252, new_Address: ContractAddress);
+ fn get_username(ref self: TContractState, key: felt252) -> ContractAddress;
+}
diff --git a/onchain/src/username_store/username_store.cairo b/onchain/src/username_store/username_store.cairo
new file mode 100644
index 00000000..309a5fe2
--- /dev/null
+++ b/onchain/src/username_store/username_store.cairo
@@ -0,0 +1,79 @@
+pub mod UserNameClaimErrors {
+ pub const USERNAME_CLAIMED: felt252 = 'username_claimed';
+ pub const USERNAME_CANNOT_BE_TRANSFER: felt252 = 'username_cannot_be_transferred';
+}
+
+#[starknet::contract]
+pub mod UsernameStore {
+ use starknet::{get_caller_address, ContractAddress, contract_address_const};
+ use art_peace::username_store::IUsernameStore;
+ use super::UserNameClaimErrors;
+
+ #[storage]
+ struct Storage {
+ usernames: LegacyMap::
+ }
+
+ #[event]
+ #[derive(Drop, starknet::Event)]
+ enum Event {
+ UserNameClaimed: UserNameClaimed,
+ UserNameTransferred: UserNameTransferred
+ }
+
+ #[derive(Drop, starknet::Event)]
+ struct UserNameClaimed {
+ #[key]
+ username: felt252,
+ address: ContractAddress
+ }
+
+ #[derive(Drop, starknet::Event)]
+ struct UserNameTransferred {
+ #[key]
+ username: felt252,
+ address: ContractAddress
+ }
+
+ #[abi(embed_v0)]
+ pub impl UsernameStore of IUsernameStore {
+ fn claim_username(ref self: ContractState, key: felt252) {
+ let mut username_address = self.usernames.read(key);
+
+ assert(
+ username_address == contract_address_const::<0>(),
+ UserNameClaimErrors::USERNAME_CLAIMED
+ );
+
+ self.usernames.write(key, get_caller_address());
+
+ self
+ .emit(
+ Event::UserNameClaimed(
+ UserNameClaimed { username: key, address: get_caller_address() }
+ )
+ )
+ }
+
+ fn transfer_username(ref self: ContractState, key: felt252, new_Address: ContractAddress) {
+ let username_address = self.usernames.read(key);
+
+ if username_address != get_caller_address() {
+ core::panic_with_felt252(UserNameClaimErrors::USERNAME_CANNOT_BE_TRANSFER);
+ }
+
+ self.usernames.write(key, new_Address);
+
+ self
+ .emit(
+ Event::UserNameTransferred(
+ UserNameTransferred { username: key, address: new_Address }
+ )
+ )
+ }
+
+ fn get_username(ref self: ContractState, key: felt252) -> ContractAddress {
+ self.usernames.read(key)
+ }
+ }
+}