cra upgrades

This commit is contained in:
Mason 2022-10-13 04:48:18 -05:00
parent 6c69a5286b
commit a0a7f53831
11 changed files with 20301 additions and 18689 deletions

View File

@ -1,4 +1,5 @@
const path = require('path');
const Dotenv = require('dotenv-webpack');
module.exports = {
webpack: {
@ -22,6 +23,25 @@ module.exports = {
'@utils': path.resolve(__dirname, 'src/utils/'),
'@hooks': path.resolve(__dirname, 'src/hooks/'),
'@abis': path.resolve(__dirname, 'src/abis/')
}
},
plugins: [
new Dotenv({
path: '../.env',
safe: true,
ignoreStub: true,
})
],
configure: {
ignoreWarnings: [
function ignoreSourcemapsloaderWarnings(warning) {
return (
warning.module &&
warning.module.resource.includes("node_modules") &&
warning.details &&
warning.details.includes("source-map-loader")
);
},
],
},
}
}

38671
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@craco/craco": "^6.4.5",
"@craco/craco": "^7.0.0-alpha.0",
"@emotion/react": "^11.9.3",
"@emotion/styled": "^11.9.3",
"@fortawesome/fontawesome-pro": "^6.2.0",
@ -16,19 +16,22 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@mui/icons-material": "^5.8.4",
"@mui/material": "^5.8.7",
"@rainbow-me/rainbowkit": "^0.6.0",
"@rainbow-me/rainbowkit": "^0.7.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"dotenv": "^16.0.3",
"dotenv-webpack": "^8.0.1",
"ethers": "^5.5.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet-async": "^1.3.0",
"react-router-dom": "^6.3.0",
"react-scripts": "4.0.3",
"react-scripts": "5.0.0",
"siwe": "^1.1.6",
"wagmi": "^0.6.6",
"web-vitals": "^2.1.4"
"wagmi": "^0.6.8",
"web-vitals": "^2.1.4",
"webpack": "^5.74.0"
},
"scripts": {
"start": "craco start",

View File

@ -1,4 +1,4 @@
import { useState, useContext, useEffect } from "react";
import { useState, useContext, useEffect, useCallback } from "react";
import { useNavigate, useParams } from "react-router-dom";
// import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -67,7 +67,7 @@ const Badge = () => {
// Update the badge array after the transaction is completed, POST
// out to the API, update our orgData context, and reset call transaction flag.
const onMembersUpdate = async () => {
const onMembersUpdate = useCallback(async () => {
if (!badge.users) badge.users = [];
membersToUpdate.forEach(member => {
@ -88,11 +88,11 @@ const Badge = () => {
setCallTransaction("");
setTxPending(false);
}
}, [badge, membersToUpdate, selectedAction, orgId, setError, setOrgData, badgeIndex]);
// Update the badge array after the transaction is completed, POST
// out to the API, update our orgData context, and reset call transaction flag.
const onDelegatesUpdate = async () => {
const onDelegatesUpdate = useCallback(async () => {
if (!badge.delegates) badge.delegates = [];
membersToUpdate.forEach(member => {
@ -113,37 +113,36 @@ const Badge = () => {
setCallTransaction("");
setTxPending(false);
}
}, [badge, badgeIndex, membersToUpdate, orgId, selectedAction, setError, setOrgData]);
const runTransaction = useCallback(async () => {
setTxPending(true);
let tx;
try {
if (setDelegates.isSuccess)
tx = await setDelegates.write?.()
else if (manageOwnership.isSuccess)
tx = await manageOwnership.write?.()
if (tx) {
const txReceipt = await tx?.wait();
if (txReceipt.status === 1) {
callTransaction === "manageOwnership" ? onMembersUpdate() : onDelegatesUpdate();
}
}
} catch (error) {
setError('Transaction failed: ' + error);
setCallTransaction("")
}
setTxPending(false);
}, [callTransaction, setDelegates, manageOwnership, setError, onMembersUpdate, onDelegatesUpdate]);
// Run the transaction hook once it has been prepped. If successful, update the badge data.
useEffect(() => {
async function runTransaction() {
setTxPending(true);
let tx;
try {
if (setDelegates.isSuccess)
tx = await setDelegates.write?.()
else if (manageOwnership.isSuccess)
tx = await manageOwnership.write?.()
if (tx) {
const txReceipt = await tx?.wait();
if (txReceipt.status === 1) {
callTransaction === "manageOwnership" ? onMembersUpdate() : onDelegatesUpdate();
}
}
} catch (error) {
setError('Transaction failed: ' + error);
setCallTransaction("")
}
setTxPending(false);
}
useEffect(() => {
if (callTransaction && !txPending)
runTransaction();
// eslint-disable-next-line
}, [setDelegates.isSuccess, manageOwnership.isSuccess, callTransaction])
}, [setDelegates.isSuccess, callTransaction, runTransaction, txPending])
useEffect(() => {
if (orgData?.badges[badgeIndex]) {

View File

@ -1,4 +1,4 @@
import { useState, useRef, useContext, useEffect } from "react";
import { useState, useRef, useContext, useEffect, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import Header from "@components/Dashboard/Header/Header";
@ -8,7 +8,6 @@ import InputListCSV from "@components/Dashboard/Form/InputListCSV";
import { OrgContext } from "@components/Dashboard/Provider/OrgContextProvider";
import { ErrorContext } from "@components/Dashboard/Provider/ErrorContextProvider";
import { IPFS_GATEWAY_URL } from "@static/constants/links"
import { postBadgeRequest, postIPFSImage, postIPFSMetadata } from "@utils/api_requests";
import { useCreateBadge } from "@hooks/useContracts";
@ -25,13 +24,13 @@ const BadgeForm = () => {
const [ txPending, setTxPending ] = useState(false);
const { orgData, setOrgData } = useContext(OrgContext);
const { setError } = useContext(ErrorContext);
const [ badgeObj, setBadgeObj ] = useState({
name: badgeName,
description: badgeDescription,
delegates: badgeDelegates,
image_hash: ipfsImageHash,
contract_address: orgData?.ethereum_address,
ethereum_address: orgData?.ethereum_address,
token_id: orgData?.badges?.length,
organization: orgData?.id,
account_bound: true,
@ -67,10 +66,10 @@ const BadgeForm = () => {
if (response.error) {
setError('Error creating token URI: ' + response.error);
}
const token_uri = IPFS_GATEWAY_URL + response.hash
setBadgeObj({
...badgeObj,
token_uri: token_uri,
token_uri: response.hash,
name: badgeName,
description: badgeDescription,
delegates: badgeDelegates,
@ -91,48 +90,67 @@ const BadgeForm = () => {
setBadgeObj({...badgeObj, image_hash: response.hash})
}
// Write to contract
const createBadgeTx = useCallback(async () => {
try {
let tx = await createBadge.write?.();
tx = await tx?.wait();
// if transaction is successful
if (tx.status === 1)
badgeObj.is_active = true;
// Post to database
const response = await postBadgeRequest(badgeObj);
badgeObj.url = response.url
// if POST is successful
if (!response.error) {
// Set in orgData context
let prev = {...orgData}
prev.badges.push(badgeObj)
setOrgData(prev)
navigate(`/dashboard/organization/${orgData?.id}/badge/${badgeObj.id}`);
}
else {
throw new Error('Could not add badge to database ' + response.error);
}
}
catch (error) {
setError('Error creating badge: ' + error);
setTxPending(false);
}
}, [badgeObj, createBadge, navigate, orgData, setError, setOrgData]);
// Run the transaction after it has been prepared by wagmi.
// After the transaction is successful, POST badge to is_active,
// set the new badge in orgData, and navigate to the badge page.
useEffect(() => {
async function createBadgeTx() {
if (
createBadge.isSuccess
&& !txPending
&& badgeObj?.ethereum_address
) {
setTxPending(true);
// Write to contract
try {
let tx = await createBadge.write?.();
tx = await tx?.wait();
// if transaction is successful
if (tx.status === 1)
badgeObj.is_active = true;
// Post to database
const response = await postBadgeRequest(badgeObj);
badgeObj.url = response.url
// if POST is successful
if (!response.error) {
// Set in orgData context
let prev = {...orgData}
prev.badges.push(badgeObj)
setOrgData(prev)
navigate(`/dashboard/organization/${orgData?.id}/badge/${badgeObj.id}`);
}
else {
throw new Error('Could not add badge to database ' + response.error);
}
}
catch (error) {
setError('Error creating badge: ' + error);
}
setTxPending(false);
}
if (createBadge.isSuccess)
createBadgeTx();
// eslint-disable-next-line
}, [createBadge.isSuccess])
}
}, [createBadge.isSuccess, txPending, createBadgeTx])
// Set the badgeObj state when orgData is updated
useEffect(() => {
setBadgeObj({
...badgeObj,
image_hash: ipfsImageHash,
ethereum_address: orgData?.ethereum_address,
token_id: orgData?.badges?.length,
organization: orgData?.id,
account_bound: true,
claimable: false,
is_active: false,
signer: orgData?.owner?.ethereum_address,
})
}, [orgData, setBadgeObj])
return (
<div id="new-badge">

View File

@ -1,4 +1,4 @@
import { useContext, useEffect } from "react";
import { useContext } from "react";
import { useNavigate, Link, useParams } from "react-router-dom";
import IconButton from "@components/Button/IconButton";
@ -10,7 +10,7 @@ import "@style/Dashboard/Org/Org.css";
const Org = () => {
const navigate = useNavigate();
const { orgData, setCurrentOrgId } = useContext(OrgContext);
const { orgData } = useContext(OrgContext);
const { orgId } = useParams();
return (

View File

@ -1,4 +1,4 @@
import { useState, useContext, useRef, useEffect, useMemo } from "react";
import { useState, useContext, useRef, useEffect, useMemo, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import { useNetwork, useAccount } from "wagmi";
@ -76,19 +76,6 @@ const OrgForm = () => {
}
}
// Determines if organizations is already in userData, before pushing or settings
// the new organization to userData.
const addOrgToState = (org) => {
let newUserData = {...userData};
if (newUserData.organizations)
newUserData.organizations.push(org);
else
newUserData.organizations = [org];
setUserData(newUserData);
}
// Posts contract uri to IPFS and sets the returned hash to orgObj uri hash.
const onFormSubmission = async () => {
setLoading(true);
@ -102,29 +89,29 @@ const OrgForm = () => {
}
// Awaits a prepared transaction before running it.
useEffect(() => {
async function createOrgTx() {
setTxPending(true);
try {
let tx = await createContract.write?.();
tx = await tx?.wait();
// Decode the transaction receipt to get the contract address from the event.
const orgCreatedTopic = badger.abi.getEventTopic("OrganizationCreated");
const orgCreatedEvent = tx.logs.find((log) => log.topics[0] === orgCreatedTopic);
const orgEvent = badger.abi.decodeEventLog("OrganizationCreated", orgCreatedEvent.data, orgCreatedEvent.topics);
const contractAddress = orgEvent.organization;
// If transaction was confirmed, add is_active and contract address to orgObj.
// Adding the ethereum address will trigger a useEffect to post to backend.
setOrgObj({...orgObj, ethereum_address: contractAddress, is_active: true});
}
catch (error) {
setError('Error creating Org: ' + error);
setLoading(false);
}
setTxPending(false);
}
const createOrgTx = useCallback(async () => {
setTxPending(true);
try {
let tx = await createContract.write?.();
tx = await tx?.wait();
// Decode the transaction receipt to get the contract address from the event.
const orgCreatedTopic = badger.abi.getEventTopic("OrganizationCreated");
const orgCreatedEvent = tx.logs.find((log) => log.topics[0] === orgCreatedTopic);
const orgEvent = badger.abi.decodeEventLog("OrganizationCreated", orgCreatedEvent.data, orgCreatedEvent.topics);
const contractAddress = orgEvent.organization;
// If transaction was confirmed, add is_active and contract address to orgObj.
// Adding the ethereum address will trigger a useEffect to post to backend.
setOrgObj({...orgObj, ethereum_address: contractAddress, is_active: true});
}
catch (error) {
setError('Error creating Org: ' + error);
setLoading(false);
}
setTxPending(false);
}, [createContract, badger.abi, orgObj, setError]);
useEffect(() => {
// This is bad/ugly code, but it works to only trigger the call when the button has been clicked
// (loading), the transaction is prepared (isSuccess), there's not a pending transaction
// (!txPending), and the ethereum address has not been set after a successful transaction.
@ -136,28 +123,33 @@ const OrgForm = () => {
) {
createOrgTx();
}
}, [createContract.isSuccess, orgObj.ethereum_address, loading, txPending])
}, [createContract.isSuccess, orgObj.ethereum_address, loading, txPending, createOrgTx])
const postOrg = useCallback(async () => {
const response = await postOrgRequest(orgObj);
if (!response?.error && response?.id) {
let newUserData = {...userData};
if (newUserData.organizations)
newUserData.organizations.push(response);
else
newUserData.organizations = [response];
setUserData(newUserData);
navigate(`/dashboard/organization/${response.id}`);
}
else {
setError('Could not add org to database: ' + response.error);
}
setLoading(false);
}, [orgObj, navigate, userData, setUserData, setError]);
// Upon receiving contract address from transaction event,
// POST org to backend and if successful, add to state and navigate to org page.
useEffect(() => {
async function postOrg() {
const response = await postOrgRequest(orgObj);
if (!response?.error && response?.id) {
addOrgToState(response);
navigate(`/dashboard/organization/${response.id}`);
}
else {
setError('Could not add org to database: ' + response.error);
}
setLoading(false);
}
if (orgObj.ethereum_address)
postOrg();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [orgObj.ethereum_address])
}, [orgObj.ethereum_address, postOrg])
return (
<div id="new-org">

View File

@ -46,7 +46,7 @@ const OrgContextProvider = ({ children }) => {
// hacky way to get OrgId. TODO: Put sidebars and context providers inside of a
// base "/dashboard" route so that we can use useParams() to get the orgId.
const path = pathname.split('/');
const orgId = path[path.indexOf('organization') + 1] || null
const orgId = path.includes('organization') && !path.includes('organization/new') ? path[3] : null;
if (orgId && orgId !== currentOrgId) {
setCurrentOrgId(orgId);

View File

@ -51,7 +51,6 @@ const UserContextProvider = ({ children, signer, address }) => {
setIsAuthenticating(false);
const siweResponse = await SIWEAuthorize(signer, address, chain?.id);
console.log('siwe response', siweResponse)
if(siweResponse.success) {
setUserData({})

View File

@ -12,11 +12,11 @@ import { UserContext } from "@components/Dashboard/Provider/UserContextProvider"
import { OrgContext } from "@components/Dashboard/Provider/OrgContextProvider";
import { IPFS_GATEWAY_URL, PLACEHOLDER_AVATAR } from "@static/constants/links";
import '@rainbow-me/rainbowkit/dist/index.css';
import '@rainbow-me/rainbowkit/styles.css'
import "@style/Dashboard/Sidebar/Sidebar.css";
import "@style/Dashboard/Sidebar/OrgSidebar.css";
const BADGER_ADDRESSES = JSON.parse(process.env.REACT_APP_BADGER_ADDRESSES)
// const BADGER_ADDRESSES = JSON.parse(process.env.REACT_APP_BADGER_ADDRESSES)
const PRIMARY_PRODUCTION_CHAIN = process.env.REACT_APP_PRODUCTION_CHAIN;
const OrgSidebar = ({ address }) => {
@ -50,15 +50,15 @@ const OrgSidebar = ({ address }) => {
// current primary chain. If programmatic network switching does not work, then change
// the connect button to switch network.
const onSwitchNetworkRequest = useCallback(() => {
if (!(chain?.name in BADGER_ADDRESSES)) {
try {
const primaryChain = chains.find(c => c.name === PRIMARY_PRODUCTION_CHAIN)
switchNetwork?.(primaryChain.id)
setCannotSwitchNetwork(true);
}
else {
setCannotSwitchNetwork(false);
}
catch {
setCannotSwitchNetwork(true);
}},
[chain, chains, switchNetwork]
[chains, switchNetwork]
)
useEffect(() => {
onSwitchNetworkRequest();

View File

@ -70,8 +70,6 @@ export const useCreateBadge = (badge) => {
badge.delegates.pop(index)
}
})
// Format to bytes32
// let paymentKey = ethers.utils.formatBytes32String(badge.payment_token[0]);
let args = [
badge.token_id,
@ -84,7 +82,7 @@ export const useCreateBadge = (badge) => {
]
const { config, isSuccess } = usePrepareContractWrite({
addressOrName: badge.contract_address,
addressOrName: badge.ethereum_address,
contractInterface: BadgerOrganization.abi,
functionName: "setBadge",
args: args,