diff --git a/packages/concordia-app/src/components/LoadingContainer.jsx b/packages/concordia-app/src/components/LoadingContainer.jsx index ec25a67..0852657 100644 --- a/packages/concordia-app/src/components/LoadingContainer.jsx +++ b/packages/concordia-app/src/components/LoadingContainer.jsx @@ -5,6 +5,7 @@ import LoadingComponent from './LoadingComponent'; // CSS import '../assets/css/loading-component.css'; +import { FORUM_CONTRACT } from '../constants/ContractNames'; const LoadingContainer = ({ children }) => { const initializing = useSelector((state) => state.drizzleStatus.initializing); @@ -15,8 +16,8 @@ const LoadingContainer = ({ children }) => { const web3NetworkId = useSelector((state) => state.web3.networkId); const web3NetworkFailed = useSelector((state) => state.web3.networkFailed); const web3AccountsFailed = useSelector((state) => state.web3.accountsFailed); - const contractInitialized = useSelector((state) => state.contracts.Forum.initialized); - const contractDeployed = useSelector((state) => state.contracts.Forum.deployed); + const contractInitialized = useSelector((state) => state.contracts[FORUM_CONTRACT].initialized); + const contractDeployed = useSelector((state) => state.contracts[FORUM_CONTRACT].deployed); const userFetched = useSelector((state) => state.user.address); if (!window.ethereum) { diff --git a/packages/concordia-app/src/components/PostCreate/index.jsx b/packages/concordia-app/src/components/PostCreate/index.jsx index 67c06b7..fcaec71 100644 --- a/packages/concordia-app/src/components/PostCreate/index.jsx +++ b/packages/concordia-app/src/components/PostCreate/index.jsx @@ -15,8 +15,10 @@ import { breeze, drizzle } from '../../redux/store'; import './styles.css'; import { TRANSACTION_ERROR, TRANSACTION_SUCCESS } from '../../constants/TransactionStatus'; import { POST_CONTENT, POST_SUBJECT } from '../../constants/PostsDatabaseKeys'; +import { FORUM_CONTRACT } from '../../constants/ContractNames'; +import { POST_CREATED_EVENT } from '../../constants/ForumContractEvents'; -const { contracts: { Forum: { methods: { createPost } } } } = drizzle; +const { contracts: { [FORUM_CONTRACT]: { methods: { createPost } } } } = drizzle; const { orbit } = breeze; const PostCreate = (props) => { @@ -84,7 +86,7 @@ const PostCreate = (props) => { setPosting(false); } else if (transactions[transactionStack[createPostCacheSendStackId]].status === TRANSACTION_SUCCESS) { const { - receipt: { events: { PostCreated: { returnValues: { postID: contractPostId } } } }, + receipt: { events: { [POST_CREATED_EVENT]: { returnValues: { postID: contractPostId } } } }, } = transactions[transactionStack[createPostCacheSendStackId]]; const { stores } = orbit; diff --git a/packages/concordia-app/src/components/PostList/PostListRow/index.jsx b/packages/concordia-app/src/components/PostList/PostListRow/index.jsx index 4549dc7..085c217 100644 --- a/packages/concordia-app/src/components/PostList/PostListRow/index.jsx +++ b/packages/concordia-app/src/components/PostList/PostListRow/index.jsx @@ -16,6 +16,7 @@ import { POSTS_DATABASE, USER_DATABASE } from '../../../constants/OrbitDatabases import determineKVAddress from '../../../utils/orbitUtils'; import { USER_PROFILE_PICTURE } from '../../../constants/UserDatabaseKeys'; import { POST_CONTENT, POST_SUBJECT } from '../../../constants/PostsDatabaseKeys'; +import { FORUM_CONTRACT } from '../../../constants/ContractNames'; const { orbit } = breeze; @@ -23,7 +24,7 @@ const PostListRow = (props) => { const { id: postId, postIndexInTopic, postCallHash, loading, } = props; - const getPostResults = useSelector((state) => state.contracts.Forum.getPost); + const getPostResults = useSelector((state) => state.contracts[FORUM_CONTRACT].getPost); const [postAuthorAddress, setPostAuthorAddress] = useState(null); const [postAuthor, setPostAuthor] = useState(null); const [timeAgo, setTimeAgo] = useState(null); diff --git a/packages/concordia-app/src/components/PostList/index.jsx b/packages/concordia-app/src/components/PostList/index.jsx index c4fe149..68759b2 100644 --- a/packages/concordia-app/src/components/PostList/index.jsx +++ b/packages/concordia-app/src/components/PostList/index.jsx @@ -6,8 +6,9 @@ import { useSelector } from 'react-redux'; import { Dimmer, Feed, Loader } from 'semantic-ui-react'; import PostListRow from './PostListRow'; import { drizzle } from '../../redux/store'; +import { FORUM_CONTRACT } from '../../constants/ContractNames'; -const { contracts: { Forum: { methods: { getPost: { cacheCall: getPostChainData } } } } } = drizzle; +const { contracts: { [FORUM_CONTRACT]: { methods: { getPost: { cacheCall: getPostChainData } } } } } = drizzle; const PostList = (props) => { const { postIds, loading } = props; diff --git a/packages/concordia-app/src/components/TopicList/TopicListRow/index.jsx b/packages/concordia-app/src/components/TopicList/TopicListRow/index.jsx index f77cd59..4d25f91 100644 --- a/packages/concordia-app/src/components/TopicList/TopicListRow/index.jsx +++ b/packages/concordia-app/src/components/TopicList/TopicListRow/index.jsx @@ -17,12 +17,13 @@ import { TOPICS_DATABASE, USER_DATABASE } from '../../../constants/OrbitDatabase import determineKVAddress from '../../../utils/orbitUtils'; import { USER_PROFILE_PICTURE } from '../../../constants/UserDatabaseKeys'; import { TOPIC_SUBJECT } from '../../../constants/TopicsDatabaseKeys'; +import { FORUM_CONTRACT } from '../../../constants/ContractNames'; const { orbit } = breeze; const TopicListRow = (props) => { const { id: topicId, topicCallHash, loading } = props; - const getTopicResults = useSelector((state) => state.contracts.Forum.getTopic); + const getTopicResults = useSelector((state) => state.contracts[FORUM_CONTRACT].getTopic); const [numberOfReplies, setNumberOfReplies] = useState(null); const [topicAuthorAddress, setTopicAuthorAddress] = useState(null); const [topicAuthor, setTopicAuthor] = useState(null); diff --git a/packages/concordia-app/src/components/TopicList/index.jsx b/packages/concordia-app/src/components/TopicList/index.jsx index 511ae2b..e171caf 100644 --- a/packages/concordia-app/src/components/TopicList/index.jsx +++ b/packages/concordia-app/src/components/TopicList/index.jsx @@ -6,8 +6,9 @@ import { useSelector } from 'react-redux'; import { List } from 'semantic-ui-react'; import TopicListRow from './TopicListRow'; import { drizzle } from '../../redux/store'; +import { FORUM_CONTRACT } from '../../constants/ContractNames'; -const { contracts: { Forum: { methods: { getTopic: { cacheCall: getTopicChainData } } } } } = drizzle; +const { contracts: { [FORUM_CONTRACT]: { methods: { getTopic: { cacheCall: getTopicChainData } } } } } = drizzle; const TopicList = (props) => { const { topicIds } = props; diff --git a/packages/concordia-app/src/constants/ContractNames.js b/packages/concordia-app/src/constants/ContractNames.js index bfb65b4..95fe6f7 100644 --- a/packages/concordia-app/src/constants/ContractNames.js +++ b/packages/concordia-app/src/constants/ContractNames.js @@ -1 +1 @@ -export const FORUM = 'Forum'; +export const FORUM_CONTRACT = 'Forum'; diff --git a/packages/concordia-app/src/constants/ForumContractEvents.js b/packages/concordia-app/src/constants/ForumContractEvents.js new file mode 100644 index 0000000..f0f9a34 --- /dev/null +++ b/packages/concordia-app/src/constants/ForumContractEvents.js @@ -0,0 +1,13 @@ +export const USER_SIGNED_UP_EVENT = 'UserSignedUp'; +export const USERNAME_UPDATED_EVENT = 'UsernameUpdated'; +export const TOPIC_CREATED_EVENT = 'TopicCreated'; +export const POST_CREATED_EVENT = 'PostCreated'; + +const forumContractEvents = [ + USER_SIGNED_UP_EVENT, + USERNAME_UPDATED_EVENT, + TOPIC_CREATED_EVENT, + POST_CREATED_EVENT, +]; + +export default forumContractEvents; diff --git a/packages/concordia-app/src/options/drizzleOptions.js b/packages/concordia-app/src/options/drizzleOptions.js index aa563f7..80dd30c 100644 --- a/packages/concordia-app/src/options/drizzleOptions.js +++ b/packages/concordia-app/src/options/drizzleOptions.js @@ -1,6 +1,8 @@ // See also: https://truffleframework.com/docs/drizzle/reference/drizzle-options import { contracts } from 'concordia-contracts'; import web3Options from './web3Options'; +import forumContractEvents from '../constants/ForumContractEvents'; +import { FORUM_CONTRACT } from '../constants/ContractNames'; const drizzleOptions = { web3: { @@ -8,7 +10,7 @@ const drizzleOptions = { }, contracts, events: { - Forum: ['UserSignedUp', 'UsernameUpdated', 'TopicCreated', 'PostCreated'], + [FORUM_CONTRACT]: forumContractEvents, }, reloadWindowOnNetworkChange: true, reloadWindowOnAccountChange: true, // We need it to reinitialize breeze and create new Orbit databases diff --git a/packages/concordia-app/src/redux/actions/contractEventActions.js b/packages/concordia-app/src/redux/actions/contractEventActions.js new file mode 100644 index 0000000..1dd5be1 --- /dev/null +++ b/packages/concordia-app/src/redux/actions/contractEventActions.js @@ -0,0 +1,20 @@ +import { + POST_CREATED_EVENT, + TOPIC_CREATED_EVENT, + USER_SIGNED_UP_EVENT, + USERNAME_UPDATED_EVENT, +} from '../../constants/ForumContractEvents'; + +export const FORUM_EVENT_USER_SIGNED_UP = 'FORUM_EVENT_USER_SIGNED_UP'; +export const FORUM_EVENT_USERNAME_UPDATED = 'FORUM_EVENT_USERNAME_UPDATED'; +export const FORUM_EVENT_TOPIC_CREATED = 'FORUM_EVENT_TOPIC_CREATED'; +export const FORUM_EVENT_POST_CREATED = 'FORUM_EVENT_POST_CREATED'; + +const eventActionMap = { + [USER_SIGNED_UP_EVENT]: FORUM_EVENT_USER_SIGNED_UP, + [USERNAME_UPDATED_EVENT]: FORUM_EVENT_USERNAME_UPDATED, + [TOPIC_CREATED_EVENT]: FORUM_EVENT_TOPIC_CREATED, + [POST_CREATED_EVENT]: FORUM_EVENT_POST_CREATED, +}; + +export default eventActionMap; diff --git a/packages/concordia-app/src/redux/sagas/eventSaga.js b/packages/concordia-app/src/redux/sagas/eventSaga.js new file mode 100644 index 0000000..b6017c6 --- /dev/null +++ b/packages/concordia-app/src/redux/sagas/eventSaga.js @@ -0,0 +1,13 @@ +import { put, takeEvery } from 'redux-saga/effects'; +import { CONTRACT_EVENT_FIRED } from '@ezerous/drizzle/src/contracts/constants'; +import eventActionMap from '../actions/contractEventActions'; + +function* eventBreakDown({ event }) { + yield put({ type: eventActionMap[event.event], event: { ...event } }); +} + +function* eventSaga() { + yield takeEvery(CONTRACT_EVENT_FIRED, eventBreakDown); +} + +export default eventSaga; diff --git a/packages/concordia-app/src/redux/sagas/rootSaga.js b/packages/concordia-app/src/redux/sagas/rootSaga.js index 7f5bfb4..dd24291 100644 --- a/packages/concordia-app/src/redux/sagas/rootSaga.js +++ b/packages/concordia-app/src/redux/sagas/rootSaga.js @@ -4,11 +4,13 @@ import { breezeSagas } from '@ezerous/breeze'; import orbitSaga from './orbitSaga'; import userSaga from './userSaga'; import peerDbReplicationSaga from './peerDbReplicationSaga'; +import eventSaga from './eventSaga'; export default function* root() { const sagas = [ ...drizzleSagas, ...breezeSagas, + eventSaga, orbitSaga, userSaga, peerDbReplicationSaga, diff --git a/packages/concordia-app/src/redux/sagas/userSaga.js b/packages/concordia-app/src/redux/sagas/userSaga.js index 6d35de4..f436914 100644 --- a/packages/concordia-app/src/redux/sagas/userSaga.js +++ b/packages/concordia-app/src/redux/sagas/userSaga.js @@ -1,13 +1,14 @@ /* eslint-disable no-console */ import { - all, call, put, take, + all, call, put, take, takeLatest, } from 'redux-saga/effects'; - import { drizzleActions } from '@ezerous/drizzle'; import { USER_DATA_UPDATED, USER_DATA_ERROR } from '../actions/userActions'; +import { FORUM_EVENT_USER_SIGNED_UP } from '../actions/contractEventActions'; +import { FORUM_CONTRACT } from '../../constants/ContractNames'; function* fetchUserData({ drizzle, account }) { - const contract = drizzle.contracts.Forum; + const contract = drizzle.contracts[FORUM_CONTRACT]; const transaction = yield call(contract.methods.hasUserSignedUp, account); try { @@ -31,6 +32,15 @@ function* fetchUserData({ drizzle, account }) { } } +function* userHasSignedUp({ event }) { + yield put({ + type: USER_DATA_UPDATED, + ...{ + address: event.returnValues.userAddress, username: event.returnValues.username, + }, + }); +} + function* userSaga() { const res = yield all([ take(drizzleActions.drizzle.DRIZZLE_INITIALIZED), @@ -38,6 +48,8 @@ function* userSaga() { ]); yield fetchUserData({ drizzle: res[0].drizzle, account: res[1].accounts[0] }); + + yield takeLatest(FORUM_EVENT_USER_SIGNED_UP, userHasSignedUp); } export default userSaga; diff --git a/packages/concordia-app/src/views/Home/index.jsx b/packages/concordia-app/src/views/Home/index.jsx index ce9decf..3272cfd 100644 --- a/packages/concordia-app/src/views/Home/index.jsx +++ b/packages/concordia-app/src/views/Home/index.jsx @@ -6,12 +6,13 @@ import { useSelector } from 'react-redux'; import Board from './Board'; import './styles.css'; import { drizzle } from '../../redux/store'; +import { FORUM_CONTRACT } from '../../constants/ContractNames'; -const { contracts: { Forum: { methods: { getNumberOfTopics } } } } = drizzle; +const { contracts: { [FORUM_CONTRACT]: { methods: { getNumberOfTopics } } } } = drizzle; const Home = () => { const [numberOfTopicsCallHash, setNumberOfTopicsCallHash] = useState(''); - const getNumberOfTopicsResults = useSelector((state) => state.contracts.Forum.getNumberOfTopics); + const getNumberOfTopicsResults = useSelector((state) => state.contracts[FORUM_CONTRACT].getNumberOfTopics); useEffect(() => { setNumberOfTopicsCallHash(getNumberOfTopics.cacheCall()); diff --git a/packages/concordia-app/src/views/Register/SignUpStep/index.jsx b/packages/concordia-app/src/views/Register/SignUpStep/index.jsx index 006ce04..948b3ae 100644 --- a/packages/concordia-app/src/views/Register/SignUpStep/index.jsx +++ b/packages/concordia-app/src/views/Register/SignUpStep/index.jsx @@ -11,13 +11,14 @@ import { useHistory } from 'react-router'; import PropTypes from 'prop-types'; import { drizzle } from '../../../redux/store'; import { TRANSACTION_ERROR, TRANSACTION_SUCCESS } from '../../../constants/TransactionStatus'; +import { FORUM_CONTRACT } from '../../../constants/ContractNames'; -const { contracts: { Forum: { methods: { isUserNameTaken, signUp } } } } = drizzle; +const { contracts: { [FORUM_CONTRACT]: { methods: { isUserNameTaken, signUp } } } } = drizzle; const SignUpStep = (props) => { const { pushNextStep, account } = props; const user = useSelector((state) => state.user); - const isUserNameTakenResults = useSelector((state) => state.contracts.Forum.isUserNameTaken); + const isUserNameTakenResults = useSelector((state) => state.contracts[FORUM_CONTRACT].isUserNameTaken); const transactionStack = useSelector((state) => state.transactionStack); const transactions = useSelector((state) => state.transactions); const [usernameInput, setUsernameInput] = useState(''); diff --git a/packages/concordia-app/src/views/Register/index.jsx b/packages/concordia-app/src/views/Register/index.jsx index e7da27f..d2dac4a 100644 --- a/packages/concordia-app/src/views/Register/index.jsx +++ b/packages/concordia-app/src/views/Register/index.jsx @@ -13,6 +13,7 @@ import { REGISTER_STEP_PROFILE_INFORMATION, REGISTER_STEP_SIGNUP } from '../../c const Register = () => { const [currentStep, setCurrentStep] = useState('signup'); const user = useSelector((state) => state.user); + const [signingUp] = useState(!user.hasSignedUp); const history = useHistory(); const { t } = useTranslation(); @@ -92,7 +93,7 @@ const Register = () => {

