From 554655209553f60c47380c306416446ef169b16e Mon Sep 17 00:00:00 2001 From: Jacob Homanics Date: Thu, 18 Apr 2024 02:25:37 -0500 Subject: [PATCH] built out hat demo --- hat-jsons/stewardship-hat.json | 5 + hat-jsons/warden-hat.json | 5 + .../contracts/ERC1155EligibiltiyModule.sol | 12 +- packages/foundry/script/DeployDemo.s.sol | 32 +++- packages/nextjs/app/hats/_components/Hats.tsx | 174 ++++++++++++++---- .../nextjs/contracts/deployedContracts.ts | 12 +- 6 files changed, 190 insertions(+), 50 deletions(-) create mode 100644 hat-jsons/stewardship-hat.json create mode 100644 hat-jsons/warden-hat.json diff --git a/hat-jsons/stewardship-hat.json b/hat-jsons/stewardship-hat.json new file mode 100644 index 0000000..4dc1e59 --- /dev/null +++ b/hat-jsons/stewardship-hat.json @@ -0,0 +1,5 @@ +{ + "name": "The Stewardship Cap", + "description": "Steward is a volunteer position, created with the intent to separate control of the treasury (through being a signer on the Safe) from those receiving direct payouts without community oversight (Wardens). Stewards can still receive Giving Circle payouts and have a paid position on a project, because these rewards have community oversight.", + "image": "ipfs://bafkreib7b5ofejprn4xv4grp7itypej7ybxus7idkymhqkyweqlgxkigcm" +} diff --git a/hat-jsons/warden-hat.json b/hat-jsons/warden-hat.json new file mode 100644 index 0000000..ae8a169 --- /dev/null +++ b/hat-jsons/warden-hat.json @@ -0,0 +1,5 @@ +{ + "name": "The Warden Hat", + "description": "Having this role indicates that the wearer has made substantial contributions to the DAO, to the point that they should get paid a stipend for their efforts.", + "image": "ipfs://bafkreie3wgy2himeujzxzfjankxd2xwac3ep5dneozyfkpjxszkqyla3q4" +} diff --git a/packages/foundry/contracts/ERC1155EligibiltiyModule.sol b/packages/foundry/contracts/ERC1155EligibiltiyModule.sol index 826b5cd..f9ddc20 100644 --- a/packages/foundry/contracts/ERC1155EligibiltiyModule.sol +++ b/packages/foundry/contracts/ERC1155EligibiltiyModule.sol @@ -6,15 +6,15 @@ import {ERC1155} from "./Hats/utils/ERC1155.sol"; contract ERC1155EligibiltiyModule { ERC1155 s_erc1155; - constructor(address erc1155Address) { + uint256 s_amount; + + constructor(address erc1155Address, uint256 amount) { s_erc1155 = ERC1155(erc1155Address); + s_amount = amount; } - function getWearerStatus( - address _wearer, - uint256 - ) external view returns (bool eligible, bool standing) { - if (s_erc1155.balanceOf(_wearer, 0) > 100) { + function getWearerStatus(address _wearer, uint256) external view returns (bool eligible, bool standing) { + if (s_erc1155.balanceOf(_wearer, 0) > s_amount) { eligible = true; } else { eligible = false; diff --git a/packages/foundry/script/DeployDemo.s.sol b/packages/foundry/script/DeployDemo.s.sol index ae46146..733656d 100644 --- a/packages/foundry/script/DeployDemo.s.sol +++ b/packages/foundry/script/DeployDemo.s.sol @@ -67,19 +67,43 @@ contract DeployDemoScript is ScaffoldETHDeploy { hatsInstance.mintHat(hatterHatId, address(hatter)); ActiveModule activeModule = new ActiveModule(); - ERC1155EligibiltiyModule eligibilityModule = new ERC1155EligibiltiyModule(address(instance)); + ERC1155EligibiltiyModule eligibilityModule = new ERC1155EligibiltiyModule(address(instance), 100); + ERC1155EligibiltiyModule eligibilityModule2 = new ERC1155EligibiltiyModule(address(instance), 500); + ERC1155EligibiltiyModule eligibilityModule3 = new ERC1155EligibiltiyModule(address(instance), 1500); - uint256 claimableHatId = hatsInstance.createHat( + uint256 claimableHatId1 = hatsInstance.createHat( hatterHatId, "Hat of Engineering", - 100, + 30, address(eligibilityModule), address(activeModule), true, "ipfs://bafkreicff2j67tg5g3klktkk4wavcctorj65y5upkolznwgbhmrakv4dba" ); - console.log(claimableHatId); + uint256 claimableHatId2 = hatsInstance.createHat( + hatterHatId, + "Hat of Steardship", + 30, + address(eligibilityModule2), + address(activeModule), + true, + "ipfs://bafkreibfian6fybuifdvchrjspqpedvrkakhwdnyhpwrroustpa7mjtto4" + ); + + uint256 claimableHatId3 = hatsInstance.createHat( + hatterHatId, + "Hat of Warden", + 30, + address(eligibilityModule3), + address(activeModule), + true, + "ipfs://bafkreigvzey77niarqslm6wjd3e77ihwc5rcdrrahp3o6og2dszzzw2fpi" + ); + + console.log(claimableHatId1); + console.log(claimableHatId2); + console.log(claimableHatId3); } vm.stopBroadcast(); diff --git a/packages/nextjs/app/hats/_components/Hats.tsx b/packages/nextjs/app/hats/_components/Hats.tsx index bb855f6..e0a6ff0 100644 --- a/packages/nextjs/app/hats/_components/Hats.tsx +++ b/packages/nextjs/app/hats/_components/Hats.tsx @@ -2,28 +2,33 @@ import { useFetch } from "usehooks-ts"; import { useAccount, useChainId } from "wagmi"; +import { useRepTokens } from "~~/components/rep-tokens/hooks/Hooks"; import { useScaffoldContractRead, useScaffoldContractWrite } from "~~/hooks/scaffold-eth"; // const claimableHatId = "26960358049567071831564234593151059434471056522609336320533481914368"; function getHatConfig(chainId: number) { - let claimableHatId = ""; + let claimableHatId1 = ""; + let claimableHatId2 = ""; + let claimableHatId3 = ""; if (chainId === 31337) { - claimableHatId = "26960358049567071831564234593151059434471056522609336320533481914368"; + claimableHatId1 = "26960358049567071831564234593151059434471056522609336320533481914368"; + claimableHatId2 = "26960358055844173566950915356986848857678722938711691764997516427264"; + claimableHatId3 = "26960358062121275302337596120822638280886389354814047209461550940160"; } else if (chainId === 11155111) { - claimableHatId = ""; + claimableHatId1 = ""; // claimHatterName = "MultiClaimsHatter"; } - return { claimableHatId }; + return { claimableHatId1, claimableHatId2, claimableHatId3 }; } export function Hats() { const { address } = useAccount(); const chainId = useChainId(); - const { claimableHatId } = getHatConfig(chainId); + const { claimableHatId1, claimableHatId2, claimableHatId3 } = getHatConfig(chainId); // const { data: isAdminOfHat } = useScaffoldContractRead({ // contractName: "Hats", @@ -31,10 +36,22 @@ export function Hats() { // args: [address, BigInt(claimableHatId)], // }); - const { data: viewHat } = useScaffoldContractRead({ + const { data: viewHat1 } = useScaffoldContractRead({ contractName: "Hats", functionName: "viewHat", - args: [BigInt(claimableHatId)], + args: [BigInt(claimableHatId1)], + }); + + const { data: viewHat2 } = useScaffoldContractRead({ + contractName: "Hats", + functionName: "viewHat", + args: [BigInt(claimableHatId2)], + }); + + const { data: viewHat3 } = useScaffoldContractRead({ + contractName: "Hats", + functionName: "viewHat", + args: [BigInt(claimableHatId3)], }); // const { data: isEligible } = useScaffoldContractRead({ @@ -49,46 +66,135 @@ export function Hats() { // args: [BigInt(claimableHatId)], // }); - const { data: balanceOfClaimableHat, refetch } = useScaffoldContractRead({ + const { data: balanceOfClaimableHat1, refetch: refetchBalance1 } = useScaffoldContractRead({ contractName: "Hats", functionName: "balanceOf", - args: [address, BigInt(claimableHatId)], + args: [address, BigInt(claimableHatId1)], }); - console.log(balanceOfClaimableHat); + const { data: balanceOfClaimableHat2, refetch: refetchBalance2 } = useScaffoldContractRead({ + contractName: "Hats", + functionName: "balanceOf", + args: [address, BigInt(claimableHatId2)], + }); - const { writeAsync: claimHat } = useScaffoldContractWrite({ + const { data: balanceOfClaimableHat3, refetch: refetchBalance3 } = useScaffoldContractRead({ + contractName: "Hats", + functionName: "balanceOf", + args: [address, BigInt(claimableHatId3)], + }); + + const { tokens: userTokens } = useRepTokens(address, "nftstorage"); + + const { writeAsync: claimHat1 } = useScaffoldContractWrite({ contractName: "MultiClaimsHatter", functionName: "claimHat", - args: [BigInt(claimableHatId)], + args: [BigInt(claimableHatId1)], }); - const result: any = useFetch(viewHat ? viewHat[5].replace("ipfs://", "https://nftstorage.link/ipfs/") : ""); + const { writeAsync: claimHat2 } = useScaffoldContractWrite({ + contractName: "MultiClaimsHatter", + functionName: "claimHat", + args: [BigInt(claimableHatId2)], + }); + + const { writeAsync: claimHat3 } = useScaffoldContractWrite({ + contractName: "MultiClaimsHatter", + functionName: "claimHat", + args: [BigInt(claimableHatId3)], + }); + + const result1: any = useFetch(viewHat1 ? viewHat1[5].replace("ipfs://", "https://nftstorage.link/ipfs/") : ""); + const result2: any = useFetch(viewHat2 ? viewHat2[5].replace("ipfs://", "https://nftstorage.link/ipfs/") : ""); + const result3: any = useFetch(viewHat3 ? viewHat3[5].replace("ipfs://", "https://nftstorage.link/ipfs/") : ""); + + const doesUserMeetRepRequirements1 = userTokens[0]?.balance >= 100; + const doesUserMeetRepRequirements2 = userTokens[0]?.balance >= 500; + const doesUserMeetRepRequirements3 = userTokens[0]?.balance >= 1500; + + const doesUserOwnHat1 = balanceOfClaimableHat1 || 0 > 0; + const doesUserOwnHat2 = balanceOfClaimableHat2 || 0 > 0; + const doesUserOwnHat3 = balanceOfClaimableHat3 || 0 > 0; + + const canClaimHat1 = doesUserMeetRepRequirements1 && !doesUserOwnHat1; + const canClaimHat2 = doesUserMeetRepRequirements2 && !doesUserOwnHat2; + const canClaimHat3 = doesUserMeetRepRequirements3 && !doesUserOwnHat3; return ( <>
-

{result?.data?.name}

- {balanceOfClaimableHat || 0 > 0 ?

Equipped

: <>} - - {/* eslint-disable-next-line @next/next/no-img-element */} - {"Hat -

{result?.data?.description}

- +
+
+

{result1?.data?.name}

+ {balanceOfClaimableHat1 || 0 > 0 ?

Equipped

: <>} + + {/* eslint-disable-next-line @next/next/no-img-element */} + {"Hat +

{result1?.data?.description}

+ +
+
+

{result2?.data?.name}

+ {balanceOfClaimableHat2 || 0 > 0 ?

Equipped

: <>} + + {/* eslint-disable-next-line @next/next/no-img-element */} + {"Hat +

{result2?.data?.description}

+ +
+ +
+

{result3?.data?.name}

+ {balanceOfClaimableHat3 || 0 > 0 ?

Equipped

: <>} + + {/* eslint-disable-next-line @next/next/no-img-element */} + {"Hat +

{result3?.data?.description}

+ +
+
); diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts index 6017dc5..7e39491 100644 --- a/packages/nextjs/contracts/deployedContracts.ts +++ b/packages/nextjs/contracts/deployedContracts.ts @@ -7,7 +7,7 @@ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract"; const deployedContracts = { 31337: { ReputationTokens: { - address: "0x5FbDB2315678afecb367f032d93F642f64180aa3", + address: "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8", abi: [ { type: "constructor", @@ -1512,7 +1512,7 @@ const deployedContracts = { }, }, ReputationFaucet: { - address: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82", + address: "0x809d550fca64d94Bd9F66E60752A544199cfAC3D", abi: [ { type: "constructor", @@ -1637,7 +1637,7 @@ const deployedContracts = { }, }, Hats: { - address: "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F", + address: "0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc", abi: [ { type: "constructor", @@ -3598,7 +3598,7 @@ const deployedContracts = { }, }, MultiClaimsHatter: { - address: "0x67d269191c92Caf3cD7723F116c85e6E9bf55933", + address: "0x162A433068F51e18b7d13932F27e66a3f99E6890", abi: [ { type: "constructor", @@ -3924,7 +3924,7 @@ const deployedContracts = { }, }, ActiveModule: { - address: "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690", + address: "0x5081a39b8A5f0E35a8D959395a630b68B74Dd30f", abi: [ { type: "function", @@ -3954,7 +3954,7 @@ const deployedContracts = { inheritedFunctions: {}, }, ERC1155EligibiltiyModule: { - address: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB", + address: "0x1fA02b2d6A771842690194Cf62D91bdd92BfE28d", abi: [ { type: "constructor",