From 26907b74820ce65b658fdcff1ce3202f65b73e92 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Wed, 19 Feb 2020 17:35:22 +0100 Subject: [PATCH] add bsae redux structure --- app/index.html | 9 ++-- app/js/actions/web3.js | 94 ++++++++++++++++++++++++++++++++++++++ app/js/components/App.js | 4 ++ app/js/config.js | 3 ++ app/js/containers/App.js | 14 ++++++ app/js/index.js | 45 +++++++++++++++++-- app/js/reducers/index.js | 8 ++++ app/js/reducers/web3.js | 47 +++++++++++++++++++ config/contracts.js | 7 ++- package-lock.json | 97 ++++++++++++++++++++++++++++++++++++++-- package.json | 6 +++ 11 files changed, 317 insertions(+), 17 deletions(-) create mode 100644 app/js/actions/web3.js create mode 100644 app/js/components/App.js create mode 100644 app/js/config.js create mode 100644 app/js/containers/App.js create mode 100644 app/js/reducers/index.js create mode 100644 app/js/reducers/web3.js diff --git a/app/index.html b/app/index.html index 1cde205..4ae316f 100644 --- a/app/index.html +++ b/app/index.html @@ -1,11 +1,10 @@ - Embark - - + Keycard Redeem + -

Welcome to Embark!

-

See the Embark's documentation to see what you can do with Embark!

