Browse Source

OrbitDB improvements

develop
Ezerous 7 years ago
parent
commit
0a48adeac9
  1. 22
      contracts/Forum.sol
  2. 5
      package.json
  3. 2
      src/containers/LoadingContainer.js
  4. 16
      src/contractReducer.js
  5. 19
      src/contractSaga.js
  6. 3
      src/layouts/home/HomeContainer.js
  7. 2
      src/reducer.js
  8. 4
      src/rootSaga.js
  9. 27
      src/userSaga.js
  10. 25
      src/util/orbit.js
  11. 26
      src/util/orbitReducer.js
  12. 42
      src/util/orbitSaga.js

22
contracts/Forum.sol

@ -80,17 +80,27 @@ contract Forum {
return users[userAddress].orbitdb.postsDB; return users[userAddress].orbitdb.postsDB;
} }
function getOrbitPublicKey() public view returns (string) { function getOrbitPublicKey(address userAddress) public view returns (string) {
require (hasUserSignedUp(msg.sender), "User hasn't signed up."); require (hasUserSignedUp(userAddress), "User hasn't signed up.");
return users[msg.sender].orbitdb.publicKey; return users[userAddress].orbitdb.publicKey;
} }
//TODO: encrypt using Metamask in the future //TODO: encrypt using Metamask in the future
function getOrbitPrivateKey() public view returns (string) { function getOrbitPrivateKey(address userAddress) public view returns (string) {
require (hasUserSignedUp(msg.sender), "User hasn't signed up."); require (hasUserSignedUp(userAddress), "User hasn't signed up.");
return users[msg.sender].orbitdb.privateKey; return users[userAddress].orbitdb.privateKey;
} }
function getOrbitDBInfo(address userAddress) public view returns (string, string, string, string, string) {
require (hasUserSignedUp(userAddress), "User hasn't signed up.");
return (
users[userAddress].orbitdb.id,
users[userAddress].orbitdb.topicsDB,
users[userAddress].orbitdb.postsDB,
users[userAddress].orbitdb.publicKey,
users[userAddress].orbitdb.privateKey
);
}
//----------------------------------------POSTING---------------------------------------- //----------------------------------------POSTING----------------------------------------

5
package.json

@ -11,8 +11,9 @@
"drizzle-react": "^1.1.1", "drizzle-react": "^1.1.1",
"drizzle-react-components": "^1.1.0", "drizzle-react-components": "^1.1.0",
"eth-block-tracker-es5": "^2.3.2", "eth-block-tracker-es5": "^2.3.2",
"ipfs":"^0.28.2", "ipfs": "^0.28.2",
"orbit-db":"^0.19.7", "orbit-db": "^0.19.7",
"orbit-db-keystore": "^0.1.0",
"prop-types": "^15.6.1", "prop-types": "^15.6.1",
"react": "^16.3.2", "react": "^16.3.2",
"react-dom": "^16.3.2", "react-dom": "^16.3.2",

2
src/containers/LoadingContainer.js

