diff --git a/app/package.json b/app/package.json index d784355..cb0aa4c 100644 --- a/app/package.json +++ b/app/package.json @@ -10,10 +10,12 @@ "connected-react-router": "6.4.0", "drizzle": "1.4.0", "history": "4.9.0", - "ipfs": "github:ipfs/js-ipfs#e849dbcab4a313f7ffc1532a389097ee76344067", + "ipfs": "0.35.0", + "level": "5.0.1", "lodash.isequal": "4.5.0", - "orbit-db": "0.19.9", - "orbit-db-keystore": "0.1.0", + "orbit-db": "0.21.0-rc.1", + "orbit-db-keystore": "0.2.1", + "orbit-db-identity-provider": "0.1.0", "prop-types": "15.7.2", "react": "16.8.6", "react-content-loader": "4.2.1", @@ -28,7 +30,7 @@ "redux-saga": "0.16.2", "semantic-ui-react": "0.87.1", "uuid": "3.3.2", - "web3": "1.0.0-beta.54" + "web3": "1.0.0-beta.55" }, "devDependencies": { "libp2p-websocket-star-rendezvous": "0.3.0" diff --git a/app/src/containers/LoadingContainer.js b/app/src/containers/LoadingContainer.js index 28b074c..c9cddbe 100644 --- a/app/src/containers/LoadingContainer.js +++ b/app/src/containers/LoadingContainer.js @@ -10,7 +10,7 @@ class LoadingContainer extends Component { render() { if (this.props.web3.status === 'failed' || !this.props.web3.networkId) { return ( -
+
ethereum_logo @@ -33,7 +33,7 @@ class LoadingContainer extends Component {
ethereum_logo -

We can't find any Ethereum accounts!.

+

We can't find any Ethereum accounts!

@@ -86,7 +86,7 @@ class LoadingContainer extends Component { return Children.only(this.props.children); return( -
+
app_logo diff --git a/app/src/redux/sagas/transactionsSaga.js b/app/src/redux/sagas/transactionsSaga.js index dca9b5c..c7e8373 100644 --- a/app/src/redux/sagas/transactionsSaga.js +++ b/app/src/redux/sagas/transactionsSaga.js @@ -4,13 +4,15 @@ import { drizzle } from '../../index'; import { orbitSagaPut } from '../../utils/orbitUtils'; import { WEB3_UTILS_SAGA_INITIALIZED } from '../actions/web3UtilsActions'; import { CONTRACT_EVENT_FIRED } from './eventSaga'; +import { getCurrentAccount } from './web3UtilsSaga'; const transactionsHistory = Object.create(null); function* initTransaction(action) { + action.transactionDescriptor.params.from = getCurrentAccount(); const dataKey = drizzle.contracts[action.transactionDescriptor.contract] .methods[action.transactionDescriptor.method].cacheSend( - ...(action.transactionDescriptor.params), + ...(action.transactionDescriptor.params) ); transactionsHistory[dataKey] = action; diff --git a/app/src/utils/EthereumIdentityProvider.js b/app/src/utils/EthereumIdentityProvider.js new file mode 100644 index 0000000..734628f --- /dev/null +++ b/app/src/utils/EthereumIdentityProvider.js @@ -0,0 +1,29 @@ +import { web3 } from '../redux/sagas/web3UtilsSaga'; + +class EthereumIdentityProvider { + constructor () { + this.web3 = web3; + } + + // Returns the type of the identity provider + static get type () { return 'ethereum' } + + // Returns the signer's id + async getId () { + return (await this.web3.eth.getAccounts())[0]; + } + + // Returns a signature of pubkeysignature + async signIdentity (data) { + const address = await this.getId(); + return await this.web3.eth.personal.sign(data,address,""); //Password not required for MetaMask + } + + static async verifyIdentity (identity) { + // Verify that identity was signed by the ID + return web3.eth.accounts.recover(identity.publicKey + identity.signatures.id, + identity.signatures.publicKey) === identity.id; + } +} + +export default EthereumIdentityProvider; diff --git a/app/src/utils/levelUtils.js b/app/src/utils/levelUtils.js new file mode 100644 index 0000000..b36df30 --- /dev/null +++ b/app/src/utils/levelUtils.js @@ -0,0 +1,20 @@ +import level from 'level' + +const db = level('./orbitdb/identity/identitykeys'); + +async function getPrivateKey(id){ + try{ + const keyPair = await db.get(id); + return JSON.parse(keyPair).privateKey; + } catch (err) { + if (err && err.notFound) + console.error("LevelDB: Private Key not found!"); + throw err; + } +} + +async function setKeyPair(id, publicKey, privateKey){ + await db.put(id,JSON.stringify({publicKey: publicKey, privateKey: privateKey})); +} + +export { getPrivateKey, setKeyPair } diff --git a/app/src/utils/orbitUtils.js b/app/src/utils/orbitUtils.js index 705d46f..8b78736 100644 --- a/app/src/utils/orbitUtils.js +++ b/app/src/utils/orbitUtils.js @@ -1,12 +1,14 @@ import OrbitDB from 'orbit-db'; -import Keystore from 'orbit-db-keystore'; -import path from 'path'; +import Identities from 'orbit-db-identity-provider'; import IPFS from 'ipfs'; import store from '../redux/store'; import { DATABASES_LOADED, IPFS_INITIALIZED, updateDatabases } from '../redux/actions/orbitActions'; import ipfsOptions from '../config/ipfsOptions'; +import EthereumIdentityProvider from './EthereumIdentityProvider'; +import { getPrivateKey, setKeyPair } from './levelUtils'; function initIPFS() { + Identities.addIdentityProvider(EthereumIdentityProvider); const ipfs = new IPFS(ipfsOptions); ipfs.on('error', (error) => console.error(`IPFS error: ${error}`)); ipfs.on('ready', async () => { @@ -24,7 +26,9 @@ function initIPFS() { async function createTempDatabases() { console.debug('Creating temporary databases...'); const ipfs = getIPFS(); - const orbitdb = new OrbitDB(ipfs); + const identity = await Identities.createIdentity({type: 'ethereum'}); + const orbitdb = await OrbitDB.createInstance(ipfs, {identity}); + console.dir(orbitdb) const topicsDB = await orbitdb.keyvalue('topics'); const postsDB = await orbitdb.keyvalue('posts'); return { orbitdb, topicsDB, postsDB }; @@ -33,19 +37,25 @@ async function createTempDatabases() { async function createDatabases() { console.debug('Creating databases...'); const ipfs = getIPFS(); - const orbitdb = new OrbitDB(ipfs); - const topicsDB = await orbitdb.keyvalue('topics'); - const postsDB = await orbitdb.keyvalue('posts'); - - const orbitKey = orbitdb.keystore.getKey(orbitdb.id); + const identity = await Identities.createIdentity({type: 'ethereum'}); + const orbitdb = await OrbitDB.createInstance(ipfs, {identity}); + const options = { + // Give write access to ourselves + accessController: { + write: ['*'] + } + }; + const topicsDB = await orbitdb.keyvalue('topics', options); + const postsDB = await orbitdb.keyvalue('posts', options); + const privateKey = await getPrivateKey(identity.id); return { - identityId: 'Tempus', - identityPublicKey: 'edax', - identityPrivateKey: 'rerum', + identityId: identity.id, + identityPublicKey: identity.publicKey, + identityPrivateKey: privateKey, orbitdb: orbitdb, - orbitPublicKey: orbitKey.getPublic('hex'), - orbitPrivateKey: orbitKey.getPrivate('hex'), + orbitPublicKey: "eeeee", + orbitPrivateKey: "fffffff", topicsDB: topicsDB.address.root, postsDB: postsDB.address.root }; @@ -54,30 +64,28 @@ async function createDatabases() { async function loadDatabases(identityId, identityPublicKey, identityPrivateKey, orbitId, orbitPublicKey, orbitPrivateKey, topicsDBId, postsDBId) { - const directory = './orbitdb'; - const keystore = Keystore.create(path.join(directory, orbitId, '/keystore')); + console.debug('Loading databases...'); + const ipfs = getIPFS(); + await setKeyPair(identityId, identityPublicKey, identityPrivateKey); + const identity = await Identities.createIdentity({type: 'ethereum' }); + const orbitdb = await OrbitDB.createInstance(ipfs, {identity}); - keystore._storage.setItem(orbitId, JSON.stringify({ - publicKey: orbitPublicKey, - privateKey: orbitPrivateKey - })); + console.dir(orbitdb) - const ipfs = getIPFS(); - const orbitdb = new OrbitDB(ipfs, directory, - { - peerId: orbitId, keystore - }); - const topicsDB = await orbitdb.keyvalue(`/orbitdb/${topicsDBId}/topics`) + const topicsDB = await orbitdb.keyvalue('topics') .catch((error) => console.error(`TopicsDB init error: ${error}`)); - const postsDB = await orbitdb.keyvalue(`/orbitdb/${postsDBId}/posts`) - .catch((error) => console.error(`PostsDB init error: ${error}`)); + console.dir(topicsDB) + + const postsDB = await orbitdb.keyvalue('posts') + .catch((error) => console.error(`PostsDB init error: ${error}`)); + console.dir(topicsDB) await topicsDB.load().catch((error) => console.error(`TopicsDB loading error: ${error}`)); await postsDB.load().catch((error) => console.error(`PostsDB loading error: ${error}`)); //It is possible that we lack our own data and need to replicate them from somewhere else topicsDB.events.on('replicate', (address) => { - console.log(`TopicsDB Replicating (${address}).`); + console.log(`TopicsDB replicating (${address}).`); }); topicsDB.events.on('replicated', (address) => { console.log(`TopicsDB replicated (${address}).`); @@ -89,7 +97,7 @@ async function loadDatabases(identityId, identityPublicKey, identityPrivateKey, console.log(`PostsDB replicated (${address}).`); }); - console.debug('Orbit databases loaded successfully.'); + console.debug('Databases loaded successfully.'); store.dispatch(updateDatabases(DATABASES_LOADED, orbitdb, topicsDB, postsDB)); }