+
+ diff --git a/app/js/actions/web3.js b/app/js/actions/web3.js new file mode 100644 index 0000000..9b0c915 --- /dev/null +++ b/app/js/actions/web3.js @@ -0,0 +1,94 @@ +import Web3 from 'web3'; +import { Dispatch } from 'redux'; +import { config } from '../config'; + +export const VALID_NETWORK_NAME = "Ropsten"; +export const VALID_NETWORK_ID = 3; +// export const VALID_NETWORK_NAME = "Goerli"; +// export const VALID_NETWORK_ID = 5; +export const LOCAL_NETWORK_ID = 1337; + +export const WEB3_INITIALIZED = "WEB3_INITIALIZED"; +export const WEB3_ERROR = "WEB3_ERROR"; +export const WEB3_NETWORK_ID_LOADED = "WEB3_NETWORK_ID_LOADED"; +export const WEB3_ACCOUNT_LOADED = "WEB3_ACCOUNT_LOADED"; + +export const web3Initialized = () => ({ + type: WEB3_INITIALIZED, +}) + +export const web3NetworkIDLoaded = networkID => ({ + type: WEB3_NETWORK_ID_LOADED, + networkID, +}); + +export const web3Error = error => ({ + type: WEB3_ERROR, + error, +}); + +export const web3AccoutLoaded = account => ({ + type: WEB3_ACCOUNT_LOADED, + account, +}); + +export const initWeb3 = () => { + if (window.ethereum) { + config.web3 = new Web3(window.ethereum); + return (dispatch, getState) => { + window.ethereum.enable() + .then(() => { + dispatch(web3Initialized()); + dispatch(loadNetwordId()); + }) + .catch((err) => { + dispatch(web3Error(err)); + }); + } + } else if (window.web3) { + config.web3 = window.web3; + return (dispatch, getState) => { + dispatch(web3Initialized()); + dispatch(loadNetwordId()); + } + } else { + //FIXME: move to config + // const web3 = new Web3('https://ropsten.infura.io/v3/f315575765b14720b32382a61a89341a'); + // const web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/v3/f315575765b14720b32382a61a89341a')); + config.web3 = new Web3(new Web3.providers.WebsocketProvider('wss://ropsten.infura.io/ws/v3/f315575765b14720b32382a61a89341a')); + return (dispatch, getState) => { + dispatch(web3Initialized()); + dispatch(loadNetwordId()); + } + } +} + +const loadNetwordId = () => { + return (dispatch, getState) => { + config.web3.eth.net.getId().then((id) => { + dispatch(web3NetworkIDLoaded(id)) + if (id !== VALID_NETWORK_ID && id !== LOCAL_NETWORK_ID) { + dispatch(web3Error(`wrong network, please connect to ${VALID_NETWORK_NAME}`)); + return; + } + + dispatch(web3NetworkIDLoaded(id)) + dispatch(loadMainAccount()); + }) + .catch((err) => { + dispatch(web3Error(err)); + }); + }; +} + +const loadMainAccount = () => { + return (dispatch, getState) => { + web3.eth.getAccounts() + .then(accounts => { + dispatch(web3AccoutLoaded(accounts[0])); + }) + .catch((err) => { + dispatch(web3Error(err)); + }); + }; +} diff --git a/app/js/components/App.js b/app/js/components/App.js new file mode 100644 index 0000000..63c8e2a --- /dev/null +++ b/app/js/components/App.js @@ -0,0 +1,4 @@ +export default function App(props) { + return `Hello World ${props.account}`; +} + diff --git a/app/js/config.js b/app/js/config.js new file mode 100644 index 0000000..44614d8 --- /dev/null +++ b/app/js/config.js @@ -0,0 +1,3 @@ +export const config = { + web3: undefined, +}; diff --git a/app/js/containers/App.js b/app/js/containers/App.js new file mode 100644 index 0000000..79ab5f2 --- /dev/null +++ b/app/js/containers/App.js @@ -0,0 +1,14 @@ +import { connect } from 'react-redux'; +import App from '../components/App'; + +const mapStateToProps = state => ({ + account: state.web3.account, +}); + +const mapDispatchToProps = dispatch => ({ +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(App); diff --git a/app/js/index.js b/app/js/index.js index fc58b25..6dda51d 100644 --- a/app/js/index.js +++ b/app/js/index.js @@ -1,10 +1,47 @@ import EmbarkJS from 'Embark/EmbarkJS'; +import React, { useEffect } from 'react'; +import ReactDOM from 'react-dom'; +import thunkMiddleware from 'redux-thunk'; +import { Provider } from 'react-redux'; +import { createStore, applyMiddleware } from 'redux'; +import createRootReducer from './reducers'; +import { initWeb3 } from './actions/web3'; +import App from './containers/App'; -// import your contracts -// e.g if you have a contract named SimpleStorage: -//import SimpleStorage from 'Embark/contracts/SimpleStorage'; +const logger = (store) => { + return (next) => { + return (action) => { + console.log('dispatching\n', action); + const result = next(action); + console.log('next state\n', store.getState()); + return result; + } + } +}; +let middlewares = [ + thunkMiddleware, +]; + +if (true || process.env.NODE_ENV !== 'production') { + middlewares = [ + ...middlewares, + logger + ]; +} + +const store = createStore( + createRootReducer(), + applyMiddleware(...middlewares), +); EmbarkJS.onReady((err) => { - // You can execute contract calls after the connection + store.dispatch(initWeb3()); + + ReactDOM.render( + + + , + document.getElementById("root") + ); }); diff --git a/app/js/reducers/index.js b/app/js/reducers/index.js new file mode 100644 index 0000000..dcfd65e --- /dev/null +++ b/app/js/reducers/index.js @@ -0,0 +1,8 @@ +import { combineReducers } from 'redux'; +import { web3Reducer } from './web3'; + +export default function() { + return combineReducers({ + web3: web3Reducer, + }); +} diff --git a/app/js/reducers/web3.js b/app/js/reducers/web3.js new file mode 100644 index 0000000..dde7664 --- /dev/null +++ b/app/js/reducers/web3.js @@ -0,0 +1,47 @@ +import { + WEB3_INITIALIZED, + WEB3_ERROR, + WEB3_NETWORK_ID_LOADED, + WEB3_ACCOUNT_LOADED, +} from '../actions/web3'; + +const initialState: Web3State = { + initialized: false, + networkID: undefined, + error: undefined, + account: undefined, +}; + +export const web3Reducer = (state = initialState, action) => { + switch (action.type) { + case WEB3_INITIALIZED: { + return { + ...state, + initialized: true, + } + } + + case WEB3_ERROR: { + return { + ...state, + error: action.error, + } + } + + case WEB3_NETWORK_ID_LOADED: { + return { + ...state, + networkID: action.networkID, + } + } + + case WEB3_ACCOUNT_LOADED: { + return { + ...state, + account: action.account, + } + } + } + + return state; +} diff --git a/config/contracts.js b/config/contracts.js index 381f53c..5313e18 100644 --- a/config/contracts.js +++ b/config/contracts.js @@ -30,10 +30,9 @@ module.exports = { // filteredFields: [], deploy: { - // example: - //SimpleStorage: { - // args: [ 100 ] - //} + GiftsBatch: { + deploy: false, + } } }, diff --git a/package-lock.json b/package-lock.json index 08d2b8e..3588c5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/runtime": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", + "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, "@babel/runtime-corejs2": { "version": "7.0.0-rc.1", "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.0.0-rc.1.tgz", @@ -2779,6 +2787,14 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", @@ -3594,6 +3610,11 @@ "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", "dev": true }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -3933,6 +3954,14 @@ } } }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -4552,8 +4581,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "oboe": { "version": "2.1.4", @@ -4946,6 +4974,16 @@ "integrity": "sha512-ghsSuzZXJX8iO7WVec2z7GI+Xk/EyiD+JZK7AZKhUqYfpLa/Zs4ylUD+CwwnKlG6G3HnkUPMAi6PO7zeqGKssg==", "dev": true }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, "protocol-buffers-schema": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.4.0.tgz", @@ -5085,6 +5123,44 @@ "unpipe": "1.0.0" } }, + "react": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz", + "integrity": "sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.12.0.tgz", + "integrity": "sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.18.0" + } + }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" + }, + "react-redux": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", + "integrity": "sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==", + "requires": { + "@babel/runtime": "^7.5.5", + "hoist-non-react-statics": "^3.3.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.9.0" + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -5117,11 +5193,15 @@ "resolve": "^1.1.6" } }, + "redux-thunk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", + "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + }, "regenerator-runtime": { "version": "0.13.3", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", - "dev": true + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" }, "request": { "version": "2.88.2", @@ -5286,6 +5366,15 @@ "taskgroup": "^4.0.5" } }, + "scheduler": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", + "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, "scrypt-js": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", diff --git a/package.json b/package.json index 94e1039..def28f4 100644 --- a/package.json +++ b/package.json @@ -22,5 +22,11 @@ "embarkjs-swarm": "^5.1.1", "embarkjs-web3": "^5.2.0", "embarkjs-whisper": "^5.1.1" + }, + "dependencies": { + "react": "^16.12.0", + "react-dom": "^16.12.0", + "react-redux": "^7.2.0", + "redux-thunk": "^2.3.0" } }