From 1019dd6365a0c9ab6ff3a9ffcda41375d8e5f87a Mon Sep 17 00:00:00 2001 From: Mubarak Muhammad Aminu Date: Tue, 16 Apr 2024 20:46:19 +0100 Subject: [PATCH 1/3] Ft username store contract (#32) * username store contract * write test for username store contract * implement changes base on the review recieved on the PR * fix unit test for claim_username and tranfer_username * fix merge conflict * Refactor --------- Co-authored-by: Brandon Roberts --- onchain/src/lib.cairo | 11 +++ onchain/src/tests/username_store.cairo | 36 +++++++++ onchain/src/username_store/interfaces.cairo | 8 ++ .../src/username_store/username_store.cairo | 79 +++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 onchain/src/tests/username_store.cairo create mode 100644 onchain/src/username_store/interfaces.cairo create mode 100644 onchain/src/username_store/username_store.cairo 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) + } + } +} From 54b5d5fdf05d55fbd2ce2d24cfcae6317f3d2d6f Mon Sep 17 00:00:00 2001 From: Abdulhakeem Abdulazeez Ayodeji <44169294+Ayoazeez26@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:47:25 +0100 Subject: [PATCH 2/3] feat: Accounts Tab (#50) * feat: added data for accounts tab * feat: fixed PR comments --- frontend/src/tabs/Account.css | 64 ++++++++++++++++++++++++++++ frontend/src/tabs/Account.js | 78 ++++++++++++++++++++++++++++++++--- 2 files changed, 137 insertions(+), 5 deletions(-) diff --git a/frontend/src/tabs/Account.css b/frontend/src/tabs/Account.css index e69de29b..5c3a638b 100644 --- a/frontend/src/tabs/Account.css +++ b/frontend/src/tabs/Account.css @@ -0,0 +1,64 @@ +.Account__flex { + display: flex; + margin: 8px 4px; +} + +.Account__flex--center { + align-items: center; +} + +.Account__wrap { + text-overflow: ellipsis; + overflow: hidden; +} + +.Account__list { + padding-left: 20px; + list-style-type: none; +} + +.Account__list li { + margin-bottom: 10px; + text-indent: -8px; +} + +.Account__list li:before { + content: "-"; + text-indent: -8px; +} + +.Account__input { + width: 100%; + padding: 6px 10px; +} + +.Account__input:focus { + border: 1px solid black; + outline: black; +} + +.Account__button { + background-color: black; + color: #efefef; + border: 1px solid black; + text-transform: uppercase; + cursor: pointer; + border-radius: 6px; +} + +.Account__button--edit { + padding: 2px 8px; + font-size: 8px; +} + +.Account__button--submit { + padding: 8px 16px; + font-size: 10px; +} + +.Account__user { + display: flex; + gap: 10px; + justify-content: space-between; + width: 100%; +} diff --git a/frontend/src/tabs/Account.js b/frontend/src/tabs/Account.js index 4d846979..f4e3d88b 100644 --- a/frontend/src/tabs/Account.js +++ b/frontend/src/tabs/Account.js @@ -1,13 +1,81 @@ -import React from 'react' -import './Account.css'; -import BasicTab from './BasicTab.js'; +import React, { useState, useEffect } from "react"; +import "./Account.css"; +import BasicTab from "./BasicTab.js"; -const Account = props => { +const Account = (props) => { // TODO: Create the account tab w/ wallet address, username, pixel info, top X % users ( pixels placed? ), ... + const [username, setUsername] = useState(""); + const [pixelCount, setPixelCount] = useState(2572); + const [accountRank, setAccountRank] = useState(""); + const [isUsernameSaved, saveUsername] = useState(false); + + const handleSubmit = (event) => { + event.preventDefault(); + setUsername(username); + saveUsername(true); + }; + + const editUsername = (e) => { + saveUsername(false); + } + + useEffect(() => { + if (pixelCount >= 5000) { + setAccountRank("Champion"); + } else if (pixelCount >= 3000) { + setAccountRank("Platinum"); + } else if (pixelCount >= 2000) { + setAccountRank("Gold"); + } else if (pixelCount >= 1000) { + setAccountRank("Silver"); + } else { + setAccountRank("Bronze"); + } + }); return ( +
+

Address:

+

+ 0x0000000000000000000000000000000000000000000000000000000000000000 +

+
+
+

Username:

+ {isUsernameSaved ? ( +
+

{username}

+ +
+ ) : ( +
+ + +
+ )} +
+
+

Pixel count:

+

{pixelCount}

+
+
+

Current Rank:

+

{accountRank}

+
); -} +}; export default Account; From 422d8125979035bc530d1f3f63b8b5b5e7c55bda Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Wed, 17 Apr 2024 13:06:59 -0500 Subject: [PATCH 3/3] :busts_in_silhouette: Add @mubarak23 as a contributor --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) 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
Abdulhakeem Abdulazeez Ayodeji

💻 Trunks @ Carbonable
Trunks @ Carbonable

💻 ptisserand
ptisserand

💻 + Mubarak Muhammad Aminu
Mubarak Muhammad Aminu

💻