Skip to content

Commit

Permalink
Merge pull request #294 from EmmanuelAR/feat/289
Browse files Browse the repository at this point in the history
Feat/289
  • Loading branch information
adrianvrj authored Dec 16, 2024
2 parents 03f0f53 + bd8f18d commit defdf26
Show file tree
Hide file tree
Showing 22 changed files with 268 additions and 135 deletions.
2 changes: 2 additions & 0 deletions contracts/src/constants.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod funds;
pub mod donator;
pub mod errors;
pub mod starknet;
pub mod fund_manager;
1 change: 1 addition & 0 deletions contracts/src/constants/fund_manager.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod fund_manager_constants;
4 changes: 1 addition & 3 deletions contracts/src/constants/funds.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
pub mod state_constants;
pub mod fund_constants;
pub mod fund_manager_constants;
pub mod starknet_constants;

17 changes: 17 additions & 0 deletions contracts/src/constants/funds/fund_constants.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,20 @@ pub mod FundConstants {
pub const INITIAL_GOAL: u256 = 0;
pub const MINIMUM_GOAL: u256 = 500;
}
// *************************************************************************
// FUND TYPES CONSTANTS
// *************************************************************************
pub mod FundTypeConstants {
pub const PROJECT: u8 = 1;
pub const CHARITY: u8 = 2;
}
// *************************************************************************
// FUND STATES CONSTANTS
// *************************************************************************
pub mod FundStates {
pub const INNACTIVE: u8 = 0;
pub const RECOLLECTING_VOTES: u8 = 1;
pub const RECOLLECTING_DONATIONS: u8 = 2;
pub const CLOSED: u8 = 3;
pub const WITHDRAW: u8 = 4;
}
10 changes: 0 additions & 10 deletions contracts/src/constants/funds/state_constants.cairo

This file was deleted.

1 change: 1 addition & 0 deletions contracts/src/constants/starknet.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod starknet_constants;
File renamed without changes.
31 changes: 24 additions & 7 deletions contracts/src/fund.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub trait IFund<TContractState> {
fn get_evidence_link(self: @TContractState) -> ByteArray;
fn set_contact_handle(ref self: TContractState, contact_handle: ByteArray);
fn get_contact_handle(self: @TContractState) -> ByteArray;
fn set_type(ref self: TContractState, fund_type: u8);
fn get_type(self: @TContractState) -> u8;
}

#[starknet::contract]
Expand All @@ -34,11 +36,10 @@ pub mod Fund {
use starknet::contract_address_const;
use starknet::get_contract_address;
use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait};
use gostarkme::constants::{funds::{state_constants::FundStates},};
use gostarkme::constants::{
funds::{fund_constants::FundConstants, fund_manager_constants::FundManagerConstants},
};
use gostarkme::constants::{funds::{starknet_constants::StarknetConstants},};
use gostarkme::constants::{funds::{fund_constants::FundStates},};
use gostarkme::constants::{funds::{fund_constants::FundConstants},};
use gostarkme::constants::{fund_manager::{fund_manager_constants::FundManagerConstants},};
use gostarkme::constants::{starknet::{starknet_constants::StarknetConstants},};

// *************************************************************************
// EVENTS
Expand Down Expand Up @@ -89,7 +90,8 @@ pub mod Fund {
goal: u256,
state: u8,
evidence_link: ByteArray,
contact_handle: ByteArray
contact_handle: ByteArray,
fund_type: u8,
}