- {user.hasSignedUp + {user.hasSignedUp && !signingUp ? ( <> diff --git a/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx b/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx index 06d77b3..a801b5a 100644 --- a/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx +++ b/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx @@ -13,8 +13,10 @@ import { TRANSACTION_ERROR, TRANSACTION_SUCCESS } from '../../../constants/Trans import { POSTS_DATABASE, TOPICS_DATABASE } from '../../../constants/OrbitDatabases'; import { TOPIC_SUBJECT } from '../../../constants/TopicsDatabaseKeys'; import { POST_CONTENT, POST_SUBJECT } from '../../../constants/PostsDatabaseKeys'; +import { FORUM_CONTRACT } from '../../../constants/ContractNames'; +import { TOPIC_CREATED_EVENT } from '../../../constants/ForumContractEvents'; -const { contracts: { Forum: { methods: { createTopic } } } } = drizzle; +const { contracts: { [FORUM_CONTRACT]: { methods: { createTopic } } } } = drizzle; const { orbit: { stores } } = breeze; const TopicCreate = (props) => { @@ -55,7 +57,7 @@ const TopicCreate = (props) => { const { receipt: { events: { - TopicCreated: { + [TOPIC_CREATED_EVENT]: { returnValues: { topicID: topicId, postID: postId, diff --git a/packages/concordia-app/src/views/Topic/TopicView/index.jsx b/packages/concordia-app/src/views/Topic/TopicView/index.jsx index 79a6109..c3fa8cf 100644 --- a/packages/concordia-app/src/views/Topic/TopicView/index.jsx +++ b/packages/concordia-app/src/views/Topic/TopicView/index.jsx @@ -16,8 +16,9 @@ import determineKVAddress from '../../../utils/orbitUtils'; import { USER_PROFILE_PICTURE } from '../../../constants/UserDatabaseKeys'; import { TOPIC_SUBJECT } from '../../../constants/TopicsDatabaseKeys'; import PostCreate from '../../../components/PostCreate'; +import { FORUM_CONTRACT } from '../../../constants/ContractNames'; -const { contracts: { Forum: { methods: { getTopic: { cacheCall: getTopicChainData } } } } } = drizzle; +const { contracts: { [FORUM_CONTRACT]: { methods: { getTopic: { cacheCall: getTopicChainData } } } } } = drizzle; const { orbit } = breeze; const TopicView = (props) => { @@ -28,7 +29,7 @@ const TopicView = (props) => { const drizzleInitialized = useSelector((state) => state.drizzleStatus.initialized); const drizzleInitializationFailed = useSelector((state) => state.drizzleStatus.failed); const userAddress = useSelector((state) => state.user.address); - const getTopicResults = useSelector((state) => state.contracts.Forum.getTopic); + const getTopicResults = useSelector((state) => state.contracts[FORUM_CONTRACT].getTopic); const topics = useSelector((state) => state.orbitData.topics); const users = useSelector((state) => state.orbitData.users); const [getTopicCallHash, setGetTopicCallHash] = useState([]); diff --git a/packages/concordia-contracts/contracts/Forum.sol b/packages/concordia-contracts/contracts/Forum.sol index 13ad2ea..5b15290 100644 --- a/packages/concordia-contracts/contracts/Forum.sol +++ b/packages/concordia-contracts/contracts/Forum.sol @@ -16,7 +16,7 @@ contract Forum { mapping (string => address) userAddresses; event UserSignedUp(string username, address userAddress); - event UsernameUpdated(string newName, string oldName,address userAddress); + event UsernameUpdated(string newName, string oldName, address userAddress); function signUp(string memory username) public returns (bool) { require (!hasUserSignedUp(msg.sender), "User has already signed up.");