Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasgrusz committed Jun 1, 2024
2 parents 3055f3c + 84acbee commit 217074b
Show file tree
Hide file tree
Showing 80 changed files with 3,082 additions and 104 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ node_modules

# cli
dist

# subgraph
subgraph/build/*
subgraph/generated/*
subgraph/graph-node/data/*
25 changes: 2 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# 🧠 Think2Earn ♦

<h4 align="center">
<a href="https://docs.scaffoldeth.io">Documentation</a> |
<a href="https://scaffoldeth.io">Website</a>
</h4>

![DALLE2024-06-0114 30 55-CreateaseriesofminimalisticlogosforacryptoprojectfeaturinganimageofabrainandincorporatingcryptoconceptsliketheEthereumETHlog-ezgif com-webp-to-jpg-converter](https://github.com/ETHPrague-BRX/think2earn/assets/83903147/d74bf393-d6a0-46de-a283-d91018edd5c8)


🧪 Brain Crypto Interfaces suggests the use of incentives for uploading brain data to improve open source classification models. Commmunication privacy and security between users can be leveraged with Waku communication protocols.
Expand Down Expand Up @@ -92,22 +90,3 @@ yarn start
```

Visit your app on: `http://localhost:3000`. You can interact with your smart contract using the `Debug Contracts` page. You can tweak the app config in `packages/nextjs/scaffold.config.ts`.

**What's next**:

- Edit your smart contract `YourContract.sol` in `packages/hardhat/contracts`
- Edit your frontend homepage at `packages/nextjs/app/page.tsx`. For guidance on [routing](https://nextjs.org/docs/app/building-your-application/routing/defining-routes) and configuring [pages/layouts](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts) checkout the Next.js documentation.
- Edit your deployment scripts in `packages/hardhat/deploy`
- Edit your smart contract test in: `packages/hardhat/test`. To run test use `yarn hardhat:test`

## Documentation

Visit our [docs](https://docs.scaffoldeth.io) to learn how to start building with Scaffold-ETH 2.

To know more about its features, check out our [website](https://scaffoldeth.io).

## Contributing to Scaffold-ETH 2

We welcome contributions to Scaffold-ETH 2!

Please see [CONTRIBUTING.MD](https://github.com/scaffold-eth/scaffold-eth-2/blob/main/CONTRIBUTING.md) for more information and guidelines for contributing to Scaffold-ETH 2.
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"workspaces": {
"packages": [
"packages/hardhat",
"packages/nextjs"
"packages/nextjs",
"packages/subgraph"
]
},
"scripts": {
Expand Down Expand Up @@ -33,7 +34,15 @@
"postinstall": "husky install",
"precommit": "lint-staged",
"vercel": "yarn workspace @se-2/nextjs vercel",
"vercel:yolo": "yarn workspace @se-2/nextjs vercel:yolo"
"vercel:yolo": "yarn workspace @se-2/nextjs vercel:yolo",
"subgraph:test": "yarn workspace @se-2/subgraph test",
"stop-node": "yarn workspace @se-2/subgraph stop-node",
"clean-node": "yarn workspace @se-2/subgraph clean-node",
"run-node": "yarn workspace @se-2/subgraph run-node",
"local-create": "yarn workspace @se-2/subgraph local-create",
"local-ship": "yarn workspace @se-2/subgraph local-ship",
"abi-copy": "yarn workspace @se-2/subgraph abi-copy",
"codegen": "yarn workspace @se-2/subgraph codegen"
},
"packageManager": "[email protected]",
"devDependencies": {
Expand Down
102 changes: 24 additions & 78 deletions packages/hardhat/contracts/Think2Earn.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@ interface Think2EarnBountyRegistry {

interface Think2EarnBountyFactoryV1 {
// seller methods
// struct Submission {}
function submitEEGData(uint256 _bountyId, bytes32 _eegDataHash) external returns (uint256 submissionId);
// function deleteEEGData(uint256 bountyId, uint256 _submissionId, bytes32 _eegDataHash) external;

// buyer methods
// struct Bounty{}
function createBounty(
string memory _name,
string memory _description,
Expand All @@ -25,10 +22,7 @@ interface Think2EarnBountyFactoryV1 {
uint256 _judgeTime,
uint256 _maxProgress
) external payable;
// function approveSubmissionAndPay(uint256 bountyId, uint256 submissionId) external; // require(msgSender == creator)
// function rejectSubmission(uint256 bountyId, uint256 submissionId) external; // require(msgSender == creator)
function completeBounty(uint256 _bountyId, uint256[] calldata acceptedSubmissions) external; // require(msgSender == creator)
// function sendMedia(uint256 _submissionId, bytes32 _mediaURIHash) external; // this was for the buyer to upload cat pics??
function completeBounty(uint256 _bountyId, uint256[] calldata acceptedSubmissions) external;

// view
function getBountyCount() external view returns (uint256);
Expand All @@ -43,16 +37,15 @@ interface Think2EarnBountyFactoryV1 {
address creator,
uint256 creationBlock,
bool isActive,
uint256 submissionsLength
uint256 submissionsLength,
uint256 currentProgress
);
function getBountySubmissions(uint256 _bountyId, uint256 _submission) external view returns (Submission memory);
function getActiveBounties() external view returns (uint[] memory);
function getVersion() external view returns (uint256);
struct Submission {
address submitter;
bytes32 eegDataHash; // Hash of the EEG data
// bool isPaid;
// bool eegDataSubmitted; // Indicates if EEG data has been submitted
}
}

Expand All @@ -67,75 +60,39 @@ contract Think2Earn is Think2EarnBountyFactoryV1, ReentrancyGuard {
uint256 judgeTime; // in blocks
uint256 maxProgress; // max number of participants
uint256 creationBlock;
address creator; // msg sender?
address creator;
bool isActive;

Submission[] submissions; // Array of submissions for this bounty
}

uint256[] public activeBountyIds;
mapping(uint256 => Bounty) public bounties;
uint256 public bountyCount = 1; // Start counting bounties from 1
uint256 public bountyCount = 0; // Start counting bounties from 0

// event MediaSent(uint256 indexed submissionId, bytes32 mediaURIHash, address indexed recipient);
event EEGDataSubmitted(uint256 indexed bountyId, uint256 indexed submissionId, bytes32 eegDataHash);
event EtherDeposited(address indexed sender, uint256 amount);
event PaymentMade(uint256 indexed bountyId, uint256 indexed submissionId, uint256 amount);
event BountyCreated(uint256 indexed bountyId, string name, string description, uint256 reward, uint256 duration, uint256 judgeTime, uint256 maxProgress, address indexed creator);
event BountyCompleted(uint256 indexed bountyId, uint256 numAcceptedSubmissions);

// constructor(address initialOwner) {
// transferOwnership(initialOwner);
// }

receive() external payable {
emit EtherDeposited(msg.sender, msg.value);
}

function submitEEGData(uint256 _bountyId, bytes32 _eegDataHash) external returns (uint256 submissionId) {
require(_eegDataHash != 0, "Invalid EEG data hash");

bounties[_bountyId].submissions.push (Submission({
bounties[_bountyId].submissions.push(Submission({
submitter: msg.sender,
eegDataHash: _eegDataHash
}));
uint256 submissionId = bounties[_bountyId].submissions.length;
submissionId = bounties[_bountyId].submissions.length;

emit EEGDataSubmitted(_bountyId, submissionId, _eegDataHash);

return submissionId;
}

// function approveAndPay(uint256 _submissionId, address _submitterAddress) external onlyOwner nonReentrant {
// Submission storage submission = submissions[_submissionId];
// require(submission.submitter == _submitterAddress, "Submission ID and address do not match");
// require(submission.submitter != address(0), "Submission not found");
// require(!submission.isPaid, "Already paid");
// require(submission.eegDataSubmitted, "EEG data not submitted");

// submission.isPaid = true;
// (bool sent, ) = submission.submitter.call{value: submission.tokenReward}("");
// require(sent, "Failed to send Ether");

// emit PaymentMade(_submissionId, submission.tokenReward);
// }

// function setReward(uint256 _submissionId, uint256 _reward) external onlyOwner {
// Submission storage submission = submissions[_submissionId];
// require(!submission.isPaid, "Already paid");
// submission.tokenReward = _reward;
// }

// function withdrawEther(address payable _to, uint256 _amount) external onlyOwner nonReentrant {
// require(_amount <= address(this).balance, "Insufficient balance");
// (bool sent, ) = _to.call{value: _amount}(""); Submission[] memory submissions;
// require(sent, "Failed to send Ether");
// }

// function getBalance() public view returns (uint256) {
// return address(this).balance;
// }

function createBounty(
string calldata _name,
string calldata _description,
Expand All @@ -146,7 +103,6 @@ contract Think2Earn is Think2EarnBountyFactoryV1, ReentrancyGuard {
) external payable {
require(bytes(_name).length > 0, "Bounty name cannot be empty");
require(bytes(_description).length > 0, "Bounty description cannot be empty");
// require(_reward > 0, "Bounty reward must be greater than zero"); // TODO - maybe not? some fun/charity bounties?
require(_duration > 0, "Bounty duration must be greater than zero");

Bounty storage newBounty = bounties[bountyCount];
Expand All @@ -161,34 +117,17 @@ contract Think2Earn is Think2EarnBountyFactoryV1, ReentrancyGuard {
newBounty.creator = msg.sender;
newBounty.isActive = true;

// bounties[bountyCount] = Bounty({
// name: _name,
// description: _description,
// mediaURIHash: _mediaURIHash, // Hash of the media URI
// reward: msg.value,
// duration: _duration,
// judgeTime: _judgeTime,
// maxProgress: _maxProgress,
// creationBlock: block.number,
// creator: msg.sender,
// isActive: true
// // submissions: submissions
// });

emit BountyCreated(bountyCount, _name, _description, msg.value, _duration, _judgeTime, _maxProgress, msg.sender);

activeBountyIds.push(bountyCount);
bountyCount++;
}

// function rejectSubmission(uint256 bountyId, uint256 dasubmissionId) external; // require(msgSender == creator)
// TODO - security consideration, this could run out of gas for some very large submission numbers
function completeBounty(uint256 _bountyId, uint256[] calldata acceptedSubmissions) external nonReentrant { // require(msgSender == creator)
function completeBounty(uint256 _bountyId, uint256[] calldata acceptedSubmissions) external nonReentrant {
Bounty storage bounty = bounties[_bountyId];
require(bounty.isActive, "Bounty is not active");
require(msg.sender == bounty.creator);
require(block.number >= bounty.creationBlock + bounty.duration, "Bounty duration not yet passed");
// require(bounty.reward <= address(this).balance, "Insufficient contract balance to reward"); // TODO we can get stuck if not enough eth in the contract (e.g. due to some rounding error)

bounty.isActive = false;

Expand All @@ -200,10 +139,9 @@ contract Think2Earn is Think2EarnBountyFactoryV1, ReentrancyGuard {
address payable submitter = payable(bounty.submissions[acceptedSubmissions[i]].submitter);
(bool success, ) = submitter.call{value: rewardPerSubmission}("");
emit PaymentMade(_bountyId, acceptedSubmissions[i], rewardPerSubmission);
// require(success, "Failed to send Ether"); TODO security issue - if we can't send bounty to someone, we coulnd't close the bounty
}

// return remainging eth (or all e.g. if nothing accepted or closing early)
// return remaining eth (or all e.g. if nothing accepted or closing early)
uint256 leftoverReward = startingBalance - address(this).balance - bounty.reward;
(bool success, ) = bounty.creator.call{value: leftoverReward}("");
bounty.reward = 0;
Expand All @@ -212,7 +150,6 @@ contract Think2Earn is Think2EarnBountyFactoryV1, ReentrancyGuard {
emit BountyCompleted(_bountyId, numAcceptedSubmissions);
}

// Helper function to remove a bounty from the active list
function removeBountyFromActiveList(uint bountyId) private {
for (uint i = 0; i < activeBountyIds.length; i++) {
if (activeBountyIds[i] == bountyId) {
Expand All @@ -227,16 +164,14 @@ contract Think2Earn is Think2EarnBountyFactoryV1, ReentrancyGuard {
return bountyCount;
}

function getBountySubmissions(uint256 _bountyId, uint256 _submissionId) external view returns (Submission memory)
{
function getBountySubmissions(uint256 _bountyId, uint256 _submissionId) external view returns (Submission memory) {
return bounties[_bountyId].submissions[_submissionId];
}

function getActiveBounties() public view returns (uint[] memory) {
return activeBountyIds;
}

// TODO @tom returns lenght of the submission array, submissions
function getBountyDetails(uint256 _bountyId) external view returns (
string memory name,
string memory description,
Expand All @@ -248,7 +183,8 @@ contract Think2Earn is Think2EarnBountyFactoryV1, ReentrancyGuard {
address creator,
uint256 creationBlock,
bool isActive,
uint256 submissionsLength
uint256 submissionsLength,
uint256 currentProgress
) {
Bounty storage bounty = bounties[_bountyId];
return (
Expand All @@ -262,11 +198,21 @@ contract Think2Earn is Think2EarnBountyFactoryV1, ReentrancyGuard {
bounty.creator,
bounty.creationBlock,
bounty.isActive,
bounty.submissions.length,
bounty.submissions.length
);
}
function getVersion() external view returns (uint256)
{

function getBounties() external view returns (Bounty[] memory) {
Bounty[] memory allBounties = new Bounty[](activeBountyIds.length);
for (uint256 i = 0; i < bountyCount; i++) {
allBounties[i] = bounties[activeBountyIds[i]];
}
return allBounties;
}

function getVersion() external view returns (uint256) {
return 1;
}
}

2 changes: 1 addition & 1 deletion packages/hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.1",
"scripts": {
"account": "hardhat run scripts/listAccount.ts",
"chain": "hardhat node --network hardhat --no-deploy",
"chain": "hardhat node --network hardhat --no-deploy --hostname 0.0.0.0",
"compile": "hardhat compile",
"deploy": "hardhat deploy",
"fork": "MAINNET_FORKING_ENABLED=true hardhat node --network hardhat --no-deploy",
Expand Down
61 changes: 61 additions & 0 deletions packages/nextjs/app/subgraph/_components/GreetingsTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"use client";

import { gql, useQuery } from "@apollo/client";
import { Address } from "~~/components/scaffold-eth";

const GreetingsTable = () => {
const GREETINGS_GRAPHQL = `
{
greetings(first: 25, orderBy: createdAt, orderDirection: desc) {
id
greeting
premium
value
createdAt
sender {
address
greetingCount
}
}
}
`;

const GREETINGS_GQL = gql(GREETINGS_GRAPHQL);
const { data: greetingsData, error } = useQuery(GREETINGS_GQL, { fetchPolicy: "network-only" });

// Subgraph maybe not yet configured
if (error) {
return <></>;
}

return (
<div className="flex justify-center items-center mt-10">
<div className="overflow-x-auto shadow-2xl rounded-xl">
<table className="table bg-base-100 table-zebra">
<thead>
<tr className="rounded-xl">
<th className="bg-primary"></th>
<th className="bg-primary">Sender</th>
<th className="bg-primary">Greetings</th>
</tr>
</thead>
<tbody>
{greetingsData?.greetings?.map((greeting: any, index: number) => {
return (
<tr key={greeting.id}>
<th>{index + 1}</th>
<td>
<Address address={greeting?.sender?.address} />
</td>
<td>{greeting.greeting}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
};

export default GreetingsTable;
Loading

0 comments on commit 217074b

Please sign in to comment.