Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/191 #192

Merged
merged 2 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions contracts/src/fund.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,13 @@ pub mod Fund {
name: ByteArray,
goal: u256,
evidence_link: ByteArray,
contact_handle: ByteArray
contact_handle: ByteArray,
reason: ByteArray
) {
self.id.write(id);
self.owner.write(owner);
self.name.write(name);
self.reason.write(" ");
self.reason.write(reason);
self.up_votes.write(FundConstants::INITIAL_UP_VOTES);
self.goal.write(goal);
self.state.write(FundStates::RECOLLECTING_VOTES);
Expand Down
7 changes: 5 additions & 2 deletions contracts/src/fundManager.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ pub trait IFundManager<TContractState> {
name: ByteArray,
goal: u256,
evidence_link: ByteArray,
contact_handle: ByteArray
contact_handle: ByteArray,
reason: ByteArray
);
fn getCurrentId(self: @TContractState) -> u128;
fn getFund(self: @TContractState, id: u128) -> ContractAddress;
Expand Down Expand Up @@ -82,7 +83,8 @@ pub mod FundManager {
name: ByteArray,
goal: u256,
evidence_link: ByteArray,
contact_handle: ByteArray
contact_handle: ByteArray,
reason: ByteArray,
) {
assert(goal >= FundConstants::MINIMUM_GOAL, 'Goal must be at least 500');
let mut call_data: Array<felt252> = array![];
Expand All @@ -92,6 +94,7 @@ pub mod FundManager {
Serde::serialize(@goal, ref call_data);
Serde::serialize(@evidence_link, ref call_data);
Serde::serialize(@contact_handle, ref call_data);
Serde::serialize(@reason, ref call_data);
let (new_fund_address, _) = deploy_syscall(
self.fund_class_hash.read(), 12345, call_data.span(), false
)
Expand Down
14 changes: 9 additions & 5 deletions contracts/tests/test_fund.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ fn FUND_MANAGER() -> ContractAddress {
fn NAME() -> ByteArray {
"Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum"
}
fn REASON() -> ByteArray {
fn REASON_1() -> ByteArray {
"Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum"
}
fn REASON_2() -> ByteArray {
"Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum"
}
fn GOAL() -> u256 {
Expand All @@ -63,6 +66,7 @@ fn _setup_() -> ContractAddress {
calldata.append_serde(GOAL());
calldata.append_serde(EVIDENCE_LINK_1());
calldata.append_serde(CONTACT_HANDLE_1());
calldata.append_serde(REASON_1());
let (contract_address, _) = contract.deploy(@calldata).unwrap();
contract_address
}
Expand All @@ -85,7 +89,7 @@ fn test_constructor() {
assert(id == ID(), 'Invalid id');
assert(owner == OWNER(), 'Invalid owner');
assert(name == NAME(), 'Invalid name');
assert(reason == " ", 'Invalid reason');
assert(reason == REASON_1(), 'Invalid reason');
assert(up_votes == 0, 'Invalid up votes');
assert(goal == GOAL(), 'Invalid goal');
assert(current_goal_state == 0, 'Invalid current goal state');
Expand All @@ -109,11 +113,11 @@ fn test_set_reason() {
let contract_address = _setup_();
let dispatcher = IFundDispatcher { contract_address };
let reason = dispatcher.getReason();
assert(reason == " ", 'Invalid reason');
assert(reason == REASON_1(), 'Invalid reason');
start_cheat_caller_address_global(OWNER());
dispatcher.setReason(REASON());
dispatcher.setReason(REASON_2());
let new_reason = dispatcher.getReason();
assert(new_reason == REASON(), 'Set reason method not working')
assert(new_reason == REASON_2(), 'Set reason method not working')
}

#[test]
Expand Down
8 changes: 4 additions & 4 deletions contracts/tests/test_fund_manager.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ fn EVIDENCE_LINK() -> ByteArray {
fn CONTACT_HANDLE() -> ByteArray {
"Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum, Lorem impsum"
}

fn _setup_() -> (ContractAddress, ClassHash) {
// Fund
let fund = declare("Fund").unwrap();
Expand All @@ -54,6 +53,7 @@ fn _setup_() -> (ContractAddress, ClassHash) {
fund_calldata.append_serde(GOAL());
fund_calldata.append_serde(EVIDENCE_LINK());
fund_calldata.append_serde(CONTACT_HANDLE());
fund_calldata.append_serde(REASON());

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 +87,7 @@ 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.newFund(NAME(), GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE());
fund_manager_contract.newFund(NAME(), GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE(), REASON());
let expected_fund_class_hash = get_class_hash(fund_manager_contract.getFund(1));
let current_id = fund_manager_contract.getCurrentId();
assert(expected_fund_class_hash == fund_class_hash, 'Invalid fund address');
Expand All @@ -100,7 +100,7 @@ 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.newFund(NAME(), BAD_GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE());
fund_manager_contract.newFund(NAME(), BAD_GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE(), REASON());
}

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

let current_id = fund_manager_contract.getCurrentId();
fund_manager_contract.newFund(NAME(), GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE());
fund_manager_contract.newFund(NAME(), GOAL(), EVIDENCE_LINK(), CONTACT_HANDLE(), REASON());

let expected_fund_class_hash = fund_manager_contract.getFund(1);

Expand Down
1 change: 0 additions & 1 deletion frontend/gostarkme-web/app/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const Dashboard = () => {
const fundContract = new Contract(fundAbi, fundaddr, wallet?.account);
// GET FUND NAME
let name = await fundContract.getName();
name = hex2ascii(name.toString(16));
// GET FUND DESCRIPTION
let desc = await fundContract.getReason();
// GET FUND ID
Expand Down
4 changes: 2 additions & 2 deletions frontend/gostarkme-web/components/modules/Fund/Fund.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ const Fund = () => {

// GET FUND NAME
let name = await fundContract.getName();
name = hex2ascii(name.toString(16));
// GET FUND DESCRIPTION

let desc = await fundContract.getReason();
if (desc == " ") {
desc = "No description provided";
}
let state = await fundContract.getState();

let currentBalance = await fundContract.getCurrentGoalState();
let currentBalance = await fundContract.get_current_goal_state();

let goal = await fundContract.getGoal();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ import React from 'react';
interface FundingStepProps {
fundingName: string;
setFundingName: (name: string) => void;
name: string;
setName: (name: string) => void;
errors: { fundingName: string; name: string }; // Expecting errors as props
setErrors: React.Dispatch<React.SetStateAction<{ fundingName: string; name: string }>>; // Specify the type for setErrors
goal: string;
setGoal: (name: string) => void;
evidenceLink: string;
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
}

const FundingStep: React.FC<FundingStepProps> = ({
fundingName,
setFundingName,
name,
setName,
goal,
setGoal,
evidenceLink,
setEvidenceLink,
contactHandle,
setContactHandle,
errors,
setErrors,
}) => {
Expand All @@ -22,10 +30,10 @@ const FundingStep: React.FC<FundingStepProps> = ({

// Check if the input is empty or a valid non-negative number
if (newValue === '' || (Number(newValue) >= 0 && !isNaN(Number(newValue)))) {
setName(newValue);
setErrors((prev) => ({ ...prev, name: '' }));
setGoal(newValue);
setErrors((prev) => ({ ...prev, goal : '' }));
} else {
setErrors((prev) => ({ ...prev, name: 'The goal must be a non-negative number.' }));
setErrors((prev) => ({ ...prev, goal: 'The goal must be a non-negative number.' }));
}
};

Expand All @@ -45,6 +53,26 @@ const FundingStep: React.FC<FundingStepProps> = ({
}
};

const handleEvidenceLink = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
setEvidenceLink(newValue);
if (!newValue) {
setErrors((prev) => ({ ...prev, evidenceLink: 'Evidence link is required.' }));
} else {
setErrors((prev) => ({ ...prev, evidenceLink: '' }));
}
};

const handleContactHandle = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
setContactHandle(newValue);
if (!newValue) {
setErrors((prev) => ({ ...prev, evidenceLink: 'Contact handle is required.' }));
} else {
setErrors((prev) => ({ ...prev, evidenceLink: '' }));
}
};

return (
<div className="text-center w-11/12 md:w-3/3 lg:w-1/1">
<input
Expand All @@ -58,19 +86,41 @@ const FundingStep: React.FC<FundingStepProps> = ({
<input
type="number"
placeholder="Set your goal in STRKs"
value={name}
value={goal}
onChange={handleGoal}
className={`mt-4 p-2 pl-4 border rounded w-full placeholder:text-base ${errors.name ? 'border-red-500' : 'border-black'}`}
className={`mt-4 p-2 pl-4 border rounded w-full placeholder:text-base ${errors.goal ? 'border-red-500' : 'border-black'}`}
required
min={0}
/>
<input
type="text"
placeholder="Set a link to the repo or evidence"
value={evidenceLink}
onChange={handleEvidenceLink}
className={`mt-4 p-2 pl-4 border rounded w-full placeholder:text-base ${errors.evidenceLink ? 'border-red-500' : 'border-black'}`}
required
/>
<input
type="text"
placeholder="Set a contact handle"
value={contactHandle}
onChange={handleContactHandle}
className={`mt-4 p-2 pl-4 border rounded w-full placeholder:text-base ${errors.contactHandle ? 'border-red-500' : 'border-black'}`}
required
/>

{/* Error Messages */}
{errors.fundingName && (
<p className="mt-5 text-red-500 text-center mb-4">{errors.fundingName}</p>
)}
{errors.name && (
<p className="mt-5 text-red-500 text-center mb-4">{errors.name}</p>
{errors.goal && (
<p className="mt-5 text-red-500 text-center mb-4">{errors.goal}</p>
)}
{errors.evidenceLink && (
<p className="mt-5 text-red-500 text-center mb-4">{errors.evidenceLink}</p>
)}
{errors.contactHandle && (
<p className="mt-5 text-red-500 text-center mb-4">{errors.contactHandle}</p>
)}
</div>
);
Expand Down
52 changes: 41 additions & 11 deletions frontend/gostarkme-web/components/modules/newfunding/Stages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,26 @@ import { Button } from "@/components/ui/Button";
import { useState } from "react";
import FundingStep from "./FundingStep";
import DescriptionStep from "./DescriptionStep";
import { Contract, wallet, InvokeFunctionResponse, shortString } from "starknet";
import { fundManager } from "@/contracts/abis/fundManager";
import { FUND_MANAGER_ADDR } from "@/constants";
import { useAtomValue } from "jotai";
import { walletStarknetkitLatestAtom } from "@/state/connectedWallet";


const Stages = () => {
const [currentStep, setCurrentStep] = useState(0);
const [fundingName, setFundingName] = useState("");
const [name, setName] = useState("");
const [goal, setGoal] = useState("");
const [fundingDescription, setFundingDescription] = useState("");
const [errors, setErrors] = useState({ fundingName: "", name: "" });
const [errors, setErrors] = useState({ fundingName: "", goal: "",evidenceLink: "",contactHandle: "" });
const [evidenceLink, setEvidenceLink] = useState("");
const [contactHandle, setContactHandle] = useState("");
const wallet = useAtomValue(walletStarknetkitLatestAtom);

const handleNextStep = () => {
// Reset errors
setErrors({ fundingName: "", name: "" });
setErrors({ fundingName: "", goal: "", evidenceLink: "", contactHandle: ""});

// Validate fields
let hasErrors = false;
Expand All @@ -21,8 +30,16 @@ const Stages = () => {
setErrors((prev) => ({ ...prev, fundingName: "Funding name is required." }));
hasErrors = true;
}
if (!name) {
setErrors((prev) => ({ ...prev, name: "The goal is required." }));
if (!goal) {
setErrors((prev) => ({ ...prev, goal: "The goal is required." }));
hasErrors = true;
}
if (!evidenceLink) {
setErrors((prev) => ({ ...prev, evidenceLink: "The evidence link is required." }));
hasErrors = true;
}
if (!contactHandle) {
setErrors((prev) => ({ ...prev, contactHandle: "The contact handle is required." }));
hasErrors = true;
}
}
Expand All @@ -38,22 +55,35 @@ const Stages = () => {
alert("Please enter a description.");
return;
}
console.log("Funding Name:", fundingName);
console.log("Name:", name);
console.log("Description:", fundingDescription);
newFund();
};

function newFund() {
const fundNameSplited = shortString.splitLongString(fundingName);
const fundManagerContract = new Contract(fundManager, FUND_MANAGER_ADDR, wallet?.account);
const myCall = fundManagerContract.newFund(fundingName,goal,evidenceLink,contactHandle,fundingDescription);
wallet?.account?.execute(myCall)
.then(async (resp: InvokeFunctionResponse) => {
console.log("increaseBalance txH =", resp.transaction_hash);
})
.catch((e: any) => { console.log("error increase balance =", e) });
}

return (
<div className="flex flex-col items-center justify-center space-y-6">
{/* Step Content */}
{currentStep === 0 ? (
<FundingStep
fundingName={fundingName}
setFundingName={setFundingName}
name={name}
setName={setName}
goal={goal}
setGoal={setGoal}
evidenceLink={evidenceLink}
setEvidenceLink={setEvidenceLink}
contactHandle={contactHandle}
setContactHandle={setContactHandle}
errors={errors} // Pass errors down
setErrors={setErrors} // Pass setErrors down
setErrors={setErrors} // Pass setErrors down,
/>
) : (
<DescriptionStep
Expand Down
2 changes: 1 addition & 1 deletion frontend/gostarkme-web/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const ARGENT_WEBWALLET_URL =
process.env.NEXT_PUBLIC_ARGENT_WEBWALLET_URL || "https://web.argent.xyz"

export const FUND_MANAGER_ADDR =
"0x0263457e0646dc4312c4a583fcae334d98f9b4ff1cf7a9c091649c2bec02543a"
"0x029875ea72f9b0ad21be7fe8defcfc5f2355a748015aefdd8b0477857a236d96"

export const navItems = [
{ label: 'My Profile', href: '/app/myprofile' },
Expand Down
Loading
Loading