mirror of
https://github.com/FlipsideCrypto/badger.git
synced 2026-02-06 10:57:46 +00:00
cra upgrades
This commit is contained in:
parent
6c69a5286b
commit
a0a7f53831
@ -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
38671
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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",
|
||||
|
||||
@ -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]) {
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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 (
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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({})
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user