// *************************************************************************
Expand All @@ -104,7 +106,8 @@ pub mod Fund {
goal: u256,
evidence_link: ByteArray,
contact_handle: ByteArray,
reason: ByteArray
reason: ByteArray,
fund_type: u8,
) {
self.id.write(id);
self.owner.write(owner);
Expand All @@ -115,6 +118,7 @@ pub mod Fund {
self.state.write(FundStates::RECOLLECTING_VOTES);
self.evidence_link.write(evidence_link);
self.contact_handle.write(contact_handle);
self.fund_type.write(fund_type);
}

// *************************************************************************
Expand Down Expand Up @@ -283,6 +287,19 @@ pub mod Fund {
fn get_contact_handle(self: @ContractState) -> ByteArray {
return self.contact_handle.read();
}
fn set_type(ref self: ContractState, fund_type: u8) {
let caller = get_caller_address();
let valid_address_1 = contract_address_const::<FundManagerConstants::VALID_ADDRESS_1>();
let valid_address_2 = contract_address_const::<FundManagerConstants::VALID_ADDRESS_2>();
assert!(
valid_address_1 == caller || valid_address_2 == caller,
"Only Admins can change the fund type."
);
self.fund_type.write(fund_type);
}
fn get_type(self: @ContractState) -> u8 {
return self.fund_type.read();
}
}
// *************************************************************************
// INTERNALS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ pub trait IFundManager<TContractState> {
goal: u256,
evidence_link: ByteArray,
contact_handle: ByteArray,
reason: ByteArray
reason: ByteArray,
fund_type: u8,
);
fn get_current_id(self: @TContractState) -> u128;
fn get_fund(self: @TContractState, id: u128) -> ContractAddress;
Expand Down Expand Up @@ -85,6 +86,7 @@ pub mod FundManager {
evidence_link: ByteArray,
contact_handle: ByteArray,
reason: ByteArray,
fund_type: u8
) {
assert(goal >= FundConstants::MINIMUM_GOAL, 'Goal must be at least 500');
let mut call_data: Array<felt252> = array![];
Expand All @@ -95,6 +97,7 @@ pub mod FundManager {
Serde::serialize(@evidence_link, ref call_data);
Serde::serialize(@contact_handle, ref call_data);
Serde::serialize(@reason, ref call_data);
Serde::serialize(@fund_type, ref call_data);
let (new_fund_address, _) = deploy_syscall(
self.fund_class_hash.read(), 12345, call_data.span(), false
)
Expand Down
4 changes: 2 additions & 2 deletions contracts/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub mod constants;
// FUND
pub mod fund;
pub mod fundManager;
pub mod fund_manager;
// DONATOR
pub mod donatorManager;
pub mod donator_manager;
pub mod donator;
1 change: 1 addition & 0 deletions contracts/tests/test_donator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,4 @@ fn test_update_donator_values() {
assert(total_stark_donations == 11, 'Invalid total stark donations');
assert(max_stark_donations_to_next_level == 20, 'Invalid total stark donations');
}

2 changes: 1 addition & 1 deletion contracts/tests/test_donator_manager.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use snforge_std::{

use openzeppelin::utils::serde::SerializedAppend;

use gostarkme::donatorManager::{
use gostarkme::donator_manager::{
DonatorManager, IDonatorManagerDispatcher, IDonatorManagerDispatcherTrait
};

Expand Down
43 changes: 31 additions & 12 deletions contracts/tests/test_fund.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTr
use gostarkme::fund::Fund;
use gostarkme::fund::IFundDispatcher;
use gostarkme::fund::IFundDispatcherTrait;
use gostarkme::constants::{funds::{fund_manager_constants::FundManagerConstants},};
use gostarkme::constants::{funds::{state_constants::FundStates},};
use gostarkme::constants::{funds::{starknet_constants::StarknetConstants},};
use gostarkme::constants::{fund_manager::{fund_manager_constants::FundManagerConstants},};
use gostarkme::constants::{funds::{fund_constants::FundStates},};
use gostarkme::constants::{funds::{fund_constants::FundTypeConstants},};
use gostarkme::constants::{starknet::{starknet_constants::StarknetConstants},};

const ONE_E18: u256 = 1000000000000000000_u256;
fn ID() -> u128 {
Expand Down Expand Up @@ -73,6 +74,8 @@ fn _setup_() -> ContractAddress {
calldata.append_serde(EVIDENCE_LINK_1());
calldata.append_serde(CONTACT_HANDLE_1());
calldata.append_serde(REASON_1());
calldata.append_serde(FundTypeConstants::PROJECT);

let (contract_address, _) = contract.deploy(@calldata).unwrap();
contract_address
}
Expand Down Expand Up @@ -223,26 +226,27 @@ fn test_set_goal_unauthorized() {
fn test_receive_vote_successful() {
let contract_address = _setup_();
let dispatcher = IFundDispatcher { contract_address };
start_cheat_caller_address_global(OTHER_USER());
dispatcher.receive_vote();
let me = dispatcher.get_voter();
// Owner vote, fund have one vote
assert(me == 1, 'Owner is not in the voters');
let votes = dispatcher.get_up_votes();
assert(votes == 1, 'Vote unuseccessful');
let other_user_votes = dispatcher.get_voter(OTHER_USER());
assert(other_user_votes == 1, 'Other user is not in the voters');
let fund_votes = dispatcher.get_up_votes();
assert(fund_votes == 1, 'Vote unuseccessful');
}

#[test]
#[should_panic(expected: ('User already voted!',))]
fn test_receive_vote_unsuccessful_double_vote() {
let contract_address = _setup_();
let dispatcher = IFundDispatcher { contract_address };
start_cheat_caller_address_global(OTHER_USER());
dispatcher.receive_vote();
let me = dispatcher.get_voter();
// Owner vote, fund have one vote
assert(me == 1, 'Owner is not in the voters');
let other_user_votes = dispatcher.get_voter(OTHER_USER());
// User vote, fund have one vote
assert(other_user_votes == 1, 'Owner is not in the voters');
let votes = dispatcher.get_up_votes();
assert(votes == 1, 'Vote unuseccessful');
// Owner vote, second time
// User vote, second time
dispatcher.receive_vote();
}

Expand Down Expand Up @@ -602,3 +606,18 @@ fn test_set_contact_handle_success() {
assert(reverted_contact_handle == CONTACT_HANDLE_1(), ' revert ')
}

#[test]
fn test_set_type() {
let contract_address = _setup_();
let dispatcher = IFundDispatcher { contract_address };
let current_type = dispatcher.get_type();
assert(current_type == FundTypeConstants::PROJECT, 'Invalid type');
start_cheat_caller_address(contract_address, VALID_ADDRESS_1());
dispatcher.set_type(FundTypeConstants::CHARITY);
let new_type = dispatcher.get_type();
assert(new_type == FundTypeConstants::CHARITY, 'Set type method not working');
start_cheat_caller_address(contract_address, VALID_ADDRESS_2());
dispatcher.set_type(FundTypeConstants::PROJECT);
let new_type = dispatcher.get_type();
assert(new_type == FundTypeConstants::PROJECT, 'Set type method not working');
}
28 changes: 22 additions & 6 deletions contracts/tests/test_fund_manager.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ use snforge_std::{

use openzeppelin::utils::serde::SerializedAppend;

use gostarkme::fundManager::IFundManagerDispatcher;
use gostarkme::fundManager::IFundManagerDispatcherTrait;
use gostarkme::fundManager::FundManager;
use gostarkme::fund_manager::IFundManagerDispatcher;
use gostarkme::fund_manager::IFundManagerDispatcherTrait;
use gostarkme::fund_manager::FundManager;
use gostarkme::constants::{funds::{fund_constants::FundTypeConstants},};

fn ID() -> u128 {
1
Expand Down Expand Up @@ -54,6 +55,7 @@ fn _setup_() -> (ContractAddress, ClassHash) {
fund_calldata.append_serde(EVIDENCE_LINK());
fund_calldata.append_serde(CONTACT_HANDLE());
fund_calldata.append_serde(REASON());
fund_calldata.append_serde(FundTypeConstants::PROJECT);

let (fund_contract_address, _) = fund.deploy(@fund_calldata).unwrap();
let fund_class_hash = get_class_hash(fund_contract_address);
Expand Down Expand Up @@ -87,7 +89,10 @@ fn test_new_fund() {
start_cheat_caller_address_global(OWNER());
let (contract_address, fund_class_hash) = _setup_();
let fund_manager_contract = IFundManagerDispatcher { contract_address };
fund_manager_contract.new_fund(NAME(), GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE(), REASON());
fund_manager_contract
.new_fund(
NAME(), GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE(), REASON(), FundTypeConstants::PROJECT
);
let expected_fund_class_hash = get_class_hash(fund_manager_contract.get_fund(1));
let current_id = fund_manager_contract.get_current_id();
assert(expected_fund_class_hash == fund_class_hash, 'Invalid fund address');
Expand All @@ -100,7 +105,15 @@ fn test_new_fund_bad_goal() {
start_cheat_caller_address_global(OWNER());
let (contract_address, _) = _setup_();
let fund_manager_contract = IFundManagerDispatcher { contract_address };
fund_manager_contract.new_fund(NAME(), BAD_GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE(), REASON());
fund_manager_contract
.new_fund(
NAME(),
BAD_GOAL(),
EVIDENCE_LINK(),
CONTACT_HANDLE(),
REASON(),
FundTypeConstants::PROJECT
);
}

#[test]
Expand All @@ -113,7 +126,10 @@ fn test_fund_deployed_event() {
let mut spy = spy_events();

let current_id = fund_manager_contract.get_current_id();
fund_manager_contract.new_fund(NAME(), GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE(), REASON());
fund_manager_contract
.new_fund(
NAME(), GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE(), REASON(), FundTypeConstants::PROJECT
);

let expected_fund_class_hash = fund_manager_contract.get_fund(1);

Expand Down
4 changes: 3 additions & 1 deletion frontend/gostarkme-web/app/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ const Dashboard = () => {
}
// GET FUND ID
let fund_id = await fundContract.get_id();
// GET FUND TYPE
let fund_type = await fundContract.get_type();
fundings.push({
type: "Project",
type: Number(BigInt(fund_type)) === 1 ? "Project" : "Charity",
title: name,
description: desc,
fund_id: fund_id.toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ interface FundingStepProps {
setEvidenceLink: (name: string) => void;
contactHandle: string;
setContactHandle: (name: string) => void;
errors: { fundingName: string; goal: string ;evidenceLink: string; contactHandle: string }; // Expecting errors as props
setErrors: React.Dispatch<React.SetStateAction<{ fundingName: string; goal: string ;evidenceLink: string; contactHandle: string }>>; // Specify the type for setErrors
type: string;
setType: (name: string) => void;
errors: { fundingName: string; goal: string ;evidenceLink: string; contactHandle: string; type: string};
setErrors: React.Dispatch<React.SetStateAction<{ fundingName: string; goal: string ;evidenceLink: string; contactHandle: string; type:string }>>;
}

const FundingStep: React.FC<FundingStepProps> = ({
Expand All @@ -22,6 +24,8 @@ const FundingStep: React.FC<FundingStepProps> = ({
setEvidenceLink,
contactHandle,
setContactHandle,
type,
setType,
errors,
setErrors,
}) => {
Expand Down Expand Up @@ -67,9 +71,19 @@ const FundingStep: React.FC<FundingStepProps> = ({
const newValue = e.target.value;
setContactHandle(newValue);
if (!newValue) {
setErrors((prev) => ({ ...prev, evidenceLink: 'Contact handle is required.' }));
setErrors((prev) => ({ ...prev, contactHandle: 'Contact handle is required.' }));
} else {
setErrors((prev) => ({ ...prev, evidenceLink: '' }));
setErrors((prev) => ({ ...prev, contactHandle: '' }));
}
};

const handleType = (e: React.ChangeEvent<HTMLSelectElement>) => {
const newValue = e.target.value;
setType(newValue);
if (!newValue) {
setErrors((prev) => ({ ...prev, type: 'Type is required.' }));
} else {
setErrors((prev) => ({ ...prev, type: '' }));
}
};

Expand Down Expand Up @@ -108,6 +122,16 @@ const FundingStep: React.FC<FundingStepProps> = ({
className={`mt-4 p-2 pl-4 border rounded w-full placeholder:text-base ${errors.contactHandle ? 'border-red-500' : 'border-black'}`}
required
/>
<select
className={`mt-4 p-2 pl-4 border rounded w-full text-base ${errors.type ? 'border-red-500' : 'border-black'}`}
value={type}
onChange={handleType}
required
>
<option value="" disabled>Select the fund type</option>
<option value="1">Project</option>
<option value="2">Charity</option>
</select>

{/* Error Messages */}
{errors.fundingName && (
Expand All @@ -122,6 +146,9 @@ const FundingStep: React.FC<FundingStepProps> = ({
{errors.contactHandle && (
<p className="mt-5 text-red-500 text-center mb-4">{errors.contactHandle}</p>
)}
{errors.type && (
<p className="mt-5 text-red-500 text-center mb-4">{errors.type}</p>
)}
</div>
);
};
Expand Down
Loading

0 comments on commit defdf26

Please sign in to comment.