From c77311eea7b4d734ca48e3ccc7cb582fedf911d3 Mon Sep 17 00:00:00 2001 From: Gizmotronn Date: Sun, 8 Jan 2023 19:40:10 +1100 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=A5=F0=9F=8E=88=20=E2=86=9D=20Adding?= =?UTF-8?q?=20context=20taken=20out=20in=20prev=20commit,=20and=20updating?= =?UTF-8?q?=20docs=20links?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 50 ++-- .../index.ts => constants/proposals.ts} | 2 +- .../index.jsx => context/proposals.jsx} | 2 +- Server/frontend/contracts/proposal.sol | 65 +++++ ...{moralisHandler.jsx => MoralisHandler.jsx} | 0 .../api/auth/{flaskAuth.tsx => flaskAuth.js} | 0 .../{fetchProposals.js => fetchProposals.jsx} | 2 + .../frontend/pages/lens/components/Navbar.js | 16 -- .../pages/lens/components/PostContent.js | 10 - .../pages/lens/components/PostFeed.jsx | 27 -- .../pages/lens/components/WritePost.js | 130 --------- .../pages/lens/constants/contractConstants.js | 38 --- .../pages/lens/constants/lensConstants.js | 253 ------------------ .../pages/lens/context/lensContext.js | 98 ------- Server/frontend/pages/lens/index.jsx | 52 ---- .../pages/lens/posts/[publicationId].jsx | 42 --- Server/frontend/pages/lens/write-post.jsx | 5 - 17 files changed, 94 insertions(+), 698 deletions(-) rename Server/frontend/{pages/api/proposals/constants/index.ts => constants/proposals.ts} (94%) rename Server/frontend/{pages/api/proposals/context/index.jsx => context/proposals.jsx} (95%) create mode 100644 Server/frontend/contracts/proposal.sol rename Server/frontend/pages/api/{moralisHandler.jsx => MoralisHandler.jsx} (100%) rename Server/frontend/pages/api/auth/{flaskAuth.tsx => flaskAuth.js} (100%) rename Server/frontend/pages/api/proposals/{fetchProposals.js => fetchProposals.jsx} (87%) delete mode 100644 Server/frontend/pages/lens/components/Navbar.js delete mode 100644 Server/frontend/pages/lens/components/PostContent.js delete mode 100644 Server/frontend/pages/lens/components/PostFeed.jsx delete mode 100644 Server/frontend/pages/lens/components/WritePost.js delete mode 100644 Server/frontend/pages/lens/constants/contractConstants.js delete mode 100644 Server/frontend/pages/lens/constants/lensConstants.js delete mode 100644 Server/frontend/pages/lens/context/lensContext.js delete mode 100644 Server/frontend/pages/lens/index.jsx delete mode 100644 Server/frontend/pages/lens/posts/[publicationId].jsx delete mode 100644 Server/frontend/pages/lens/write-post.jsx diff --git a/README.md b/README.md index dc651026..5b5decf2 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,26 @@ # sytizen-unity -[![.github/workflows/moralis.yml](https://github.com/Signal-K/sytizen/actions/workflows/moralis.yml/badge.svg?branch=ansible)](https://github.com/Signal-K/sytizen/actions/workflows/moralis.yml)
-Citizen Science (Sci-tizen) visualisation in the Unity.com engine - - -Check out our compass [here](http://ar.skinetics.tech/stellarios/compass) for more information about this product - -# Contracts - - View contract - - - - -## Trader branch -This branch contains a connection between Supabase (our current hosting platform for this backend) and the rest our our Notebooks & API. Everything else has been stripped out of this branch. - -Run `python3 -m venv .venv` to get started. - -Note: Start integrating in API from signal-k/polygon - -### Planti branch -Stripping everything out (e.g. `Ansible`/`Generator`) and just leaving the initial dashboard/game frontend. We'll merge it back with `Trader` later \ No newline at end of file +[![.github/workflows/moralis.yml](https://github.com/Signal-K/sytizen/actions/workflows/moralis.yml/badge.svg?branch=ansible)](https://github.com/Signal-K/sytizen/actions/workflows/moralis.yml) +[![Node.js CI](https://github.com/Signal-K/sytizen/actions/workflows/node.js.yml/badge.svg)](https://github.com/Signal-K/sytizen/actions/workflows/node.js.yml) +[![Node.js CI](https://github.com/Signal-K/sytizen/actions/workflows/node.js.yml/badge.svg?branch=wb3-7--interacting-with-anomalies-from-smart)](https://github.com/Signal-K/sytizen/actions/workflows/node.js.yml) +[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/signal-k/sytizen/HEAD) +[![](https://github.com/Signal-K/sytizen/actions/workflows/node.js.yml/badge.svg?branch=wb3-7--interacting-with-anomalies-from-smart)](https://deepnote.com/workspace/star-sailors-49d2efda-376f-4329-9618-7f871ba16007/project/Supabase-Talk-ab6b31e5-13c3-4949-af38-1197d00bd4d1/notebook/Flask%20API-cb9219547b9e4e228b15cbf8a1aa9cf4#99de0381ef0d40ffaee2354354861bae) +[![](https://badges.thirdweb.com/contract?address=0xCcaA1ABA77Bae6296D386C2F130c46FEc3E5A004&theme=light&chainId=5)](https://thirdweb.com/goerli/0xCcaA1ABA77Bae6296D386C2F130c46FEc3E5A004?utm_source=contract_badge) + +# Signal-K/Sytizen Repo +## Related repositories +* [Signal-K/polygon](https://github.com/Signal-K/polygon/issues/26) ↝ Contract interactions +* [Signal-K/client](https://github.com/Signal-K/client) ↝ Frontend for interactions with our contracts + +## Documentation +All documentation is visible on [Notion](https://www.notion.so/skinetics/Sample-Planets-Contract-4c3bdcbca4b9450382f9cc4e72e081f7) + +# Citizen Science Classifications +## Process +* User mints an anomaly that has appeared in their UI (for now, the webapp, later it will be the game as well) +* API searches for a token that has already been lazy minted with the TIC id of the anomaly (or the identifier of the candidate) + * If there is a token id that has the TIC Id, then claim a copy of that to the `msg.sender` (player’s address) so they can manipulate it in-game + * If the TIC ID has never been minted before, lazy mint a new one with parameters fetched from the data source and send it to `msg.sender` + * Return the IPFS metadata +* Add some buttons that allow manipulations for the NFT (e.g. viewing (reading) metadata (e.g. image/video files, graphs). + * Graphs should be generated in a Jupyter notebook and returned in the Next app. +* User creates post (proposal [Proposal Board → Migration from Vite](https://www.notion.so/Proposal-Board-Migration-from-Vite-2e3ef95e384d4ac1875e0dbbe9a59337)) with the NFT ID for their anomaly and some extra metadata for their discoveries and proposal, and then users can vote \ No newline at end of file diff --git a/Server/frontend/pages/api/proposals/constants/index.ts b/Server/frontend/constants/proposals.ts similarity index 94% rename from Server/frontend/pages/api/proposals/constants/index.ts rename to Server/frontend/constants/proposals.ts index 112c2e12..2055c405 100644 --- a/Server/frontend/pages/api/proposals/constants/index.ts +++ b/Server/frontend/constants/proposals.ts @@ -1,6 +1,6 @@ import { createCampaign, dashboard, logout, payment, profile, withdraw } from '../../../../assets'; -export const navlinks = [ +export const navlinksProposals = [ { name: 'dashboard', imgUrl: dashboard, diff --git a/Server/frontend/pages/api/proposals/context/index.jsx b/Server/frontend/context/proposals.jsx similarity index 95% rename from Server/frontend/pages/api/proposals/context/index.jsx rename to Server/frontend/context/proposals.jsx index 71cc1c7e..7d60aaeb 100644 --- a/Server/frontend/pages/api/proposals/context/index.jsx +++ b/Server/frontend/context/proposals.jsx @@ -5,7 +5,7 @@ import { ethers } from 'ethers'; const StateContext = createContext(); export const StateContextProvider = ({ children }) => { - const { contract } = useContract('0xCcaA1ABA77Bae6296D386C2F130c46FEc3E5A004'); + const { contract } = useContract('0xed6e837Fda815FBf78E8E7266482c5Be80bC4bF9'); // Goerli contract -> will update to Polygon mainnet when in production const { mutateAsync: createProposal } = useContractWrite(contract, 'createProposal'); // Call function & create a proposal, passing in params from the form const address = useAddress(); const connect = useMetamask(); diff --git a/Server/frontend/contracts/proposal.sol b/Server/frontend/contracts/proposal.sol new file mode 100644 index 00000000..7fdafc6c --- /dev/null +++ b/Server/frontend/contracts/proposal.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.9; + +contract ClassificationProposal { + struct Classification { + // What types will this struct/campaign have? + address owner; + string title; // Title of the Proposal, type string + string description; + uint256 target; // How many coins to get the proposal to pass? + uint256 deadline; + uint256 amountCollected; // Goes towards target + string image; // image uri/url + address[] voters; + uint256[] votes; // Consider adding more components to match discussion in wb3-5 task + } + + mapping(uint256 => Classification) public classifications; + uint256 public numberOfClassifications = 0; + + function createProposal(address _owner, string memory _title, string memory _description, uint256 _target, uint256 _deadline, string memory _image) public returns (uint256) { // Returns id of the classification's proposal + Classification storage classification = classifications[numberOfClassifications]; // Populates the classifications array + require(classification.deadline < block.timestamp, "The deadline should be a date in the future"); // Maybe add another modifier to specify a minimum deadline period e.g. 1 day + + classification.owner = _owner; + classification.title = _title; + classification.description = _description; + classification.target = _target; + classification.deadline = _deadline; + classification.amountCollected = 0; + classification.image = _image; + + numberOfClassifications++; + + return numberOfClassifications - 1; + } + + function voteForProposal(uint256 _id) public payable { // Some crypto will be sent with the classificationID used as a param + uint256 amount = msg.value; // This amount is set by user (typically in frontend); the amount they'll be pledging towards a classification + Classification storage classification = classifications[_id]; + + classification.voters.push(msg.sender); // Push the address of user who voted + classification.votes.push(amount); // Amount of custom erc20 token pledged + + (bool sent,) = payable(classification.owner).call{value: amount}(""); + if (sent) { + classification.amountCollected = classification.amountCollected + amount; + } + } + + function getVoters(uint256 _id) view public returns(address[] memory, uint256[] memory) { // Array of votes and number of voters + return (classifications[_id].voters, classifications[_id].votes); + } + + function getProposals() public view returns(Classification[] memory) { // Retrieved from memory + Classification[] memory allClassifications = new Classification[](numberOfClassifications); // Empty array of empty structs referencing each classification/proposal + + for (uint i = 0; i < numberOfClassifications; i++) { + Classification storage item = classifications[i]; + allClassifications[i] = item; // Fetch the classification from storage and populate it in allClassifications + } + + return allClassifications; + } +} \ No newline at end of file diff --git a/Server/frontend/pages/api/moralisHandler.jsx b/Server/frontend/pages/api/MoralisHandler.jsx similarity index 100% rename from Server/frontend/pages/api/moralisHandler.jsx rename to Server/frontend/pages/api/MoralisHandler.jsx diff --git a/Server/frontend/pages/api/auth/flaskAuth.tsx b/Server/frontend/pages/api/auth/flaskAuth.js similarity index 100% rename from Server/frontend/pages/api/auth/flaskAuth.tsx rename to Server/frontend/pages/api/auth/flaskAuth.js diff --git a/Server/frontend/pages/api/proposals/fetchProposals.js b/Server/frontend/pages/api/proposals/fetchProposals.jsx similarity index 87% rename from Server/frontend/pages/api/proposals/fetchProposals.js rename to Server/frontend/pages/api/proposals/fetchProposals.jsx index e38a5c39..e6857d94 100644 --- a/Server/frontend/pages/api/proposals/fetchProposals.js +++ b/Server/frontend/pages/api/proposals/fetchProposals.jsx @@ -1,3 +1,5 @@ +import { StateContextProvider } from "../../../context/proposals"; +import { NavLinkProposals } from '../../../constants/proposals'; /*import { useContract, useContractRead } from "@thirdweb-dev/react"; export default function fetchProposalFromContract () { diff --git a/Server/frontend/pages/lens/components/Navbar.js b/Server/frontend/pages/lens/components/Navbar.js deleted file mode 100644 index d38dd467..00000000 --- a/Server/frontend/pages/lens/components/Navbar.js +++ /dev/null @@ -1,16 +0,0 @@ -import { ConnectButton } from "web3uikit"; -import Link from "next/link"; - -export default function Navbar() { - return ( - - ) -}; \ No newline at end of file diff --git a/Server/frontend/pages/lens/components/PostContent.js b/Server/frontend/pages/lens/components/PostContent.js deleted file mode 100644 index 874517a9..00000000 --- a/Server/frontend/pages/lens/components/PostContent.js +++ /dev/null @@ -1,10 +0,0 @@ -import ReactMarkdown from "react-markdown"; - -export default function PostContent({ post }) { - return ( -
-

{post.metadata.name}

- {post.metadata.content} -
- ) -} \ No newline at end of file diff --git a/Server/frontend/pages/lens/components/PostFeed.jsx b/Server/frontend/pages/lens/components/PostFeed.jsx deleted file mode 100644 index 5763bdac..00000000 --- a/Server/frontend/pages/lens/components/PostFeed.jsx +++ /dev/null @@ -1,27 +0,0 @@ -import Link from "next/link"; - -export default function PostFeed({ posts }) { - return ( -
- {posts - ? posts.map((post) => ) - : null} -
- ); -} - -function PostItem({ post }) { - let imageURL; - if (post.metadata.image) { // IPFS gateway (URI/url) - imageURL = post.metadata.image.replace("ipfs://", 'https://ipfs.io/ipfs'); // Replace ipfs link with a regular http ref.uri - } - - return ( -
- - -

{post.metadata.name}

- -
- ) -} \ No newline at end of file diff --git a/Server/frontend/pages/lens/components/WritePost.js b/Server/frontend/pages/lens/components/WritePost.js deleted file mode 100644 index d3d7a7e6..00000000 --- a/Server/frontend/pages/lens/components/WritePost.js +++ /dev/null @@ -1,130 +0,0 @@ -import { useForm } from "react-hook-form"; -import { useLensContext } from '../context/lensContext'; -import { - createContentMetadata, - getCreatePostQuery, // Compare to https://github.com/PatrickAlphaC/lens-blog - lensClient, - } from "../constants/lensConstants"; -import { useWeb3Contract } from "react-moralis"; -import lensAbi from '../contracts/lensABI.json'; -import { - lensHub, - networkConfig, - TRUE_BYTES, - } from "../constants/contractConstants"; - -const PINATA_PIN_ENDPOINT = 'https://api.pinata.cloud/pinning/pinJSONToIPFS'; - -async function pinMetadataToPinata ( - metadata, - contentName, - pinataApiKey, - pinataApiSecret -) { - console.log('pinning metadata to pinata'); - const data = JSON.stringify({ - pinataMetadata: { name: contentName }, - pinataContent: metadata, - }); - const config = { - method: "POST", - headers: { - "Content-Type": 'application/json', - pinata_api_key: pinataApiKey, - pinata_secret_api_key: pinataApiSecret, - }, - body: data, - }; - const response = await fetch(PINATA_PIN_ENDPOINT, config); - const ipfsHash = (await response.json()).ipfsHash; - console.log(`Stored content metadata with ${ipfsHash}`); - return ipfsHash; -} - -function PostForm () { - const { profileId, token } = useLensContext(); - const { register, errors, handleSubmit, formState, reset, watch } = useForm({ - mode: 'onChange', - }); - const { runContractFunction } = useWeb3Contract(); - - const publishPost = async function ({ content, contentName, imageUri, imageType, pinataApiKey, pinataApiSecret }) { - let fullContentUri; - const contentMetadata = createContentMetadata(content, contentName, imageUri, imageType); - const metadataIpfsHash = await pinMetadataToPinata(contentMetadata, contentName, pinataApiKey, pinataApiSecret); - fullContentUri = `ipfs://${metadataIpfsHash}`; - console.log(fullContentUri); - - // Post IPFS hash to Lens/blockchain - const transactionParameters = [ - profileId, - fullContentUri, - '0x23b9467334bEb345aAa6fd1545538F3d54436e96', // Free collect module contract address on Polygon (for now, all posts will be able to be collected without a fee). - TRUE_BYTES, - '0x17317F96f0C7a845FFe78c60B10aB15789b57Aaa', // Follower only reference module - ]; - console.log(transactionParameters); - const transactionOptions = { - abi: lensAbi, - contractAddress: '0xDb46d1Dc155634FbC732f92E853b10B288AD5a1d', // Lens Hub proxy contract address - functionName: 'post', - params: { - vars: transactionParameters, - }, - }; - - await runContractFunction({ - params: transactionOptions, - onError: (error) => console.log(error), - }); - - return ( - "Hi" - ) - }; - - return ( -
- -