diff --git a/packages/concordia-app/package.json b/packages/concordia-app/package.json
index 54356c7..904518e 100644
--- a/packages/concordia-app/package.json
+++ b/packages/concordia-app/package.json
@@ -31,6 +31,7 @@
"@welldone-software/why-did-you-render": "~6.0.5",
"concordia-contracts": "~0.1.0",
"concordia-shared": "~0.1.0",
+ "crypto-js": "~4.0.0",
"i18next": "^19.8.3",
"i18next-browser-languagedetector": "^6.0.1",
"i18next-http-backend": "^1.0.21",
diff --git a/packages/concordia-app/public/locales/en/translation.json b/packages/concordia-app/public/locales/en/translation.json
index d4661ce..aa249a2 100644
--- a/packages/concordia-app/public/locales/en/translation.json
+++ b/packages/concordia-app/public/locales/en/translation.json
@@ -22,6 +22,12 @@
"edit.information.modal.form.profile.picture.field.placeholder": "URL",
"edit.information.modal.form.submit.button": "Submit",
"edit.information.modal.title": "Edit profile information",
+ "poll.create.question.field.label": "Poll Question",
+ "poll.create.question.field.placeholder": "Question",
+ "poll.create.allow.vote.changes.field.label": "Allow vote changes",
+ "poll.create.option.field.label": "Option #{{id}}",
+ "poll.create.option.field.placeholder": "Option #{{id}}",
+ "poll.create.add.option.button": "Add Option",
"post.create.form.send.button": "Post",
"post.form.content.field.placeholder": "Message",
"post.form.subject.field.placeholder": "Subject",
@@ -34,6 +40,7 @@
"profile.general.tab.number.of.posts.row.title": "Number of posts:",
"profile.general.tab.number.of.topics.row.title": "Number of topics created:",
"profile.general.tab.posts.db.address.row.title": "PostsDB:",
+ "profile.general.tab.polls.db.address.row.title": "PollsDB:",
"profile.general.tab.registration.date.row.title": "Member since:",
"profile.general.tab.save.info.button.title": "Save information",
"profile.general.tab.title": "General",
@@ -73,6 +80,8 @@
"topic.create.form.post.button": "Create Topic",
"topic.create.form.subject.field.label": "Topic subject",
"topic.create.form.subject.field.placeholder": "Subject",
+ "topic.create.form.add.poll.button": "Add Poll",
+ "topic.create.form.remove.poll.button": "Remove Poll",
"topic.list.row.topic.id": "#{{id}}",
"username.selector.error.username.empty.message": "Username is required",
"username.selector.error.username.taken.message": "The username {{username}} is already taken.",
diff --git a/packages/concordia-app/src/components/PollCreate/PollOption/index.jsx b/packages/concordia-app/src/components/PollCreate/PollOption/index.jsx
new file mode 100644
index 0000000..c64dc0f
--- /dev/null
+++ b/packages/concordia-app/src/components/PollCreate/PollOption/index.jsx
@@ -0,0 +1,50 @@
+import React, { memo } from 'react';
+import PropTypes from 'prop-types';
+import {
+ Button, Form, Icon, Input,
+} from 'semantic-ui-react';
+import { useTranslation } from 'react-i18next';
+import './styles.css';
+
+const PollOption = (props) => {
+ const {
+ id, removable, onChange, onRemove,
+ } = props;
+ const { t } = useTranslation();
+
+ return (
+
+
+ onChange(e, id)}
+ />
+ {removable
+ && (
+
+ )}
+
+ );
+};
+
+PollOption.propTypes = {
+ id: PropTypes.number.isRequired,
+ onChange: PropTypes.func,
+ onRemove: PropTypes.func,
+ removable: PropTypes.bool,
+};
+
+export default memo(PollOption);
diff --git a/packages/concordia-app/src/components/PollCreate/PollOption/styles.css b/packages/concordia-app/src/components/PollCreate/PollOption/styles.css
new file mode 100644
index 0000000..2516280
--- /dev/null
+++ b/packages/concordia-app/src/components/PollCreate/PollOption/styles.css
@@ -0,0 +1,4 @@
+.form-poll-option > .form-input{
+ width: 50% !important;
+ margin-right: 0.25em;
+}
diff --git a/packages/concordia-app/src/components/PollCreate/index.jsx b/packages/concordia-app/src/components/PollCreate/index.jsx
new file mode 100644
index 0000000..f631cdc
--- /dev/null
+++ b/packages/concordia-app/src/components/PollCreate/index.jsx
@@ -0,0 +1,190 @@
+import React, {
+ useMemo, useState, useCallback, useEffect, forwardRef, useImperativeHandle,
+} from 'react';
+import PropTypes from 'prop-types';
+import { useSelector } from 'react-redux';
+import { useTranslation } from 'react-i18next';
+import {
+ Button, Checkbox, Form, Icon, Input,
+} from 'semantic-ui-react';
+import { VOTING_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames';
+import { POLL_CREATED_EVENT } from 'concordia-shared/src/constants/contracts/events/VotingContractEvents';
+import { POLLS_DATABASE } from 'concordia-shared/src/constants/orbit/OrbitDatabases';
+import PollOption from './PollOption';
+import { breeze, drizzle } from '../../redux/store';
+import { TRANSACTION_ERROR, TRANSACTION_SUCCESS } from '../../constants/TransactionStatus';
+import './styles.css';
+import { POLL_OPTIONS, POLL_QUESTION } from '../../constants/orbit/PollsDatabaseKeys';
+import generateHash from '../../utils/hashUtils';
+
+const { contracts: { [VOTING_CONTRACT]: { methods: { createPoll } } } } = drizzle;
+const { orbit: { stores } } = breeze;
+
+const PollCreate = forwardRef((props, ref) => {
+ const { account, onChange, onCreated } = props;
+ const transactionStack = useSelector((state) => state.transactionStack);
+ const transactions = useSelector((state) => state.transactions);
+ const [createPollCacheSendStackId, setCreatePollCacheSendStackId] = useState('');
+ const [question, setQuestion] = useState('');
+ const [options, setOptions] = useState(
+ [{ id: 1 }, { id: 2 }],
+ );
+ const [optionValues, setOptionValues] = useState(
+ ['', ''],
+ );
+ const [optionsNextId, setOptionsNextId] = useState(3);
+ const [allowVoteChanges, setAllowVoteChanges] = useState(false);
+ const [creating, setCreating] = useState(false);
+ const [errored, setErrored] = useState(false);
+ const { t } = useTranslation();
+
+ const handlePollQuestionChange = useCallback((event) => {
+ const newQuestion = event.target.value.trim();
+ if (newQuestion !== question) setQuestion(newQuestion);
+ }, [question]);
+
+ const addOption = useCallback((e) => {
+ e.currentTarget.blur();
+ const newOptions = [...options, { id: optionsNextId, removable: true }];
+ const newOptionValues = [...optionValues, ''];
+ setOptionsNextId(optionsNextId + 1);
+ setOptions(newOptions);
+ setOptionValues(newOptionValues);
+ }, [optionValues, options, optionsNextId]);
+
+ const removeOption = useCallback((e, id) => {
+ e.currentTarget.blur();
+ const newOptions = [...options];
+ newOptions.splice(id - 1, 1);
+ const newOptionValues = [...optionValues];
+ newOptionValues.splice(id - 1, 1);
+ setOptions(newOptions);
+ setOptionValues(newOptionValues);
+ }, [optionValues, options]);
+
+ const handlePollOptionChange = useCallback((event, id) => {
+ const newValue = event.target.value.trim();
+ if (newValue !== optionValues[id - 1]) {
+ const newOptionValues = [...optionValues];
+ newOptionValues[id - 1] = newValue;
+ setOptionValues(newOptionValues);
+ }
+ }, [optionValues]);
+
+ const pollOptions = useMemo(() => options
+ .map((option, index) => {
+ const { id, removable } = option;
+ return (
+
+ );
+ }), [handlePollOptionChange, options, removeOption]);
+
+ useEffect(() => {
+ onChange({ question, optionValues });
+ }, [onChange, optionValues, question]);
+
+ const handleCheckboxChange = useCallback((event, data) => {
+ setAllowVoteChanges(data.checked);
+ }, []);
+
+ useImperativeHandle(ref, () => ({
+ createPoll(topicId) {
+ setCreating(true);
+ const dataHash = generateHash(JSON.stringify({ question, optionValues }));
+ setCreatePollCacheSendStackId(createPoll.cacheSend(
+ ...[topicId, options.length, dataHash, allowVoteChanges], { from: account },
+ ));
+ },
+ pollCreating() {
+ return creating;
+ },
+ pollErrored() {
+ return errored;
+ },
+ }));
+
+ useEffect(() => {
+ if (creating && transactionStack && transactionStack[createPollCacheSendStackId]
+ && transactions[transactionStack[createPollCacheSendStackId]]) {
+ if (transactions[transactionStack[createPollCacheSendStackId]].status === TRANSACTION_ERROR) {
+ setErrored(true);
+ setCreating(false);
+ onCreated(false);
+ } else if (transactions[transactionStack[createPollCacheSendStackId]].status === TRANSACTION_SUCCESS) {
+ const {
+ receipt: {
+ events: {
+ [POLL_CREATED_EVENT]: {
+ returnValues: {
+ topicID: topicId,
+ },
+ },
+ },
+ },
+ } = transactions[transactionStack[createPollCacheSendStackId]];
+
+ const pollsDb = Object.values(stores).find((store) => store.dbname === POLLS_DATABASE);
+
+ pollsDb
+ .put(topicId, { [POLL_QUESTION]: question, [POLL_OPTIONS]: optionValues })
+ .then(() => {
+ onCreated(topicId);
+ })
+ .catch((reason) => {
+ console.error(reason);
+ setErrored(true);
+ setCreating(false);
+ onCreated(false);
+ });
+ }
+ }
+ }, [createPollCacheSendStackId, creating, onCreated, optionValues, question, transactionStack, transactions]);
+
+ return useMemo(() => (
+
+
+
+
+
+
+
+
+ {pollOptions}
+
+
+ ), [addOption, handleCheckboxChange, handlePollQuestionChange, pollOptions, t]);
+});
+
+PollCreate.propTypes = {
+ onChange: PropTypes.func,
+ onCreated: PropTypes.func,
+};
+
+export default PollCreate;
diff --git a/packages/concordia-app/src/components/PollCreate/styles.css b/packages/concordia-app/src/components/PollCreate/styles.css
new file mode 100644
index 0000000..9fc624c
--- /dev/null
+++ b/packages/concordia-app/src/components/PollCreate/styles.css
@@ -0,0 +1,10 @@
+.poll-create {
+ padding-top: 1em;
+ padding-bottom: 1em;
+}
+
+.poll-create .checkbox > label, label:focus, label:hover{
+ color: white !important;
+ font-weight: 700;
+}
+
diff --git a/packages/concordia-app/src/components/PostList/PostVoting/index.jsx b/packages/concordia-app/src/components/PostList/PostVoting/index.jsx
index 52033d8..a4a780d 100644
--- a/packages/concordia-app/src/components/PostList/PostVoting/index.jsx
+++ b/packages/concordia-app/src/components/PostList/PostVoting/index.jsx
@@ -77,9 +77,9 @@ const PostVoting = (props) => {
if (voting) return;
setVoting(true);
- if ((ownVote === CHOICE_DEFAULT || ownVote === CHOICE_DOWN) && choice === CHOICE_UP) setVoteCacheSendStackId(upvote.cacheSend(...[postId], { from: userAccount }));
- else if ((ownVote === CHOICE_DEFAULT || ownVote === CHOICE_UP) && choice === CHOICE_DOWN) setVoteCacheSendStackId(downvote.cacheSend(...[postId], { from: userAccount }));
- else if ((ownVote === CHOICE_UP && choice === CHOICE_UP) || (ownVote === CHOICE_DOWN && choice === CHOICE_DOWN)) setVoteCacheSendStackId(unvote.cacheSend(...[postId], { from: userAccount }));
+ if ((ownVote === CHOICE_DEFAULT || ownVote === CHOICE_DOWN) && choice === CHOICE_UP) setVoteCacheSendStackId(upvote.cacheSend(postId, { from: userAccount }));
+ else if ((ownVote === CHOICE_DEFAULT || ownVote === CHOICE_UP) && choice === CHOICE_DOWN) setVoteCacheSendStackId(downvote.cacheSend(postId, { from: userAccount }));
+ else if ((ownVote === CHOICE_UP && choice === CHOICE_UP) || (ownVote === CHOICE_DOWN && choice === CHOICE_DOWN)) setVoteCacheSendStackId(unvote.cacheSend(postId, { from: userAccount }));
else setVoting(false);
}, [ownVote, postId, userAccount, voting]);
diff --git a/packages/concordia-app/src/constants/orbit/PollsDatabaseKeys.js b/packages/concordia-app/src/constants/orbit/PollsDatabaseKeys.js
new file mode 100644
index 0000000..b1f6c72
--- /dev/null
+++ b/packages/concordia-app/src/constants/orbit/PollsDatabaseKeys.js
@@ -0,0 +1,9 @@
+export const POLL_QUESTION = 'question';
+export const POLL_OPTIONS = 'options';
+
+const pollsDatabaseKeys = [
+ POLL_QUESTION,
+ POLL_OPTIONS,
+];
+
+export default pollsDatabaseKeys;
diff --git a/packages/concordia-app/src/redux/actions/contractEventActions.js b/packages/concordia-app/src/redux/actions/contractEventActions.js
index b736e31..11b340e 100644
--- a/packages/concordia-app/src/redux/actions/contractEventActions.js
+++ b/packages/concordia-app/src/redux/actions/contractEventActions.js
@@ -7,6 +7,9 @@ import {
import {
USER_VOTED_POST_EVENT,
} from 'concordia-shared/src/constants/contracts/events/PostVotingContractEvents';
+import {
+ POLL_CREATED_EVENT, USER_VOTED_POLL_EVENT
+} from 'concordia-shared/src/constants/contracts/events/VotingContractEvents';
export const FORUM_EVENT_USER_SIGNED_UP = 'FORUM_EVENT_USER_SIGNED_UP';
export const FORUM_EVENT_USERNAME_UPDATED = 'FORUM_EVENT_USERNAME_UPDATED';
@@ -15,12 +18,17 @@ export const FORUM_EVENT_POST_CREATED = 'FORUM_EVENT_POST_CREATED';
export const POST_VOTING_USER_VOTED_POST = 'POST_VOTING_USER_VOTED_POST';
+export const VOTING_POLL_CREATED = 'VOTING_POLL_CREATED';
+export const VOTING_USER_VOTED_POLL = 'VOTING_USER_VOTED_POLL';
+
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,
[USER_VOTED_POST_EVENT]: POST_VOTING_USER_VOTED_POST,
+ [POLL_CREATED_EVENT]: VOTING_POLL_CREATED,
+ [USER_VOTED_POLL_EVENT]: VOTING_USER_VOTED_POLL,
};
export default eventActionMap;
diff --git a/packages/concordia-app/src/utils/hashUtils.js b/packages/concordia-app/src/utils/hashUtils.js
new file mode 100644
index 0000000..3a6d269
--- /dev/null
+++ b/packages/concordia-app/src/utils/hashUtils.js
@@ -0,0 +1,7 @@
+import sha256 from 'crypto-js/sha256';
+
+function generateHash(message) {
+ return sha256(message).toString().substring(0, 16);
+}
+
+export default generateHash;
diff --git a/packages/concordia-app/src/views/Profile/GeneralTab/index.jsx b/packages/concordia-app/src/views/Profile/GeneralTab/index.jsx
index 0b710fa..eb956e3 100644
--- a/packages/concordia-app/src/views/Profile/GeneralTab/index.jsx
+++ b/packages/concordia-app/src/views/Profile/GeneralTab/index.jsx
@@ -23,6 +23,7 @@ const GeneralTab = (props) => {
const [userInfoOrbitAddress, setUserInfoOrbitAddress] = useState(null);
const [userTopicsOrbitAddress, setUserTopicsOrbitAddress] = useState(null);
const [userPostsOrbitAddress, setUserPostsOrbitAddress] = useState(null);
+ const [userPollsOrbitAddress, setUserPollsOrbitAddress] = useState(null);
const [profileMetadataFetched, setProfileMetadataFetched] = useState(false);
const [userAvatarUrl, setUserAvatarUrl] = useState(null);
const [userLocation, setUserLocation] = useState(null);
@@ -41,10 +42,11 @@ const GeneralTab = (props) => {
userAddress: profileAddress,
})))
.then((values) => {
- const [userOrbitAddress, topicsOrbitAddress, postsOrbitAddress] = values;
+ const [userOrbitAddress, topicsOrbitAddress, postsOrbitAddress, pollsOrbitAddress] = values;
setUserInfoOrbitAddress(userOrbitAddress);
setUserTopicsOrbitAddress(topicsOrbitAddress);
setUserPostsOrbitAddress(postsOrbitAddress);
+ setUserPollsOrbitAddress(pollsOrbitAddress);
const userFound = users
.find((user) => user.id === userOrbitAddress);
@@ -141,6 +143,12 @@ const GeneralTab = (props) => {
{userPostsOrbitAddress || ()}
+
+ {t('profile.general.tab.polls.db.address.row.title')}
+
+ {userPollsOrbitAddress || ()}
+
+
{t('profile.general.tab.number.of.topics.row.title')}
@@ -192,7 +200,7 @@ const GeneralTab = (props) => {
{isSelf && editInformationModal}
>
- ), [editInformationModal, isSelf, numberOfPosts, numberOfTopics, profileAddress, profileMetadataFetched, t, userAvatarUrl, userInfoOrbitAddress, userLocationCell, userPostsOrbitAddress, userRegistrationTimestamp, userTopicsOrbitAddress, username]);
+ ), [editInformationModal, isSelf, numberOfPosts, numberOfTopics, profileAddress, profileMetadataFetched, t, userAvatarUrl, userInfoOrbitAddress, userLocationCell, userPollsOrbitAddress, userPostsOrbitAddress, userRegistrationTimestamp, userTopicsOrbitAddress, username]);
};
GeneralTab.defaultProps = {
diff --git a/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx b/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx
index f9867a2..620339c 100644
--- a/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx
+++ b/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx
@@ -1,5 +1,5 @@
import React, {
- useCallback, useEffect, useState,
+ useCallback, useEffect, useRef, useState,
} from 'react';
import {
Button, Container, Form, Header, Icon, Input, TextArea,
@@ -15,6 +15,7 @@ import { TRANSACTION_ERROR, TRANSACTION_SUCCESS } from '../../../constants/Trans
import { TOPIC_SUBJECT } from '../../../constants/orbit/TopicsDatabaseKeys';
import { POST_CONTENT } from '../../../constants/orbit/PostsDatabaseKeys';
import './styles.css';
+import PollCreate from '../../../components/PollCreate';
const { contracts: { [FORUM_CONTRACT]: { methods: { createTopic } } } } = drizzle;
const { orbit: { stores } } = breeze;
@@ -25,9 +26,12 @@ const TopicCreate = (props) => {
const transactions = useSelector((state) => state.transactions);
const [subjectInput, setSubjectInput] = useState('');
const [contentInput, setContentInput] = useState('');
+ const [newTopicId, setNewTopicId] = useState(null);
const [createTopicCacheSendStackId, setCreateTopicCacheSendStackId] = useState('');
const [posting, setPosting] = useState(false);
-
+ const [pollAdded, setPollAdded] = useState(false);
+ const [pollFilled, setPollFilled] = useState(false);
+ const pollCreateRef = useRef();
const history = useHistory();
const { t } = useTranslation();
@@ -48,9 +52,18 @@ const TopicCreate = (props) => {
}
}, [posting]);
+ const goToTopic = useCallback((topicId) => {
+ if (topicId) history.push(`/topics/${topicId}`);
+ else {
+ console.error('Error creating poll!');
+ history.push(`/topics/${newTopicId}`);
+ }
+ }, [history, newTopicId]);
+
useEffect(() => {
if (posting && transactionStack && transactionStack[createTopicCacheSendStackId]
- && transactions[transactionStack[createTopicCacheSendStackId]]) {
+ && transactions[transactionStack[createTopicCacheSendStackId]]
+ && (!pollAdded || (!pollCreateRef.current.pollCreating() && !pollCreateRef.current.pollErrored()))) {
if (transactions[transactionStack[createTopicCacheSendStackId]].status === TRANSACTION_ERROR) {
setPosting(false);
} else if (transactions[transactionStack[createTopicCacheSendStackId]].status === TRANSACTION_SUCCESS) {
@@ -67,6 +80,12 @@ const TopicCreate = (props) => {
},
} = transactions[transactionStack[createTopicCacheSendStackId]];
+ setNewTopicId(topicId);
+
+ if (pollAdded) {
+ pollCreateRef.current.createPoll(topicId);
+ }
+
const topicsDb = Object.values(stores).find((store) => store.dbname === TOPICS_DATABASE);
const postsDb = Object.values(stores).find((store) => store.dbname === POSTS_DATABASE);
@@ -77,14 +96,15 @@ const TopicCreate = (props) => {
[POST_CONTENT]: contentInput,
}))
.then(() => {
- history.push(`/topics/${topicId}`);
+ if (!pollAdded) goToTopic();
})
.catch((reason) => {
console.error(reason);
});
}
}
- }, [createTopicCacheSendStackId, history, contentInput, posting, subjectInput, transactionStack, transactions]);
+ }, [createTopicCacheSendStackId,
+ contentInput, posting, subjectInput, transactionStack, transactions, pollAdded, goToTopic]);
const validateAndPost = useCallback(() => {
if (subjectInput === '' || contentInput === '') {
@@ -95,8 +115,24 @@ const TopicCreate = (props) => {
setCreateTopicCacheSendStackId(createTopic.cacheSend(...[], { from: account }));
}, [account, contentInput, subjectInput]);
+ const togglePollCreate = useCallback((e) => {
+ e.currentTarget.blur();
+ if (!pollAdded) {
+ setPollAdded(true);
+ } else {
+ setPollAdded(false);
+ }
+ }, [pollAdded]);
+
+ const handlePollCreateChanges = useCallback((pollCreateState) => {
+ const { question, optionValues } = pollCreateState;
+ if (question !== '' && !optionValues.includes('')) {
+ setPollFilled(true);
+ } else setPollFilled(false);
+ }, []);
+
return (
-
+
@@ -126,13 +162,43 @@ const TopicCreate = (props) => {
onChange={handleSubjectInputChange}
/>
+
+ {pollAdded && (
+
+ )}
-
);
diff --git a/packages/concordia-app/src/views/Topic/TopicCreate/styles.css b/packages/concordia-app/src/views/Topic/TopicCreate/styles.css
index 2bd6916..b8cdfec 100644
--- a/packages/concordia-app/src/views/Topic/TopicCreate/styles.css
+++ b/packages/concordia-app/src/views/Topic/TopicCreate/styles.css
@@ -17,5 +17,5 @@
#create-topic-button {
float: right;
- margin: 1rem 0 4rem 0;
+ margin: 0 0 4rem 0;
}
diff --git a/packages/concordia-pinner/src/utils/orbitUtils.js b/packages/concordia-pinner/src/utils/orbitUtils.js
index d1c3326..c8e4404 100644
--- a/packages/concordia-pinner/src/utils/orbitUtils.js
+++ b/packages/concordia-pinner/src/utils/orbitUtils.js
@@ -2,6 +2,7 @@ import OrbitDB from 'orbit-db';
import Identities from 'orbit-db-identity-provider';
import { EthereumContractIdentityProvider } from '@ezerous/eth-identity-provider';
import Web3 from 'web3';
+import { databaseNames } from 'concordia-shared/src/constants/orbit/OrbitDatabases';
import { ORBIT_DIRECTORY_DEFAULT } from '../constants';
import { logger } from './logger';
@@ -31,11 +32,7 @@ export const createOrbitInstance = async (ipfs, contractAddress) => {
};
export const getPeerDatabases = async (orbit, userAddresses) => Promise.all(userAddresses
- .flatMap((userAddress) => [
- determineKVAddress({ orbit, dbName: 'user', userAddress }),
- determineKVAddress({ orbit, dbName: 'posts', userAddress }),
- determineKVAddress({ orbit, dbName: 'topics', userAddress }),
- ]));
+ .flatMap((userAddress) => databaseNames.map((dbName) => determineKVAddress({ orbit, dbName, userAddress }))));
export const openKVDBs = async (orbit, databases) => {
databases
diff --git a/packages/concordia-shared/src/constants/contracts/events/VotingContractEvents.js b/packages/concordia-shared/src/constants/contracts/events/VotingContractEvents.js
new file mode 100644
index 0000000..8ab8a85
--- /dev/null
+++ b/packages/concordia-shared/src/constants/contracts/events/VotingContractEvents.js
@@ -0,0 +1,13 @@
+const POLL_CREATED_EVENT = 'PollCreated';
+const USER_VOTED_POLL_EVENT = 'UserVotedPoll';
+
+const votingContractEvents = Object.freeze([
+ POLL_CREATED_EVENT,
+ USER_VOTED_POLL_EVENT,
+]);
+
+module.exports = {
+ POLL_CREATED_EVENT,
+ USER_VOTED_POLL_EVENT,
+ votingContractEvents,
+};
diff --git a/packages/concordia-shared/src/constants/contracts/events/index.js b/packages/concordia-shared/src/constants/contracts/events/index.js
index ddc86bd..91b2fb4 100644
--- a/packages/concordia-shared/src/constants/contracts/events/index.js
+++ b/packages/concordia-shared/src/constants/contracts/events/index.js
@@ -1,10 +1,12 @@
const { forumContractEvents } = require('./ForumContractEvents');
const { postVotingContractEvents } = require('./PostVotingContractEvents');
-const { FORUM_CONTRACT, POST_VOTING_CONTRACT } = require('../ContractNames');
+const { votingContractEvents } = require('./VotingContractEvents');
+const { FORUM_CONTRACT, POST_VOTING_CONTRACT, VOTING_CONTRACT } = require('../ContractNames');
const appEvents = Object.freeze({
[FORUM_CONTRACT]: forumContractEvents,
[POST_VOTING_CONTRACT]: postVotingContractEvents,
+ [VOTING_CONTRACT]: votingContractEvents,
});
module.exports = appEvents;
diff --git a/packages/concordia-shared/src/constants/orbit/OrbitDatabases.js b/packages/concordia-shared/src/constants/orbit/OrbitDatabases.js
index 75048f6..085288a 100644
--- a/packages/concordia-shared/src/constants/orbit/OrbitDatabases.js
+++ b/packages/concordia-shared/src/constants/orbit/OrbitDatabases.js
@@ -1,6 +1,7 @@
const USER_DATABASE = 'user';
const TOPICS_DATABASE = 'topics';
const POSTS_DATABASE = 'posts';
+const POLLS_DATABASE = 'polls';
const databases = [
{
@@ -15,11 +16,19 @@ const databases = [
address: POSTS_DATABASE,
type: 'keyvalue',
},
+ {
+ address: POLLS_DATABASE,
+ type: 'keyvalue',
+ },
];
+const databaseNames = [USER_DATABASE, TOPICS_DATABASE, POSTS_DATABASE, POLLS_DATABASE];
+
module.exports = Object.freeze({
USER_DATABASE,
TOPICS_DATABASE,
POSTS_DATABASE,
+ POLLS_DATABASE,
databases,
+ databaseNames,
});
diff --git a/yarn.lock b/yarn.lock
index 4dc7c8e..54416c0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5071,6 +5071,11 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
+crypto-js@~4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.0.0.tgz#2904ab2677a9d042856a2ea2ef80de92e4a36dcc"
+ integrity sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==
+
crypto-random-string@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"