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;
}
function getOrbitPublicKey() public view returns (string) {
require (hasUserSignedUp(msg.sender), "User hasn't signed up.");
return users[msg.sender].orbitdb.publicKey;
function getOrbitPublicKey(address userAddress) public view returns (string) {
require (hasUserSignedUp(userAddress), "User hasn't signed up.");
return users[userAddress].orbitdb.publicKey;
}
//TODO: encrypt using Metamask in the future
function getOrbitPrivateKey() public view returns (string) {
require (hasUserSignedUp(msg.sender), "User hasn't signed up.");
return users[msg.sender].orbitdb.privateKey;
function getOrbitPrivateKey(address userAddress) public view returns (string) {
require (hasUserSignedUp(userAddress), "User hasn't signed up.");
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----------------------------------------

5
package.json

@ -11,8 +11,9 @@
"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",
"ipfs": "^0.28.2",
"orbit-db": "^0.19.7",
"orbit-db-keystore": "^0.1.0",
"prop-types": "^15.6.1",
"react": "^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(
<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">
<h2>Account</h2>
<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/>
<br/><br/>
</div>
@ -29,6 +31,7 @@ const mapStateToProps = state => {
accounts: state.accounts,
Forum: state.contracts.Forum,
user: state.user,
orbitDB: state.orbitDB,
drizzleStatus: state.drizzleStatus
}
};

2
src/reducer.js

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

4
src/rootSaga.js

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

27
src/userSaga.js

@ -1,19 +1,18 @@
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;
let account;
let initFlag = false;
let forumContract;
let contractGrabbed = false;
function* initUser() {
if(!initFlag)
{
while(true)
if(contractGrabbed)
if(yield select(contractWasGrabbed))
{
yield call(getUserData);
initFlag=true;
@ -22,13 +21,6 @@ function* initUser() {
}
}
function grabContract({contract}) {
if(!contractGrabbed)
{
forumContract = contract;
contractGrabbed=true;
}
}
function* updateUserData() {
if(initFlag)
@ -37,14 +29,18 @@ function* updateUserData() {
function* getUserData() {
account = (yield select(accounts))[0];
forumContract.methods["hasUserSignedUp"].cacheCall(...[account]);
const txObj1 = yield call(forumContract.methods["hasUserSignedUp"], ...[account]);
const currentAccount = (yield select(accounts))[0];
if(currentAccount!==account)
{
account = currentAccount;
yield put({type: 'ACCOUNT_CHANGED', ...[]});
}
const txObj1 = yield call(contract.methods["hasUserSignedUp"], ...[account]);
try {
const callResult = yield call(txObj1.call, {address:account});
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 dispatchArgs = {
address: account,
@ -67,7 +63,6 @@ function* getUserData() {
function* userSaga() {
yield takeLatest('LISTEN_FOR_EVENT', grabContract);
yield takeLatest("DRIZZLE_INITIALIZED", initUser);
yield takeEvery("ACCOUNTS_FETCHED", updateUserData);
}

25
src/util/orbit.js

@ -1,6 +1,7 @@
import IPFS from 'ipfs';
import OrbitDB from 'orbit-db';
import Keystore from 'orbit-db-keystore';
import path from 'path';
import store from './../store';
// OrbitDB uses Pubsub which is an experimental feature
@ -17,7 +18,7 @@ const ipfsOptions = {
const ipfs = new IPFS(ipfsOptions);
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 topicsDB = await orbitdb.keyvalue('topics');
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,
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 = {
initialized: false,
databasesReady: false
ipfsInitialized: false,
ready: false,
id: null
};
const orbitReducer = (state = initialState, action) => {
switch (action.type) {
case 'IPFS_READY':
case 'IPFS_INITIALIZED':
return {
initialized: true
...state,
ipfsInitialized: true
};
case 'DATABASES_CREATED':
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:
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