@ -42,7 +42,7 @@ class LoadingContainer extends Component {
) )
} }
if (!this.props.orbitDB.initialized) if (!this.props.orbitDB.ipfsInitialized)
{ {
return( return(
<main className="container loading-screen"> <main className="container loading-screen">

16
src/contractReducer.js

@ -0,0 +1,16 @@
const initialState = {
grabbed: false
};
const contractReducer = (state = initialState, action) => {
switch (action.type) {
case 'CONTRACT_GRABBED':
return {
grabbed: true,
};
default:
return state
}
};
export default contractReducer

19
src/contractSaga.js

@ -0,0 +1,19 @@
import { put, takeLatest } from 'redux-saga/effects'
let contractGrabbed=false;
let grabbedContract;
function* grabContract({contract}) {
if(!contractGrabbed)
{
contractGrabbed=true;
grabbedContract = contract;
yield put({type: 'CONTRACT_GRABBED', ...[]});
}
}
function* contractSaga() {
yield takeLatest('LISTEN_FOR_EVENT', grabContract);
}
export { contractSaga, grabbedContract };

3
src/layouts/home/HomeContainer.js

@ -14,6 +14,8 @@ class Home extends Component {
<div className="pure-u-1-1"> <div className="pure-u-1-1">
<h2>Account</h2> <h2>Account</h2>
<p><strong>Username</strong>: {this.props.user.username}</p> <p><strong>Username</strong>: {this.props.user.username}</p>
<p><strong>Account</strong>: {this.props.user.address}</p>
<p><strong>OrbitDB</strong>: {this.props.orbitDB.id}</p>
<UsernameFormContainer/> <UsernameFormContainer/>
<br/><br/> <br/><br/>
</div> </div>
@ -29,6 +31,7 @@ const mapStateToProps = state => {
accounts: state.accounts, accounts: state.accounts,
Forum: state.contracts.Forum, Forum: state.contracts.Forum,
user: state.user, user: state.user,
orbitDB: state.orbitDB,
drizzleStatus: state.drizzleStatus drizzleStatus: state.drizzleStatus
} }
}; };

2
src/reducer.js

@ -2,12 +2,14 @@ import { combineReducers } from 'redux'
import { routerReducer } from 'react-router-redux' import { routerReducer } from 'react-router-redux'
import { drizzleReducers } from 'drizzle' import { drizzleReducers } from 'drizzle'
import userReducer from "./userReducer"; import userReducer from "./userReducer";
import contractReducer from "./contractReducer";
import orbitReducer from "./util/orbitReducer"; import orbitReducer from "./util/orbitReducer";
const reducer = combineReducers({ const reducer = combineReducers({
routing: routerReducer, routing: routerReducer,
user: userReducer, user: userReducer,
orbitDB: orbitReducer, orbitDB: orbitReducer,
forumContract: contractReducer,
...drizzleReducers ...drizzleReducers
}); });

4
src/rootSaga.js

@ -1,9 +1,11 @@
import { all, fork } from 'redux-saga/effects' import { all, fork } from 'redux-saga/effects'
import { drizzleSagas } from 'drizzle' import { drizzleSagas } from 'drizzle'
import { contractSaga } from "./contractSaga";
import userSaga from "./userSaga"; import userSaga from "./userSaga";
import orbitSaga from "./util/orbitSaga";
export default function* root() { export default function* root() {
let sagas = [...drizzleSagas,userSaga]; let sagas = [...drizzleSagas,userSaga,orbitSaga,contractSaga];
yield all( yield all(
sagas.map(saga => fork(saga)) sagas.map(saga => fork(saga))
) )

27
src/userSaga.js

@ -1,19 +1,18 @@
import { call, put, select, takeLatest, takeEvery } from 'redux-saga/effects' import { call, put, select, takeLatest, takeEvery } from 'redux-saga/effects'
import {grabbedContract as contract} from "./contractSaga";
const contractWasGrabbed = (state) => state.forumContract.grabbed;
const accounts = (state) => state.accounts; const accounts = (state) => state.accounts;
let account; let account;
let initFlag = false; let initFlag = false;
let forumContract;
let contractGrabbed = false;
function* initUser() { function* initUser() {
if(!initFlag) if(!initFlag)
{ {
while(true) while(true)
if(contractGrabbed) if(yield select(contractWasGrabbed))
{ {
yield call(getUserData); yield call(getUserData);
initFlag=true; initFlag=true;
@ -22,13 +21,6 @@ function* initUser() {
} }
} }
function grabContract({contract}) {
if(!contractGrabbed)
{
forumContract = contract;
contractGrabbed=true;
}
}
function* updateUserData() { function* updateUserData() {
if(initFlag) if(initFlag)
@ -37,14 +29,18 @@ function* updateUserData() {
function* getUserData() { function* getUserData() {
account = (yield select(accounts))[0]; const currentAccount = (yield select(accounts))[0];
forumContract.methods["hasUserSignedUp"].cacheCall(...[account]); if(currentAccount!==account)
const txObj1 = yield call(forumContract.methods["hasUserSignedUp"], ...[account]); {
account = currentAccount;
yield put({type: 'ACCOUNT_CHANGED', ...[]});
}
const txObj1 = yield call(contract.methods["hasUserSignedUp"], ...[account]);
try { try {
const callResult = yield call(txObj1.call, {address:account}); const callResult = yield call(txObj1.call, {address:account});
if(callResult) if(callResult)
{ {
const txObj2 = yield call(forumContract.methods["getUsername"], ...[account]); const txObj2 = yield call(contract.methods["getUsername"], ...[account]);
const username = yield call(txObj2.call, {address:account}); const username = yield call(txObj2.call, {address:account});
const dispatchArgs = { const dispatchArgs = {
address: account, address: account,
@ -67,7 +63,6 @@ function* getUserData() {
function* userSaga() { function* userSaga() {
yield takeLatest('LISTEN_FOR_EVENT', grabContract);
yield takeLatest("DRIZZLE_INITIALIZED", initUser); yield takeLatest("DRIZZLE_INITIALIZED", initUser);
yield takeEvery("ACCOUNTS_FETCHED", updateUserData); yield takeEvery("ACCOUNTS_FETCHED", updateUserData);
} }

25
src/util/orbit.js

@ -1,6 +1,7 @@
import IPFS from 'ipfs'; import IPFS from 'ipfs';
import OrbitDB from 'orbit-db'; import OrbitDB from 'orbit-db';
import Keystore from 'orbit-db-keystore';
import path from 'path';
import store from './../store'; import store from './../store';
// OrbitDB uses Pubsub which is an experimental feature // OrbitDB uses Pubsub which is an experimental feature
@ -17,7 +18,7 @@ const ipfsOptions = {
const ipfs = new IPFS(ipfsOptions); const ipfs = new IPFS(ipfsOptions);
ipfs.on('ready', async () => { ipfs.on('ready', async () => {
store.dispatch({type: "IPFS_READY"}); store.dispatch({type: "IPFS_INITIALIZED"});
}); });
@ -25,9 +26,25 @@ async function createDatabases() {
const orbitdb = new OrbitDB(ipfs); const orbitdb = new OrbitDB(ipfs);
const topicsDB = await orbitdb.keyvalue('topics'); const topicsDB = await orbitdb.keyvalue('topics');
const postsDB = await orbitdb.keyvalue('posts'); const postsDB = await orbitdb.keyvalue('posts');
console.log("OrbitDBs created successfully!"); store.dispatch({type: "DATABASES_CREATED", id: orbitdb.id});
return {id: orbitdb.id, topicsDB: topicsDB.address.root, postsDB: postsDB.address.root, return {id: orbitdb.id, topicsDB: topicsDB.address.root, postsDB: postsDB.address.root,
publicKey: orbitdb.key.getPublic('hex'), privateKey:orbitdb.key.getPrivate('hex')}; publicKey: orbitdb.key.getPublic('hex'), privateKey:orbitdb.key.getPrivate('hex')};
} }
export { createDatabases } async function loadDatabases(id,topicsDB, postsDB,publicKey,privateKey) { //TODO: does this work? does IPFS need reinitializng?
let directory = "./orbitdb";
let keystore = Keystore.create(path.join(directory, id, '/keystore'));
keystore._storage.setItem(id, JSON.stringify({
publicKey: publicKey,
privateKey: privateKey
}));
const orbitdb = new OrbitDB(ipfs,directory,{peerId:id, keystore:keystore});
await orbitdb.keyvalue('/orbitdb/' + topicsDB +'/topics');
await orbitdb.keyvalue('/orbitdb/' + postsDB +'/posts');
//todo: loadedDBs.load() (?)
store.dispatch({type: "DATABASES_LOADED", id: orbitdb.id});
}
export { createDatabases, loadDatabases }

26
src/util/orbitReducer.js

@ -1,17 +1,33 @@
const initialState = { const initialState = {
initialized: false, ipfsInitialized: false,
databasesReady: false ready: false,
id: null
}; };
const orbitReducer = (state = initialState, action) => { const orbitReducer = (state = initialState, action) => {
switch (action.type) { switch (action.type) {
case 'IPFS_READY': case 'IPFS_INITIALIZED':
return { return {
initialized: true ...state,
ipfsInitialized: true
}; };
case 'DATABASES_CREATED': case 'DATABASES_CREATED':
return { return {
databasesReady: true ...state,
ready: true,
id: action.id
};
case 'DATABASES_LOADED':
return {
...state,
ready: true,
id: action.id
};
case 'DATABASES_NOT_READY':
return {
...state,
ready: false,
id: null
}; };
default: default:
return state return state

42
src/util/orbitSaga.js

@ -0,0 +1,42 @@
import { loadDatabases } from './../util/orbit'
import { call, put, select, takeLatest } from 'redux-saga/effects'
import {grabbedContract as contract} from "../contractSaga";
const accounts = (state) => state.accounts;
let latestAccount;
function* getOrbitDBInfo() {
yield put({type: 'ORRBIT_GETTING_INFO', ...[]});
const account = (yield select(accounts))[0];
if(account!==latestAccount)
{
console.log("Deleting local storage..");
localStorage.clear();
const txObj1 = yield call(contract.methods["hasUserSignedUp"], ...[account]);
try {
const callResult = yield call(txObj1.call, {address:account});
if(callResult) {
const txObj2 = yield call(contract.methods["getOrbitDBInfo"], ...[account]);
const info = yield call(txObj2.call, {address: account});
//TODO: update localStorage OrbitDB stuff
yield call(loadDatabases, info[0], info[1], info[2],info[3], info[4]);
}
else
yield put({type: 'DATABASES_NOT_READY', ...[]});
latestAccount=account;
}
catch (error) {
console.error(error);
yield put({type: 'ORBIT_SAGA_ERROR', ...[]});
}
}
}
function* orbitSaga() {
yield takeLatest("ACCOUNT_CHANGED", getOrbitDBInfo);
}
export default orbitSaga;
Loading…
Cancel
Save