From d39cad96194c8770a6ce8018f5be2c5e3a366411 Mon Sep 17 00:00:00 2001 From: Ladd Hoffman Date: Sat, 16 Mar 2024 21:19:57 -0500 Subject: [PATCH] move availability stakes component to separate file --- client/package-lock.json | 1 + client/package.json | 1 + client/src/App.jsx | 156 ++++-------------------------- client/src/AvailabilityStakes.jsx | 130 +++++++++++++++++++++++++ client/src/Web3Context.js | 5 + client/src/contracts.js | 12 +++ 6 files changed, 170 insertions(+), 135 deletions(-) create mode 100644 client/src/AvailabilityStakes.jsx create mode 100644 client/src/Web3Context.js create mode 100644 client/src/contracts.js diff --git a/client/package-lock.json b/client/package-lock.json index 1e403d3..99b09df 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -13,6 +13,7 @@ "axios": "^1.6.7", "bootstrap": "^5.3.3", "bootswatch": "^5.3.3", + "prop-types": "^15.8.1", "react": "^18.2.0", "react-bootstrap": "^2.10.1", "react-dom": "^18.2.0", diff --git a/client/package.json b/client/package.json index e00985d..b6d5b10 100644 --- a/client/package.json +++ b/client/package.json @@ -15,6 +15,7 @@ "axios": "^1.6.7", "bootstrap": "^5.3.3", "bootswatch": "^5.3.3", + "prop-types": "^15.8.1", "react": "^18.2.0", "react-bootstrap": "^2.10.1", "react-dom": "^18.2.0", diff --git a/client/src/App.jsx b/client/src/App.jsx index 732fb09..45f8b99 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -1,5 +1,5 @@ import { - useCallback, useEffect, useReducer, useState, createContext, useContext, useMemo, + useCallback, useEffect, useReducer, useState, useMemo, } from 'react'; import { useSDK } from '@metamask/sdk-react'; import { Web3 } from 'web3'; @@ -11,19 +11,11 @@ import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; import Stack from 'react-bootstrap/Stack'; +import Web3Context from './Web3Context'; +import contracts from './contracts'; import DAOArtifact from './assets/DAO.json'; import work1Artifact from './assets/Work1.json'; - -const contracts = { - '0x539': { // Hardhat - DAO: '0x76Dfe9F47f06112a1b78960bf37d87CfbB6D6133', - Work1: '0xd2845aE812Ee42cF024fB4C55c052365792aBd78', - }, - '0xaa36a7': { // Sepolia - DAO: '0x39B7522Ee1A5B13aE5580C40114239D4cE0e7D29', - Work1: '0xC0Bb36820Ba891DE4ed6D60f75066805361dbeB8', - }, -}; +import AvailabilityStakes from './AvailabilityStakes'; const updateList = (list, action) => { switch (action.type) { @@ -40,8 +32,6 @@ const updateList = (list, action) => { const useList = (initialValue) => useReducer(updateList, initialValue ?? []); -const Web3Context = createContext({}); - function App() { const { sdk, connected, provider, chainId, account, balance, @@ -78,8 +68,8 @@ function App() { }; const fetchReputation = async () => { - setReputation(Number(await DAOContract.methods.balanceOf(account).call())); - setTotalReputation(Number(await DAOContract.methods.totalSupply().call())); + setReputation(await DAOContract.methods.balanceOf(account).call()); + setTotalReputation(await DAOContract.methods.totalSupply().call()); }; const fetchPost = async (postIndex) => { @@ -324,11 +314,11 @@ function App() { // Since this is the result we expect from the server, we preemptively set it here. // We can let this value be negative -- this would just mean we'll be getting // at least one error from the server, and a corrected reputation. - setReputation((current) => current - stake); + setReputation((current) => current - BigInt(amount)); }, [DAO, account, setReputation]); - const stakeAllInFavor = useCallback(async (poolIndex) => { - await stake(poolIndex, reputation, true); + const stakeHalfInFavor = useCallback(async (poolIndex) => { + await stake(poolIndex, reputation / BigInt(2), true); }, [stake, reputation]); const evaluateOutcome = useCallback(async (poolIndex) => { @@ -378,6 +368,7 @@ function App() { }), [ DAO, work1, availabilityStakes, reputation, setReputation, account, chainId, ]); + return ( {!connected && } @@ -412,10 +403,10 @@ function App() {
- {`Your REP: ${reputation}`} + {`Your REP: ${reputation?.toString()}`}
- {`Total REP: ${totalReputation}`} + {`Total REP: ${totalReputation?.toString()}`}
@@ -503,8 +494,8 @@ function App() { {!pool.resolved && reputation > 0 && pool.timeRemaining > 0 && ( <> - {' '} @@ -525,15 +516,7 @@ function App() {
{`Price: ${work1Price} ETH`}
- +
@@ -602,18 +585,14 @@ function App() {
{`Price: ${work1Price} ETH`}
- + - TBD +

Work Contract 1

+
+ {`Price: ${work1Price} ETH`} +
+
@@ -622,97 +601,4 @@ function App() { ); } -function AvailabilityStakes() { - const { - DAO, work1, availabilityStakes, reputation, setReputation, account, chainId, - } = useContext(Web3Context); - const stakeAvailability = useCallback(async (duration) => { - const target = contracts[chainId].Work1; - await DAO.methods.stakeAvailability(target, reputation, duration).send({ - from: account, - gas: 999999, - }); - // Note that as with validation pool stakes, we should keep track locally of our reputation - setReputation(0); - }, [DAO, account, chainId, reputation, setReputation]); - - const reclaimAvailabilityStake = useCallback(async (stakeIndex) => { - await work1.methods.reclaimAvailability(stakeIndex).send({ - from: account, - gas: 999999, - }); - }, [work1, account]); - - const extendAvailabilityStake = useCallback(async (stakeIndex, duration) => { - await work1.methods.extendAvailability(stakeIndex, duration).send({ - from: account, - gas: 999999, - }); - }, [work1, account]); - return ( - <> -
- Stake Availability: - {' '} - {!reputation && <>No reputation available to stake} - {reputation > 0 && ( - <> - - {' '} - - - )} -
-
- Availability Stake Count: - {' '} - {availabilityStakes?.length} -
-
- - - - - - - - - - - - - - {availabilityStakes?.filter((x) => !!x).map((s) => ( - - - - - - - - - - ))} - -
IDWorkerAmountEnd TimeAssignedReclaimedActions
{s.id.toString()}{s.worker.toString()}{s.amount.toString()}{new Date(Number(s.endTime) * 1000).toLocaleString()}{s.assigned.toString()}{s.reclaimed.toString()} - {s.currentUserIsWorker() && ( - - )} - {s.currentUserIsWorker() && s.timeRemaining <= 0 - && !s.assigned && !s.reclaimed && ( - <> - {' '} - - - )} -
-
- - ); -} - export default App; diff --git a/client/src/AvailabilityStakes.jsx b/client/src/AvailabilityStakes.jsx new file mode 100644 index 0000000..e035be0 --- /dev/null +++ b/client/src/AvailabilityStakes.jsx @@ -0,0 +1,130 @@ +import { useCallback, useContext } from 'react'; +import { PropTypes } from 'prop-types'; +import Button from 'react-bootstrap/Button'; + +import Web3Context from './Web3Context'; +import contracts from './contracts'; + +const getAvailabilityStatus = (stake) => { + if (stake.reclaimed) return 'Reclaimed'; + if (stake.assigned) return 'Assigned'; + if (new Date() < new Date(Number(stake.endTime) * 1000)) return 'Available'; + return 'Expired'; +}; + +function AvailabilityStakes({ showActions, showAmount, onlyShowAvailable }) { + const { + DAO, work1, availabilityStakes, reputation, setReputation, account, chainId, + } = useContext(Web3Context); + + const stakeAvailability = useCallback(async (duration) => { + const target = contracts[chainId].Work1; + await DAO.methods.stakeAvailability(target, reputation / BigInt(2), duration).send({ + from: account, + gas: 999999, + }); + // Note that as with validation pool stakes, we should keep track locally of our reputation + setReputation(reputation / BigInt(2)); + }, [DAO, account, chainId, reputation, setReputation]); + + const reclaimAvailabilityStake = useCallback(async (stakeIndex) => { + await work1.methods.reclaimAvailability(stakeIndex).send({ + from: account, + gas: 999999, + }); + }, [work1, account]); + + const extendAvailabilityStake = useCallback(async (stakeIndex, duration) => { + await work1.methods.extendAvailability(stakeIndex, duration).send({ + from: account, + gas: 999999, + }); + }, [work1, account]); + + const displayData = availabilityStakes.filter((stake) => { + if (!onlyShowAvailable) return true; + if (getAvailabilityStatus(stake) === 'Available') return true; + return false; + }); + + return ( + <> + {showActions && ( +
+ Stake Availability: + {' '} + {!reputation && <>No reputation available to stake} + {reputation > 0 && ( + <> + + {' '} + + + )} +
+ )} +
+ Availability Stake Count: + {' '} + {displayData?.length} +
+
+ + + + + + {showAmount && } + + + {showActions && } + + + + {displayData?.filter((x) => !!x).map((s) => ( + + + + {showAmount && } + + + {showActions && ( + + )} + + ))} + +
IDWorkerAmountEnd TimeStatusActions
{s.id.toString()}{s.worker.toString()}{s.amount.toString()}{new Date(Number(s.endTime) * 1000).toLocaleString()}{getAvailabilityStatus(s)} + {s.currentUserIsWorker() && !s.assigned && !s.reclaimed && ( + + )} + {s.currentUserIsWorker() && s.timeRemaining <= 0 + && !s.assigned && !s.reclaimed && ( + <> + {' '} + + + )} +
+
+ + ); +} + +AvailabilityStakes.propTypes = { + showActions: PropTypes.bool, + showAmount: PropTypes.bool, + onlyShowAvailable: PropTypes.bool, +}; + +AvailabilityStakes.defaultProps = { + showActions: true, + showAmount: true, + onlyShowAvailable: false, +}; + +export default AvailabilityStakes; diff --git a/client/src/Web3Context.js b/client/src/Web3Context.js new file mode 100644 index 0000000..8c72f8f --- /dev/null +++ b/client/src/Web3Context.js @@ -0,0 +1,5 @@ +import { createContext } from 'react'; + +const Web3Context = createContext({}); + +export default Web3Context; diff --git a/client/src/contracts.js b/client/src/contracts.js new file mode 100644 index 0000000..a9bb053 --- /dev/null +++ b/client/src/contracts.js @@ -0,0 +1,12 @@ +const contracts = { + '0x539': { // Hardhat + DAO: '0x76Dfe9F47f06112a1b78960bf37d87CfbB6D6133', + Work1: '0xd2845aE812Ee42cF024fB4C55c052365792aBd78', + }, + '0xaa36a7': { // Sepolia + DAO: '0x39B7522Ee1A5B13aE5580C40114239D4cE0e7D29', + Work1: '0xC0Bb36820Ba891DE4ed6D60f75066805361dbeB8', + }, +}; + +export default contracts;