From 291a2b729bb37c20efb0dafbe57c14e5120716a4 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Fri, 18 May 2018 16:46:52 +0300 Subject: [PATCH] OrbitDB init --- contracts/Forum.sol | 21 +++++- package.json | 2 + src/containers/LoadingContainer.js | 96 ++++++++++++++++++++++++ src/containers/UsernameFormContainer.js | 12 ++- src/index.js | 4 +- src/reducer.js | 2 + src/resources/ipfs_logo.png | Bin 0 -> 1660 bytes src/store.js | 2 +- src/{ => util}/drizzleOptions.js | 2 +- src/util/orbit.js | 32 ++++++++ src/util/orbitReducer.js | 21 ++++++ 11 files changed, 183 insertions(+), 11 deletions(-) create mode 100644 src/containers/LoadingContainer.js create mode 100644 src/resources/ipfs_logo.png rename src/{ => util}/drizzleOptions.js (79%) create mode 100644 src/util/orbit.js create mode 100644 src/util/orbitReducer.js diff --git a/contracts/Forum.sol b/contracts/Forum.sol index 0fc71f3..693514b 100644 --- a/contracts/Forum.sol +++ b/contracts/Forum.sol @@ -2,10 +2,13 @@ pragma solidity ^0.4.23; contract Forum { - //----------------------------------------AUTHENTICATION---------------------------------------- + //----------------------------------------USER---------------------------------------- struct User { string username; // TODO: set an upper bound instead of arbitrary string - // TODO: orbitDBAddress; + string orbitMainDB; // TODO: set an upper bound instead of arbitrary string + string orbitTopicsDB; + string orbitPostsDB; + uint[] topicIDs; // IDs of the topics the user created uint[] postIDs; // IDs of the posts the user created bool signedUp; // Helper variable for hasUserSignedUp() @@ -17,10 +20,10 @@ contract Forum { event UserSignedUp(string username, address userAddress); event UsernameUpdated(string newName, string oldName,address userAddress); - function signUp(string username) public returns (bool) { + function signUp(string username, string orbitMainDB, string orbitTopicsDB, string orbitPostsDB) public returns (bool) { require (!hasUserSignedUp(msg.sender), "User has already signed up."); require(!isUserNameTaken(username), "Username is already taken."); - users[msg.sender] = User(username, new uint[](0), new uint[](0), true); + users[msg.sender] = User(username, orbitMainDB, orbitTopicsDB, orbitPostsDB, new uint[](0), new uint[](0), true); userAddresses[username] = msg.sender; emit UserSignedUp(username, msg.sender); return true; @@ -55,7 +58,17 @@ contract Forum { return false; } + function getOrbitMainDB(address userAddress) public view returns (string) { + return users[userAddress].orbitMainDB; + } + function getOrbitTopicsDB(address userAddress) public view returns (string) { + return users[userAddress].orbitTopicsDB; + } + + function getOrbitPostsDB(address userAddress) public view returns (string) { + return users[userAddress].orbitPostsDB; + } //----------------------------------------POSTING---------------------------------------- struct Topic { uint topicID; diff --git a/package.json b/package.json index 0de2376..f0f3b4c 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ "drizzle-react": "^1.1.1", "drizzle-react-components": "^1.1.0", "eth-block-tracker-es5": "^2.3.2", + "ipfs":"^0.28.2", + "orbit-db":"^0.19.7", "prop-types": "^15.6.1", "react": "^16.3.2", "react-dom": "^16.3.2", diff --git a/src/containers/LoadingContainer.js b/src/containers/LoadingContainer.js new file mode 100644 index 0000000..71720db --- /dev/null +++ b/src/containers/LoadingContainer.js @@ -0,0 +1,96 @@ +import { drizzleConnect } from 'drizzle-react' +import React, { Children, Component } from 'react' +import PropTypes from 'prop-types' + +import ipfs_logo from './../resources/ipfs_logo.png'; + +/* + * Create component. + */ + +class LoadingContainer extends Component { + render() { + if (this.props.web3.status === 'failed') + { + if (this.props.errorComp) { + return this.props.errorComp + } + + return( +
+
+
+

⚠️

+

This browser has no connection to the Ethereum network. Please use the Chrome/FireFox extension MetaMask, or dedicated Ethereum browsers Mist or Parity.

+
+
+
+ ) + } + + if (this.props.web3.status === 'initialized' && Object.keys(this.props.accounts).length === 0) + { + return( +
+
+
+

🦊

+

We can't find any Ethereum accounts! Please check and make sure Metamask or you browser are pointed at the correct network and your account is unlocked.

+
+
+
+ ) + } + + if (!this.props.orbitDB.initialized) + { + return( +
+
+
+ ipfs_logo +

Initializing IPFS...

+
+
+
+ ) + } + + if (this.props.drizzleStatus.initialized) + return Children.only(this.props.children); + + if (this.props.loadingComp) + return this.props.loadingComp; + + + return( +
+
+
+

⚙️

+

Loading dapp...

+
+
+
+ ) + } +} + +LoadingContainer.contextTypes = { + drizzle: PropTypes.object +}; + +/* + * Export connected component. + */ + +const mapStateToProps = state => { + return { + accounts: state.accounts, + drizzleStatus: state.drizzleStatus, + web3: state.web3, + orbitDB: state.orbitDB + } +}; + +export default drizzleConnect(LoadingContainer, mapStateToProps) \ No newline at end of file diff --git a/src/containers/UsernameFormContainer.js b/src/containers/UsernameFormContainer.js index 9b9d59d..bf5cdfa 100644 --- a/src/containers/UsernameFormContainer.js +++ b/src/containers/UsernameFormContainer.js @@ -1,5 +1,8 @@ import { drizzleConnect } from 'drizzle-react' import React, { Component } from 'react' + +import { createDatabases } from './../util/orbit' + import PropTypes from 'prop-types' const contract = "Forum"; @@ -17,12 +20,15 @@ class UsernameFormContainer extends Component { this.state = {usernameInput:''}; } - handleSubmit() { - this.setState({usernameInput:''}); + async handleSubmit() { if(this.props.user.hasSignedUp) this.contracts[contract].methods[updateUsernameMethod].cacheSend(...[this.state.usernameInput]); else - this.contracts[contract].methods[signUpMethod].cacheSend(...[this.state.usernameInput]); + { + const orbitdb = await createDatabases(); + this.contracts[contract].methods[signUpMethod].cacheSend(...[this.state.usernameInput, orbitdb.mainDB, orbitdb.topicsDB, orbitdb.postsDB]); + } + } diff --git a/src/index.js b/src/index.js index 7877e8d..92cb377 100644 --- a/src/index.js +++ b/src/index.js @@ -7,10 +7,10 @@ import { DrizzleProvider } from 'drizzle-react' // Layouts import App from './App' import HomeContainer from './layouts/home/HomeContainer' -import { LoadingContainer } from 'drizzle-react-components' +import LoadingContainer from './containers/LoadingContainer' import store from './store' -import drizzleOptions from './drizzleOptions' +import drizzleOptions from './util/drizzleOptions' import './css/index.css' diff --git a/src/reducer.js b/src/reducer.js index d49b26d..bf815d1 100644 --- a/src/reducer.js +++ b/src/reducer.js @@ -2,10 +2,12 @@ import { combineReducers } from 'redux' import { routerReducer } from 'react-router-redux' import { drizzleReducers } from 'drizzle' import userReducer from "./userReducer"; +import orbitReducer from "./util/orbitReducer"; const reducer = combineReducers({ routing: routerReducer, user: userReducer, + orbitDB: orbitReducer, ...drizzleReducers }); diff --git a/src/resources/ipfs_logo.png b/src/resources/ipfs_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2aa68e8c69e938c7162aa06a2547a7ee417167cd GIT binary patch literal 1660 zcmV-?27~#DP)C0001xP)t-s|NsBs z?e6aL^Y{1no6XKmq^G>t*{;*nOQ54lo}p>6v&G)vNt~ZerKpw2%6YxOoyp5}wz$yc z=3J(!g2Tj6s;ySHx~j>_UB=2|)7N3n(pkR2QJbE#)YW6s*4gXpRI|2&y1b3U#I?=N z-0A6F$jno(vy;EUMwFLosjH*G!j8eiywTE!w6@CC)o``9FmaDe00004bW%=J00000 zvy*0;00001VoOIv0Eh)0NB{r;32;bRa{vGUNB{r;NB~C3Yd!z~1rtd`K~#9!?VH(F z<2Vq8Lk58aazn$!#7-weGm}8i*6;szV_8cq+mfoZm~-Z&uDBqs&-#CBv8z_Aw74cW ziC0L9TS6JRyZWs3_g(rfc=hE|(yt!~XDaC9^7*eTHVDENw!$r8cJS)!db#vZ&*S|4 zC@f}$U#0jPZ2?Ye=>-0=MEXY}hkV<#bw|QkwQHJ2B9L$QrPJ?O|L9SXw2MO*@~?Iy zxgLHgnf|vsdHb&_s})mj!SP@Aw_)HqvwiU zZw1Q##OD7?-hCA#{;UEm~;>@&mkme|nZPPlEV%9OXnx|AC6nGKg=- zPL3$V3hy+R_;zS3{OeD@&ndng(hAHwE9mWZjh%O4u?<*3iw|6MW5R2NcfHFmF#P91 zkSXS@@IsaY=;C9tPVdbT>r^iP(VS?x2OxU&3x!-A!vG~_0TDH4U;xGd+h1I4$uPeU zKy3k2wgJtiI1cfU*Awarql~?9y08KC?r1Dl7;~EDO+PloeKIpp@Yi|?j#5xMlRh7 zqbGl$B>*7Z3by$6xgG?NW(9}%IDl^Pu&n@}6_ogl&9g%R#L;S~1LXZk|EtOpe>$hb z0mLbLI5k2RYPI=f9%u}JSw)oMVgbfhm=7L4*T(}ijlED?!_Ht6MIwN)!hFEaG)VxHbsqHOX9X||^*B9v zxl9I_+vqdIF(MtHIZRbR9IF4P0I!PzG}DOyv3Jh_P*0u##Lhhjz(fOt0$Bhia{=O~ zc>o%FDnK3N^8gIr`4HTTgiHYEmu}d%Ik^CuV}$-$0k&!zZ~?dgTmUWr7k~>uE&#Sc zzLAXt5SuC22MgR7L;1*_);0BmDRI#;5iIaJgd1W2uKehGZH4gjQ< z^@@1&7TEa#G88saF+MG091KD$y44h!eIpm zK#5+L`4*2^09|~NF1{UeR+s@O)#M^#+U7F>DB0#CV%+F71}NO_f1AP5(9)-_nd|nM&zu!J3y@=b6fZSzUbYtR6wNJaie;09q_OB3bTmS$7 zC3HntbYx+4WjbSWWnpw>05UK!I4v+WEipJ$FgH3iH##&kEig4YFfg;&7E%BJ03~!q zSaf7zbY(hiZ)9m^c>ppnF*q$SH7zkXR4_L>H8(mmGc7PRIxsN8g|6-Z0000 { + store.dispatch({type: "IPFS_READY"}); +}); + + +async function createDatabases() { + const orbitdb = new OrbitDB(ipfs); + const topicsDB = await orbitdb.keyvalue('topics'); + const postsDB = await orbitdb.keyvalue('posts'); + console.log("OrbitDBs created successfully!"); + return {mainDB: orbitdb.id, topicsDB: topicsDB.address.toString(), postsDB: postsDB.address.toString()}; //TODO: regex in the latter two +} + +export { createDatabases } \ No newline at end of file diff --git a/src/util/orbitReducer.js b/src/util/orbitReducer.js new file mode 100644 index 0000000..dd6bbbb --- /dev/null +++ b/src/util/orbitReducer.js @@ -0,0 +1,21 @@ +const initialState = { + initialized: false, + databasesReady: false +}; + +const orbitReducer = (state = initialState, action) => { + switch (action.type) { + case 'IPFS_READY': + return { + initialized: true + }; + case 'DATABASES_CREATED': + return { + databasesReady: true + }; + default: + return state + } +}; + +export default orbitReducer