diff --git a/embark-ui/package-lock.json b/embark-ui/package-lock.json index ce78d3b5..1b5f3406 100644 --- a/embark-ui/package-lock.json +++ b/embark-ui/package-lock.json @@ -12194,14 +12194,6 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "^1.0.0" - } - }, "ua-parser-js": { "version": "0.7.18", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz", @@ -12932,8 +12924,19 @@ "integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==", "requires": { "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.36", - "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + "web3-core-helpers": "1.0.0-beta.36" + }, + "dependencies": { + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "from": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "requires": { + "debug": "^2.2.0", + "nan": "^2.3.3", + "typedarray-to-buffer": "^3.1.2", + "yaeti": "^0.0.6" + } + } } }, "web3-shh": { @@ -13371,16 +13374,6 @@ "source-map": "~0.6.1" } }, - "websocket": { - "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", - "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible", - "requires": { - "debug": "^2.2.0", - "nan": "^2.3.3", - "typedarray-to-buffer": "^3.1.2", - "yaeti": "^0.0.6" - } - }, "websocket-driver": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", @@ -13611,11 +13604,6 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, - "yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" - }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", diff --git a/embark-ui/src/actions/index.js b/embark-ui/src/actions/index.js index 4ee35715..e4a73dd7 100644 --- a/embark-ui/src/actions/index.js +++ b/embark-ui/src/actions/index.js @@ -349,6 +349,67 @@ export const web3EstimateGas = { failure: (error, payload) => action(WEB3_ESTIMAGE_GAS[FAILURE], {web3Error: error, contract: payload.contract}) }; +export const START_DEBUG = createRequestTypes('START_DEBUG'); +export const startDebug = { + request: (txHash) => action(START_DEBUG[REQUEST], {txHash}), + success: () => action(START_DEBUG[SUCCESS]), + failure: (error) => action(START_DEBUG[FAILURE], {error}) +}; + +export const DEBUG_JUMP_BACK = createRequestTypes('DEBUG_JUMP_BACK'); +export const debugJumpBack = { + request: () => action(DEBUG_JUMP_BACK[REQUEST], {}), + success: () => action(DEBUG_JUMP_BACK[SUCCESS]), + failure: (error) => action(DEBUG_JUMP_BACK[FAILURE], {error}) +}; + +export const DEBUG_JUMP_FORWARD = createRequestTypes('DEBUG_JUMP_FORWARD'); +export const debugJumpForward = { + request: () => action(DEBUG_JUMP_FORWARD[REQUEST], {}), + success: () => action(DEBUG_JUMP_FORWARD[SUCCESS]), + failure: (error) => action(DEBUG_JUMP_FORWARD[FAILURE], {error}) +}; + +export const DEBUG_STEP_OVER_BACKWARD = createRequestTypes('DEBUG_STEP_OVER_BACKWARD'); +export const debugStepOverBackward = { + request: () => action(DEBUG_STEP_OVER_BACKWARD[REQUEST], {}), + success: () => action(DEBUG_STEP_OVER_BACKWARD[SUCCESS]), + failure: (error) => action(DEBUG_STEP_OVER_BACKWARD[FAILURE], {error}) +}; + +export const DEBUG_STEP_OVER_FORWARD = createRequestTypes('DEBUG_STEP_OVER_FORWARD'); +export const debugStepOverForward = { + request: () => action(DEBUG_STEP_OVER_FORWARD[REQUEST], {}), + success: () => action(DEBUG_STEP_OVER_FORWARD[SUCCESS]), + failure: (error) => action(DEBUG_STEP_OVER_FORWARD[FAILURE], {error}) +}; + +export const DEBUG_STEP_INTO_BACKWARD = createRequestTypes('DEBUG_STEP_INTO_BACKWARD'); +export const debugStepIntoBackward = { + request: () => action(DEBUG_STEP_INTO_BACKWARD[REQUEST], {}), + success: () => action(DEBUG_STEP_INTO_BACKWARD[SUCCESS]), + failure: (error) => action(DEBUG_STEP_INTO_BACKWARD[FAILURE], {error}) +}; + +export const DEBUG_STEP_INTO_FORWARD = createRequestTypes('DEBUG_STEP_INTO_FORWARD'); +export const debugStepIntoForward = { + request: () => action(DEBUG_STEP_INTO_FORWARD[REQUEST], {}), + success: () => action(DEBUG_STEP_INTO_FORWARD[SUCCESS]), + failure: (error) => action(DEBUG_STEP_INTO_FORWARD[FAILURE], {error}) +}; + +export const TOGGLE_BREAKPOINT = createRequestTypes('TOGGLE_BREAKPOINT'); +export const toggleBreakpoint = { + request: (filename, lineNumber) => action(TOGGLE_BREAKPOINT[REQUEST], {filename, lineNumber}), + success: (data, payload) => action(TOGGLE_BREAKPOINT[SUCCESS], {payload}), + failure: (error) => action(TOGGLE_BREAKPOINT[FAILURE], {error}) +}; + +export const DEBUGGER_INFO = createRequestTypes('DEBUGGER_INFO'); +export const debuggerInfo = { + success: (data) => action(DEBUGGER_INFO[SUCCESS], {data}) +}; + // Web Socket export const WATCH_NEW_PROCESS_LOGS = 'WATCH_NEW_PROCESS_LOGS'; export const STOP_NEW_PROCESS_LOGS = 'STOP_NEW_PROCESS_LOGS'; @@ -358,6 +419,7 @@ export const INIT_BLOCK_HEADER = 'INIT_BLOCK_HEADER'; export const STOP_BLOCK_HEADER = 'STOP_BLOCK_HEADER'; export const WATCH_GAS_ORACLE = 'WATCH_GAS_ORACLE'; export const STOP_GAS_ORACLE = 'STOP_GAS_ORACLE'; +export const STOP_DEBUGGER = 'STOP_DEBUGGER'; export function listenToProcessLogs(processName) { return { @@ -409,6 +471,12 @@ export function stopGasOracle(){ }; } +export function stopDebugger(){ + return { + type: STOP_DEBUGGER + } +} + // Actions without Side Effect export const UPDATE_BASE_ETHER = 'UPDATE_BASE_ETHER'; export function updateBaseEther(value) { @@ -418,18 +486,10 @@ export function updateBaseEther(value) { }; } -export const TOGGLE_BREAKPOINT = 'TOGGLE_BREAKPOINT'; -export function toggleBreakpoint(filename, lineNumber) { - return { - type: TOGGLE_BREAKPOINT, - payload: {filename, lineNumber} - }; -} - export const UPDATE_DEPLOYMENT_PIPELINE = 'UPDATE_DEPLOYMENT_PIPELINE'; export function updateDeploymentPipeline(value) { return { type: UPDATE_DEPLOYMENT_PIPELINE, payload: value }; -} \ No newline at end of file +} diff --git a/embark-ui/src/components/ContractDebugger.js b/embark-ui/src/components/ContractDebugger.js new file mode 100644 index 00000000..b6f517ff --- /dev/null +++ b/embark-ui/src/components/ContractDebugger.js @@ -0,0 +1,95 @@ +import PropTypes from "prop-types"; +import React, {Component} from 'react'; +import { + Row, + Col, + FormGroup, + Label, + Input, + Button, + Card, + CardBody, + CardHeader, + CardTitle, + CardFooter, + ListGroup, + ListGroupItem +} from "reactstrap"; +import ReactJson from 'react-json-view'; + +class ContractDebugger extends Component { + + constructor(props) { + super(props); + } + + handleChange(e) { + this.setState({txHash: e.target.value}); + } + + debug(e) { + this.props.startDebug(this.state.txHash); + } + + debugJumpBack(e) { + this.props.debugJumpBack() + } + + debugJumpForward(e) { + this.props.debugJumpForward() + } + + debugStepOverForward(e) { + this.props.debugStepOverForward() + } + + debugStepOverBackward(e) { + this.props.debugStepOverBackward() + } + + debugStepIntoForward(e) { + this.props.debugStepIntoForward() + } + + debugStepIntoBackward(e) { + this.props.debugStepIntoBackward() + } + + render() { + return ( +
+ + + this.handleChange(e)}/> + + + + + + + + + + + + + + + +
Scopes +
+ +
+ +
+
+ ); + } +} + +ContractDebugger.propTypes = { + contract: PropTypes.object.isRequired, +}; + +export default ContractDebugger; + diff --git a/embark-ui/src/components/ContractLayout.js b/embark-ui/src/components/ContractLayout.js index acf8d114..fbb32a94 100644 --- a/embark-ui/src/components/ContractLayout.js +++ b/embark-ui/src/components/ContractLayout.js @@ -6,6 +6,7 @@ import classnames from 'classnames'; import ContractDetail from '../components/ContractDetail'; import ContractLoggerContainer from '../containers/ContractLoggerContainer'; import ContractOverviewContainer from '../containers/ContractOverviewContainer'; +import ContractDebuggerContainer from '../containers/ContractDebuggerContainer'; class ContractLayout extends React.Component { constructor(props) { @@ -55,6 +56,14 @@ class ContractLayout extends React.Component { Logger + + { this.toggle('4'); }} + > + Debugger + + @@ -66,6 +75,9 @@ class ContractLayout extends React.Component { + + + diff --git a/embark-ui/src/components/TextEditor.js b/embark-ui/src/components/TextEditor.js index 1b9efc7a..07fa8393 100644 --- a/embark-ui/src/components/TextEditor.js +++ b/embark-ui/src/components/TextEditor.js @@ -97,8 +97,9 @@ class TextEditor extends React.Component { } )); - //TODO remove me when debuggerLine comes from the debugger API - let debuggerLine = this.props.debuggerLine || 11; + let debuggerLine = this.props.debuggerLine; + console.dir("debuggerLine") + console.dir(debuggerLine) newDecorations.push({ range: new monaco.Range(debuggerLine,1,debuggerLine,1), options: { @@ -116,9 +117,8 @@ class TextEditor extends React.Component { } this.updateMarkers(); - // TODO replace with const expectedDecorationsLength = this.props.debuggerLine ? this.props.breakpoints.length + 1 : this.props.breakpoints.length - const expectedDecorationsLength = this.props.breakpoints.length + 1; - if (expectedDecorationsLength !== this.state.decorations.length) { + const expectedDecorationsLength = this.props.debuggerLine ? this.props.breakpoints.length + 1 : this.props.breakpoints.length + if (expectedDecorationsLength !== this.state.decorations.length || this.props.debuggerLine !== prevProps.debuggerLine) { this.updateDecorations(); } this.updateLanguage(); @@ -142,4 +142,4 @@ TextEditor.propTypes = { debuggerLine: PropTypes.number }; -export default TextEditor; \ No newline at end of file +export default TextEditor; diff --git a/embark-ui/src/components/TextEditorToolbar.js b/embark-ui/src/components/TextEditorToolbar.js index 4eaf4305..61620828 100644 --- a/embark-ui/src/components/TextEditorToolbar.js +++ b/embark-ui/src/components/TextEditorToolbar.js @@ -41,6 +41,9 @@ const TextEditorToolbar = (props) => ( Logger | + } + Once you set the value, the transaction will need to be mined and then the value will be updated + on the blockchain. + + + +

2. Get the current value

+
+ + current value is {this.state.valueGet} + + Click the button to get the current value. The initial value is 100. + +
+ +

3. Contract Calls

+

Javascript calls being made:

+
+ { + this.state.logs.map((item, i) =>

{item}

) + } +
+ + ); + } +} + +export default Blockchain; diff --git a/test_apps/embark_demo/app/components/ens.js b/test_apps/embark_demo/app/components/ens.js new file mode 100644 index 00000000..1afaf510 --- /dev/null +++ b/test_apps/embark_demo/app/components/ens.js @@ -0,0 +1,180 @@ +/*global web3*/ +import EmbarkJS from 'Embark/EmbarkJS'; +import React from 'react'; +import { Alert, Form, FormGroup, FormControl, Button } from 'react-bootstrap'; + +window.EmbarkJS = EmbarkJS; + +class ENS extends React.Component { + + constructor(props) { + super(props); + + this.state = { + valueResolve: 'eth', + responseResolve: null, + isResolveError: false, + valueLookup: '', + responseLookup: null, + isLookupError: false, + valueRegister: '', + addressRegister: '', + responseRegister: null, + isRegisterError: false, + embarkLogs: [] + }; + } + + componentDidMount() { + EmbarkJS.onReady(() => { + if (!web3.eth.defaultAccount) { + this.setState({ + globalError: 'There is currently no default account. If Metamask is active, please sign in or deactivate it.' + }); + } + this.setState({ + addressRegister: web3.eth.defaultAccount, + valueLookup: web3.eth.defaultAccount + }) + }); + } + + handleChange(stateName, e) { + this.setState({ [stateName]: e.target.value }); + } + + checkEnter(e, func) { + if (e.key !== 'Enter') { + return; + } + e.preventDefault(); + func.apply(this, [e]); + } + + registerSubDomain(e) { + e.preventDefault(); + const self = this; + const embarkLogs = this.state.embarkLogs; + embarkLogs.push(`EmbarkJS.Names.registerSubDomain('${this.state.valueRegister}', '${this.state.addressRegister}', console.log)`); + this.setState({ + embarkLogs: embarkLogs + }); + + EmbarkJS.Names.registerSubDomain(this.state.valueRegister, this.state.addressRegister, (err, transaction) => { + const message = err ? err : `Successfully registered "${this.state.valueRegister}" with ${transaction.gasUsed} gas`; + self.setState({ + responseRegister: message, + isRegisterError: !!err + }); + }); + } + + resolveName(e) { + e.preventDefault(); + const embarkLogs = this.state.embarkLogs; + embarkLogs.push(`EmbarkJS.Names.resolve('${this.state.valueResolve}', console.log)`); + + this.setState({ + embarkLogs: embarkLogs + }); + EmbarkJS.Names.resolve(this.state.valueResolve, (err, result) => { + if (err) { + return this.setState({ + responseResolve: err.message || err, + isResolveError: true + }); + } + this.setState({ + responseResolve: result, + isResolveError: false + }); + }); + } + + lookupAddress(e) { + e.preventDefault(); + const embarkLogs = this.state.embarkLogs; + embarkLogs.push(`EmbarkJS.Names.resolve('${this.state.valueLookup}', console.log)`); + + this.setState({ + embarkLogs: embarkLogs + }); + EmbarkJS.Names.lookup(this.state.valueLookup, (err, result) => { + if (err) { + return this.setState({ + responseLookup: err.message || err, + isLookupError: true + }); + } + this.setState({ + responseLookup: result, + isLookupError: false + }); + }); + } + + render() { + return ( + {this.state.globalError && {this.state.globalError}} +

Resolve a name

+
this.checkEnter(e, this.resolveName)}> + + {this.state.responseResolve && + + Resolved address: {this.state.responseResolve} + } + this.handleChange('valueResolve', e)}/> + + +
+ +

Lookup an address

+
this.checkEnter(e, this.lookupAddress)}> + + {this.state.responseLookup && + + Looked up domain: {this.state.responseLookup} + } + this.handleChange('valueLookup', e)}/> + + +
+ +

Register subdomain

+
this.checkEnter(e, this.registerSubDomain)}> + + {this.state.responseRegister && + + {this.state.responseRegister} + } + this.handleChange('valueRegister', e)}/> + this.handleChange('addressRegister', e)}/> + + +
+ +

Embark Calls

+

Javascript calls being made:

+
+ { + this.state.embarkLogs.map((item, i) =>

{item}

) + } +
+
+ ); + } +} + +export default ENS; diff --git a/test_apps/embark_demo/app/components/storage.js b/test_apps/embark_demo/app/components/storage.js new file mode 100644 index 00000000..0de4815c --- /dev/null +++ b/test_apps/embark_demo/app/components/storage.js @@ -0,0 +1,272 @@ +import EmbarkJS from 'Embark/EmbarkJS'; +import React from 'react'; +import {Alert, Form, FormGroup, FormControl, HelpBlock, Button} from 'react-bootstrap'; + +class Storage extends React.Component { + + constructor(props) { + super(props); + + this.state = { + textToSave: 'hello world!', + generatedHash: '', + loadText: '', + storedText: '', + fileToUpload: null, + fileHash: '', + imageToDownload: '', + url: '', + logs: [], + storageError: '', + valueRegister: '', + valueResolver: '', + }; + } + + handleChange(e, name) { + this.state[name] = e.target.value; + this.setState(this.state); + } + + checkEnter(e, func) { + if (e.key !== 'Enter') { + return; + } + e.preventDefault(); + func.apply(this, [e]); + } + + handleFileUpload(e) { + this.setState({fileToUpload: [e.target]}); + } + + addToLog(txt) { + this.state.logs.push(txt); + this.setState({logs: this.state.logs}); + } + + setText(e) { + e.preventDefault(); + + EmbarkJS.Storage.saveText(this.state.textToSave) + .then((hash) => { + this.setState({ + generatedHash: hash, + loadText: hash, + storageError: '' + }); + this.addToLog("EmbarkJS.Storage.saveText('" + this.state.textToSave + "').then(function(hash) { })"); + }) + .catch((err) => { + if (err) { + this.setState({storageError: err.message}); + console.log("Storage saveText Error => " + err.message); + } + }); + } + + loadHash(e) { + e.preventDefault(); + + EmbarkJS.Storage.get(this.state.loadText) + .then((content) => { + this.setState({storedText: content, storageError: ''}); + this.addToLog("EmbarkJS.Storage.get('" + this.state.loadText + "').then(function(content) { })"); + }) + .catch((err) => { + if (err) { + this.setState({storageError: err.message}); + console.log("Storage get Error => " + err.message); + } + }); + } + + uploadFile(e) { + e.preventDefault(); + + EmbarkJS.Storage.uploadFile(this.state.fileToUpload) + .then((hash) => { + this.setState({ + fileHash: hash, + imageToDownload: hash, + storageError: '' + }); + this.addToLog("EmbarkJS.Storage.uploadFile(this.state.fileToUpload).then(function(hash) { })"); + }) + .catch((err) => { + if (err) { + this.setState({storageError: err.message}); + console.log("Storage uploadFile Error => " + err.message); + } + }); + } + + loadFile(e) { + let _url = EmbarkJS.Storage.getUrl(this.state.imageToDownload); + this.setState({url: _url}); + this.addToLog("EmbarkJS.Storage.getUrl('" + this.state.imageToDownload + "')"); + } + + ipnsRegister(e) { + e.preventDefault(); + this.setState({ registering: true, responseRegister: false }); + this.addToLog("EmbarkJS.Storage.register(this.state.ipfsHash).then(function(hash) { })"); + EmbarkJS.Storage.register(this.state.valueRegister, (err, name) => { + let responseRegister; + let isRegisterError = false; + if (err) { + isRegisterError = true; + responseRegister = "Name Register Error: " + (err.message || err) + } else { + responseRegister = name; + } + + this.setState({ + registering: false, + responseRegister, + isRegisterError + }); + }); + } + + ipnsResolve(e) { + e.preventDefault(); + this.setState({ resolving: true, responseResolver: false }); + this.addToLog("EmbarkJS.Storage.resolve(this.state.ipnsName, function(err, path) { })"); + EmbarkJS.Storage.resolve(this.state.valueResolver, (err, path) => { + let responseResolver; + let isResolverError = false; + if (err) { + isResolverError = true; + responseResolver = "Name Resolve Error: " + (err.message || err) + } else { + responseResolver = path; + } + + this.setState({ + resolving: false, + responseResolver, + isResolverError + }); + }); + } + + isIpfs(){ + return EmbarkJS.Storage.currentProviderName === 'ipfs'; + } + + render() { + return + { + !this.props.enabled ? + + The node you are using does not support IPFS. Please ensure CORS is setup for the IPFS + node. + : '' + } + { + this.state.storageError !== '' ? + {this.state.storageError} + : '' + } +

Save text to storage

+
this.checkEnter(e, this.setText)}> + + this.handleChange(e, 'textToSave')}/> + + generated Hash: {this.state.generatedHash} + +
+ +

Load text from storage given an hash

+
this.checkEnter(e, this.loadHash)}> + + this.handleChange(e, 'loadText')}/> + + result: {this.state.storedText} + +
+ +

Upload file to storage

+
+ + this.handleFileUpload(e)}/> + + generated hash: {this.state.fileHash} + +
+ +

Get file or image from storage

+
this.checkEnter(e, this.loadFile)}> + + this.handleChange(e, 'imageToDownload')}/> + + file available at: {this.state.url} + + +
+ + {!this.isIpfs() && The 2 functions below are only available with IPFS} + +

Register to IPNS

+
this.checkEnter(e, this.ipnsRegister)}> + + this.handleChange(e, 'valueRegister')}/> + + It will take around 1 minute + {this.state.responseRegister && + + {this.state.responseRegister} + } + +
+ +

Resolve name

+
this.checkEnter(e, this.ipnsResolve)}> + + this.handleChange(e, 'valueResolver')}/> + + It will take around 1 minute + {this.state.responseResolver && + + {this.state.responseResolver} + } + +
+ + +

Javascript calls being made:

+
+

EmbarkJS.Storage.setProvider('ipfs',{'{'}server: 'localhost', port: '5001'{'}'})

+ { + this.state.logs.map((item, i) =>

{item}

) + } +
+
; + } +} + +export default Storage; diff --git a/test_apps/embark_demo/app/components/whisper.js b/test_apps/embark_demo/app/components/whisper.js new file mode 100644 index 00000000..29d2bb27 --- /dev/null +++ b/test_apps/embark_demo/app/components/whisper.js @@ -0,0 +1,126 @@ +import EmbarkJS from 'Embark/EmbarkJS'; +import React from 'react'; +import {Alert, Form, FormGroup, FormControl, Button} from 'react-bootstrap'; + +class Whisper extends React.Component { + + constructor (props) { + super(props); + + this.state = { + listenTo: '', + channel: '', + message: '', + subscribedChannels: [], + messageList: [], + logs: [] + }; + } + + handleChange (e, name) { + this.state[name] = e.target.value; + this.setState(this.state); + } + + checkEnter(e, func) { + if (e.key !== 'Enter') { + return; + } + e.preventDefault(); + func.apply(this, [e]); + } + + sendMessage (e) { + e.preventDefault(); + EmbarkJS.Messages.sendMessage({topic: this.state.channel, data: this.state.message}); + this.addToLog("EmbarkJS.Messages.sendMessage({topic: '" + this.state.channel + "', data: '" + this.state.message + "'})"); + } + + listenToChannel (e) { + e.preventDefault(); + + const subscribedChannels = this.state.subscribedChannels; + subscribedChannels.push(Subscribed to {this.state.listenTo}. Now try sending a message); + this.setState({ + subscribedChannels + }); + + EmbarkJS.Messages.listenTo({topic: [this.state.listenTo]}, (error, message) => { + const messageList = this.state.messageList; + if (error) { + messageList.push(Error: {error}); + } else { + messageList.push(Channel: {message.topic} | Message: {message.data}); + } + this.setState({ + messageList + }); + }); + + this.addToLog("EmbarkJS.Messages.listenTo({topic: ['" + this.state.listenTo + "']}).then(function(message) {})"); + } + + addToLog (txt) { + this.state.logs.push(txt); + this.setState({logs: this.state.logs}); + } + + render () { + return ( + + { + !this.props.enabled ? + + The node you are using does not support Whisper + The node uses an unsupported version of Whisper + : '' + } +

Listen To channel

+
this.checkEnter(e, this.listenToChannel)}> + + this.handleChange(e, 'listenTo')}/> + +
+ {this.state.subscribedChannels.map((item, i) =>

{item}

)} +
+

messages received:

+
+ {this.state.messageList.map((item, i) =>

{item}

)} +
+
+
+ +

Send Message

+
this.checkEnter(e, this.sendMessage)}> + + this.handleChange(e, 'channel')}/> + this.handleChange(e, 'message')}/> + + +
+ +

Javascript calls being made:

+
+

EmbarkJS.Messages.setProvider('whisper')

+ { + this.state.logs.map((item, i) =>

{item}

) + } +
+
+ ); + } +} + +export default Whisper; diff --git a/test_apps/embark_demo/app/dapp.css b/test_apps/embark_demo/app/dapp.css new file mode 100644 index 00000000..401124e8 --- /dev/null +++ b/test_apps/embark_demo/app/dapp.css @@ -0,0 +1,57 @@ + +div { + margin: 15px; +} + +.logs { + background-color: black; + font-size: 14px; + color: white; + font-weight: bold; + padding: 10px; + border-radius: 8px; +} + +.tab-content { + border-left: 1px solid #ddd; + border-right: 1px solid #ddd; + border-bottom: 1px solid #ddd; + padding: 10px; + margin: 0px; +} + +.nav-tabs { + margin-bottom: 0; +} + +.status-offline { + vertical-align: middle; + margin-left: 5px; + margin-top: 4px; + width: 12px; + height: 12px; + background: red; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + border-radius: 10px; +} + +.status-online { + vertical-align: middle; + margin-left: 5px; + margin-top: 4px; + width: 12px; + height: 12px; + background: mediumseagreen; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + border-radius: 10px; +} + +input.form-control { + margin-right: 5px; +} + +.alert-result { + margin-left: 0; +} diff --git a/test_apps/embark_demo/app/dapp.js b/test_apps/embark_demo/app/dapp.js new file mode 100644 index 00000000..c44d840b --- /dev/null +++ b/test_apps/embark_demo/app/dapp.js @@ -0,0 +1,94 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import {Tabs, Tab} from 'react-bootstrap'; + +import EmbarkJS from 'Embark/EmbarkJS'; +import Blockchain from './components/blockchain'; +import Whisper from './components/whisper'; +import Storage from './components/storage'; +import ENS from './components/ens'; + +import './dapp.css'; + +class App extends React.Component { + + constructor(props) { + super(props); + + this.handleSelect = this.handleSelect.bind(this); + + this.state = { + error: null, + activeKey: 1, + whisperEnabled: false, + storageEnabled: false, + blockchainEnabled: false, + ensEnabled: false + }; + } + + componentDidMount() { + EmbarkJS.onReady((err) => { + this.setState({blockchainEnabled: true}); + if (err) { + // If err is not null then it means something went wrong connecting to ethereum + // you can use this to ask the user to enable metamask for e.g + return this.setState({error: err.message || err}); + } + + EmbarkJS.Messages.Providers.whisper.getWhisperVersion((err, _version) => { + if (err) { + return console.log(err); + } + this.setState({whisperEnabled: true}); + }); + + EmbarkJS.Storage.isAvailable().then((result) => { + this.setState({storageEnabled: result}); + }).catch(() => { + this.setState({storageEnabled: false}); + }); + }); + } + + _renderStatus(title, available) { + let className = available ? 'pull-right status-online' : 'pull-right status-offline'; + return + {title} + + ; + } + + handleSelect(key) { + this.setState({ activeKey: key }); + } + + render() { + const ensEnabled = EmbarkJS.Names.currentNameSystems && EmbarkJS.Names.isAvailable(); + if (this.state.error) { + return (
+
Something went wrong connecting to ethereum. Please make sure you have a node running or are using metamask to connect to the ethereum network:
+
{this.state.error}
+
); + } + return (
+

Embark - Usage Example

+ + + + + + + + + + + + + + +
); + } +} + +ReactDOM.render(, document.getElementById('app')); diff --git a/test_apps/embark_demo/app/images/.gitkeep b/test_apps/embark_demo/app/images/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test_apps/embark_demo/app/index.html b/test_apps/embark_demo/app/index.html new file mode 100644 index 00000000..55521af6 --- /dev/null +++ b/test_apps/embark_demo/app/index.html @@ -0,0 +1,12 @@ + + + Embark - SimpleStorage Demo + + + + +
+
+ + + diff --git a/test_apps/embark_demo/chains.json b/test_apps/embark_demo/chains.json new file mode 100644 index 00000000..208c2404 --- /dev/null +++ b/test_apps/embark_demo/chains.json @@ -0,0 +1,22 @@ +{ + "0x4c88925b6fabc1d138606800ff7f4fb5d90b1977624f38f99576056449a6a500": { + "contracts": { + "0x0aea975ceeaff5c320a0559708c5c6f94999421a0be61587cdece9b4542cc110": { + "name": "SimpleStorage", + "address": "0x74A18cBcd27e4652cD3FE852C5362432056E6480" + }, + "0x3043b04ad856d169c8f0b0509c0bc63192dc7edd92d6933c58708298a0e381be": { + "name": "ENSRegistry", + "address": "0x88D7fD23Fc1c96FF89BeAd9aEb24Ccca96432c63" + }, + "0x60daddeb23aae81f0807e071c25012fc78e521a3e829d2b1fcda1b8bc40d3815": { + "name": "Resolver", + "address": "0xcF1FF793d4510E1E2838642BC4B118AB14C5B1ac" + }, + "0x842276d67a5bf54ee66032015bbeb8f58ca3ce6cabf05cf7ec19b0b282c6dbc0": { + "name": "FIFSRegistrar", + "address": "0x8fcDa55C6F48A9c591eA5227837dA30B9560Ed33" + } + } + } +} diff --git a/test_apps/embark_demo/config/blockchain.js b/test_apps/embark_demo/config/blockchain.js new file mode 100644 index 00000000..f3428c71 --- /dev/null +++ b/test_apps/embark_demo/config/blockchain.js @@ -0,0 +1,99 @@ +module.exports = { + // applies to all environments + default: { + enabled: true, + rpcHost: "localhost", // HTTP-RPC server listening interface (default: "localhost") + rpcPort: 8545, // HTTP-RPC server listening port (default: 8545) + rpcCorsDomain: "auto", // Comma separated list of domains from which to accept cross origin requests (browser enforced) + // When set to "auto", Embark will automatically set the cors to the address of the webserver + wsRPC: true, // Enable the WS-RPC server + wsOrigins: "auto", // Origins from which to accept websockets requests + // When set to "auto", Embark will automatically set the cors to the address of the webserver + wsHost: "localhost", // WS-RPC server listening interface (default: "localhost") + wsPort: 8546 // WS-RPC server listening port (default: 8546) + }, + + // default environment, merges with the settings in default + // assumed to be the intended environment by `embark run` and `embark blockchain` + development: { + networkType: "custom", // Can be: testnet, rinkeby, livenet or custom, in which case, it will use the specified networkId + networkId: "1337", // Network id used when networkType is custom + isDev: true, // Uses and ephemeral proof-of-authority network with a pre-funded developer account, mining enabled + datadir: ".embark/development/datadir", // Data directory for the databases and keystore + mineWhenNeeded: true, // Uses our custom script (if isDev is false) to mine only when needed + nodiscover: true, // Disables the peer discovery mechanism (manual peer addition) + maxpeers: 0, // Maximum number of network peers (network disabled if set to 0) (default: 25) + proxy: true, // Proxy is used to present meaningful information about transactions + targetGasLimit: 8000000, // Target gas limit sets the artificial target gas floor for the blocks to mine + simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm", // Mnemonic used by the simulator to generate a wallet + simulatorBlocktime: 0, // Specify blockTime in seconds for automatic mining. Default is 0 and no auto-mining. + account: { + // numAccounts: 3, // When specified, creates accounts for use in the dapp. This option only works in the development environment, and can be used as a quick start option that bypasses the need for MetaMask in development. These accounts are unlocked and funded with the below settings. + // password: "config/development/password", // Password for the created accounts (as specified in the `numAccounts` setting). If `mineWhenNeeded` is enabled (and isDev is not), this password is used to create a development account controlled by the node. + // balance: "5 ether" // Balance to be given to the created accounts (as specified in the `numAccounts` setting) + } + }, + + // merges with the settings in default + // used with "embark run privatenet" and/or "embark blockchain privatenet" + privatenet: { + networkType: "custom", + networkId: "1337", + isDev: false, + datadir: ".embark/privatenet/datadir", + // -- mineWhenNeeded -- + // This options is only valid when isDev is false. + // Enabling this option uses our custom script to mine only when needed. + // Embark creates a development account for you (using `geth account new`) and funds the account. This account can be used for + // development (and even imported in to MetaMask). To enable correct usage, a password for this account must be specified + // in the `account > password` setting below. + // NOTE: once `mineWhenNeeded` is enabled, you must run an `embark reset` on your dApp before running + // `embark blockchain` or `embark run` for the first time. + mineWhenNeeded: true, + // -- genesisBlock -- + // This option is only valid when mineWhenNeeded is true (which is only valid if isDev is false). + // When enabled, geth uses POW to mine transactions as it would normally, instead of using POA as it does in --dev mode. + // On the first `embark blockchain or embark run` after this option is enabled, geth will create a new chain with a + // genesis block, which can be configured using the `genesisBlock` configuration option below. + genesisBlock: "config/privatenet/genesis.json", // Genesis block to initiate on first creation of a development node + nodiscover: true, + maxpeers: 0, + proxy: true, + account: { + // "address": "", // When specified, uses that address instead of the default one for the network + password: "config/privatenet/password" // Password to unlock the account + }, + targetGasLimit: 8000000, + wsHost: "localhost", + wsPort: 8546, + simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm", + simulatorBlocktime: 0 + }, + + // merges with the settings in default + // used with "embark run testnet" and/or "embark blockchain testnet" + testnet: { + networkType: "testnet", + syncMode: "light", + account: { + password: "config/testnet/password" + } + }, + + // merges with the settings in default + // used with "embark run livenet" and/or "embark blockchain livenet" + livenet: { + networkType: "livenet", + syncMode: "light", + rpcCorsDomain: "http://localhost:8000", + wsOrigins: "http://localhost:8000", + account: { + password: "config/livenet/password" + } + }, + + // you can name an environment with specific settings and then specify with + // "embark run custom_name" or "embark blockchain custom_name" + //custom_name: { + //} +}; diff --git a/test_apps/embark_demo/config/communication.js b/test_apps/embark_demo/config/communication.js new file mode 100644 index 00000000..81824825 --- /dev/null +++ b/test_apps/embark_demo/config/communication.js @@ -0,0 +1,46 @@ +module.exports = { + // default applies to all environments + default: { + enabled: true, + provider: "whisper", // Communication provider. Currently, Embark only supports whisper + available_providers: ["whisper"], // Array of available providers + }, + + // default environment, merges with the settings in default + // assumed to be the intended environment by `embark run` + development: { + connection: { + host: "localhost", // Host of the blockchain node + port: 8546, // Port of the blockchain node + type: "ws" // Type of connection (ws or rpc) + } + }, + + // merges with the settings in default + // used with "embark run privatenet" + privatenet: { + }, + + + // merges with the settings in default + // used with "embark run testnet" + testnet: { + }, + + // merges with the settings in default + // used with "embark run livenet" + livenet: { + }, + + // you can name an environment with specific settings and then specify with + // "embark run custom_name" + //custom_name: { + //} + // Use this section when you need a specific symmetric or private keys in whisper + /* + ,keys: { + symmetricKey: "your_symmetric_key",// Symmetric key for message decryption + privateKey: "your_private_key" // Private Key to be used as a signing key and for message decryption + } + */ +}; diff --git a/test_apps/embark_demo/config/contracts.js b/test_apps/embark_demo/config/contracts.js new file mode 100644 index 00000000..56643605 --- /dev/null +++ b/test_apps/embark_demo/config/contracts.js @@ -0,0 +1,72 @@ +module.exports = { + // default applies to all environments + default: { + // Blockchain node to deploy the contracts + deployment: { + host: "localhost", // Host of the blockchain node + port: 8545, // Port of the blockchain node + type: "rpc" // Type of connection (ws or rpc), + // Accounts to use instead of the default account to populate your wallet + /*,accounts: [ + { + privateKey: "your_private_key", + balance: "5 ether" // You can set the balance of the account in the dev environment + // Balances are in Wei, but you can specify the unit with its name + }, + { + privateKeyFile: "path/to/file", // Either a keystore or a list of keys, separated by , or ; + password: "passwordForTheKeystore" // Needed to decrypt the keystore file + }, + { + mnemonic: "12 word mnemonic", + addressIndex: "0", // Optionnal. The index to start getting the address + numAddresses: "1", // Optionnal. The number of addresses to get + hdpath: "m/44'/60'/0'/0/" // Optionnal. HD derivation path + } + ]*/ + }, + // order of connections the dapp should connect to + dappConnection: [ + "$WEB3", // uses pre existing web3 object if available (e.g in Mist) + "ws://localhost:8546", + "http://localhost:8545" + ], + gas: "auto", + contracts: { + SimpleStorage: { + fromIndex: 0, + args: [100] + } + } + }, + + // default environment, merges with the settings in default + // assumed to be the intended environment by `embark run` + development: { + dappConnection: [ + "ws://localhost:8546", + "http://localhost:8545", + "$WEB3" // uses pre existing web3 object if available (e.g in Mist) + ] + }, + + // merges with the settings in default + // used with "embark run privatenet" + privatenet: { + }, + + // merges with the settings in default + // used with "embark run testnet" + testnet: { + }, + + // merges with the settings in default + // used with "embark run livenet" + livenet: { + }, + + // you can name an environment with specific settings and then specify with + // "embark run custom_name" or "embark blockchain custom_name" + //custom_name: { + //} +}; diff --git a/test_apps/embark_demo/config/namesystem.js b/test_apps/embark_demo/config/namesystem.js new file mode 100644 index 00000000..05a737b9 --- /dev/null +++ b/test_apps/embark_demo/config/namesystem.js @@ -0,0 +1,39 @@ +module.exports = { + // default applies to all environments + default: { + enabled: true, + available_providers: ["ens"], + provider: "ens" + }, + + // default environment, merges with the settings in default + // assumed to be the intended environment by `embark run` + development: { + register: { + rootDomain: "eth", + subdomains: { + 'embark': '0x1a2f3b98e434c02363f3dac3174af93c1d690914' + } + } + }, + + // merges with the settings in default + // used with "embark run privatenet" + privatenet: { + }, + + // merges with the settings in default + // used with "embark run testnet" + testnet: { + }, + + // merges with the settings in default + // used with "embark run livenet" + livenet: { + }, + + // you can name an environment with specific settings and then specify with + // "embark run custom_name" or "embark blockchain custom_name" + //custom_name: { + //} +}; diff --git a/test_apps/embark_demo/config/privatenet/genesis.json b/test_apps/embark_demo/config/privatenet/genesis.json new file mode 100644 index 00000000..a67418b8 --- /dev/null +++ b/test_apps/embark_demo/config/privatenet/genesis.json @@ -0,0 +1,18 @@ +{ + "config": { + "homesteadBlock": 0, + "byzantiumBlock": 0, + "daoForkSupport": true + }, + "nonce": "0x0000000000000042", + "difficulty": "0x0", + "alloc": { + "0x3333333333333333333333333333333333333333": {"balance": "15000000000000000000"} + }, + "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x3333333333333333333333333333333333333333", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x7a1200" +} diff --git a/test_apps/embark_demo/config/privatenet/password b/test_apps/embark_demo/config/privatenet/password new file mode 100644 index 00000000..c747d679 --- /dev/null +++ b/test_apps/embark_demo/config/privatenet/password @@ -0,0 +1 @@ +dev_password diff --git a/test_apps/embark_demo/config/storage.js b/test_apps/embark_demo/config/storage.js new file mode 100644 index 00000000..1ed67215 --- /dev/null +++ b/test_apps/embark_demo/config/storage.js @@ -0,0 +1,59 @@ +module.exports = { + // default applies to all environments + default: { + enabled: true, + ipfs_bin: "ipfs", + provider: "ipfs", + available_providers: ["ipfs"], + upload: { + host: "localhost", + port: 5001 + }, + dappConnection: [ + { + provider:"ipfs", + host: "localhost", + port: 5001, + getUrl: "http://localhost:8080/ipfs/" + } + ] + // Configuration to start Swarm in the same terminal as `embark run` + /*,account: { + address: "YOUR_ACCOUNT_ADDRESS", // Address of account accessing Swarm + password: "PATH/TO/PASSWORD/FILE" // File containing the password of the account + }, + swarmPath: "PATH/TO/SWARM/EXECUTABLE" // Path to swarm executable (default: swarm)*/ + }, + + // default environment, merges with the settings in default + // assumed to be the intended environment by `embark run` + development: { + enabled: true, + provider: "ipfs", + upload: { + host: "localhost", + port: 5001, + getUrl: "http://localhost:8080/ipfs/" + } + }, + + // merges with the settings in default + // used with "embark run privatenet" + privatenet: { + }, + + // merges with the settings in default + // used with "embark run testnet" + testnet: { + }, + + // merges with the settings in default + // used with "embark run livenet" + livenet: { + }, + + // you can name an environment with specific settings and then specify with + // "embark run custom_name" + //custom_name: { + //} +}; diff --git a/test_apps/embark_demo/config/testnet/password b/test_apps/embark_demo/config/testnet/password new file mode 100644 index 00000000..414f8490 --- /dev/null +++ b/test_apps/embark_demo/config/testnet/password @@ -0,0 +1 @@ +test_password diff --git a/test_apps/embark_demo/config/webserver.js b/test_apps/embark_demo/config/webserver.js new file mode 100644 index 00000000..506490b5 --- /dev/null +++ b/test_apps/embark_demo/config/webserver.js @@ -0,0 +1,6 @@ +module.exports = { + enabled: true, + host: "localhost", + openBrowser: true, + port: 8000 +}; diff --git a/test_apps/embark_demo/contracts/simple_storage.sol b/test_apps/embark_demo/contracts/simple_storage.sol new file mode 100644 index 00000000..00b15548 --- /dev/null +++ b/test_apps/embark_demo/contracts/simple_storage.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.4.25; + +contract SimpleStorage { + uint public storedData; + address owner; + + constructor(uint initialValue) public { + storedData = initialValue; + owner = msg.sender; + } + + function set(uint x) public { + storedData = x; + require(msg.sender != owner); + storedData = x + 2; + } + + function get() public view returns (uint retVal) { + return storedData; + } + +} diff --git a/test_apps/embark_demo/embark.json b/test_apps/embark_demo/embark.json new file mode 100644 index 00000000..b6a611cd --- /dev/null +++ b/test_apps/embark_demo/embark.json @@ -0,0 +1,23 @@ +{ + "contracts": ["contracts/**"], + "app": { + "js/dapp.js": ["app/dapp.js"], + "index.html": "app/index.html", + "images/": ["app/images/**"] + }, + "buildDir": "dist/", + "config": "config/", + "versions": { + "web3": "1.0.0-beta", + "solc": "0.4.25", + "ipfs-api": "17.2.4" + }, + "plugins": { + }, + "options": { + "solc": { + "optimize": true, + "optimize-runs": 200 + } + } +} diff --git a/test_apps/embark_demo/package-lock.json b/test_apps/embark_demo/package-lock.json new file mode 100644 index 00000000..6c2ea9a2 --- /dev/null +++ b/test_apps/embark_demo/package-lock.json @@ -0,0 +1,278 @@ +{ + "name": "app_name", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + } + } + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "dom-helpers": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz", + "integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg==" + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "keycode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz", + "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ=" + }, + "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" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "prop-types-extra": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.0.tgz", + "integrity": "sha512-QFyuDxvMipmIVKD2TwxLVPzMnO4e5oOf1vr3tJIomL8E7d0lr6phTHd5nkPhFIzTD1idBLLEPeylL9g+rrTzRg==", + "requires": { + "react-is": "^16.3.2", + "warning": "^3.0.0" + } + }, + "react": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/react/-/react-16.4.2.tgz", + "integrity": "sha512-dMv7YrbxO4y2aqnvA7f/ik9ibeLSHQJTI6TrYAenPSaQ6OXfb+Oti+oJiy8WBxgRzlKatYqtCjphTgDSCEiWFg==", + "requires": { + "fbjs": "^0.8.16", + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.0" + } + }, + "react-bootstrap": { + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.32.1.tgz", + "integrity": "sha512-RbfzKUbsukWsToWqGHfCCyMFq9QQI0TznutdyxyJw6dih2NvIne25Mrssg8LZsprqtPpyQi8bN0L0Fx3fUsL8Q==", + "requires": { + "babel-runtime": "^6.11.6", + "classnames": "^2.2.5", + "dom-helpers": "^3.2.0", + "invariant": "^2.2.1", + "keycode": "^2.1.2", + "prop-types": "^15.5.10", + "prop-types-extra": "^1.0.1", + "react-overlays": "^0.8.0", + "react-prop-types": "^0.4.0", + "react-transition-group": "^2.0.0", + "uncontrollable": "^4.1.0", + "warning": "^3.0.0" + } + }, + "react-dom": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.4.2.tgz", + "integrity": "sha512-Usl73nQqzvmJN+89r97zmeUpQDKDlh58eX6Hbs/ERdDHzeBzWy+ENk7fsGQ+5KxArV1iOFPT46/VneklK9zoWw==", + "requires": { + "fbjs": "^0.8.16", + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.0" + } + }, + "react-is": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.4.2.tgz", + "integrity": "sha512-rI3cGFj/obHbBz156PvErrS5xc6f1eWyTwyV4mo0vF2lGgXgS+mm7EKD5buLJq6jNgIagQescGSVG2YzgXt8Yg==" + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-overlays": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.8.3.tgz", + "integrity": "sha512-h6GT3jgy90PgctleP39Yu3eK1v9vaJAW73GOA/UbN9dJ7aAN4BTZD6793eI1D5U+ukMk17qiqN/wl3diK1Z5LA==", + "requires": { + "classnames": "^2.2.5", + "dom-helpers": "^3.2.1", + "prop-types": "^15.5.10", + "prop-types-extra": "^1.0.1", + "react-transition-group": "^2.2.0", + "warning": "^3.0.0" + } + }, + "react-prop-types": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/react-prop-types/-/react-prop-types-0.4.0.tgz", + "integrity": "sha1-+ZsL+0AGkpya8gUefBQUpcdbk9A=", + "requires": { + "warning": "^3.0.0" + } + }, + "react-transition-group": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.4.0.tgz", + "integrity": "sha512-Xv5d55NkJUxUzLCImGSanK8Cl/30sgpOEMGc5m86t8+kZwrPxPCPcFqyx83kkr+5Lz5gs6djuvE5By+gce+VjA==", + "requires": { + "dom-helpers": "^3.3.1", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "ua-parser-js": { + "version": "0.7.18", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz", + "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA==" + }, + "uncontrollable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-4.1.0.tgz", + "integrity": "sha1-4DWCkSUuGGUiLZCTmxny9J+Bwak=", + "requires": { + "invariant": "^2.1.0" + } + }, + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + } + } +} diff --git a/test_apps/embark_demo/package.json b/test_apps/embark_demo/package.json new file mode 100644 index 00000000..b470aa91 --- /dev/null +++ b/test_apps/embark_demo/package.json @@ -0,0 +1,17 @@ +{ + "name": "app_name", + "version": "0.0.1", + "description": "", + "main": "Gruntfile.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "homepage": "", + "dependencies": { + "react": "^16.3.2", + "react-bootstrap": "0.32.1", + "react-dom": "^16.3.2" + } +} diff --git a/test_apps/embark_demo/test/simple_storage_spec.js b/test_apps/embark_demo/test/simple_storage_spec.js new file mode 100644 index 00000000..aa09607d --- /dev/null +++ b/test_apps/embark_demo/test/simple_storage_spec.js @@ -0,0 +1,41 @@ +/*global contract, config, it, assert*/ +const SimpleStorage = require('Embark/contracts/SimpleStorage'); + +let accounts; + +// For documentation please see https://embark.status.im/docs/contracts_testing.html +config({ + //deployment: { + // accounts: [ + // // you can configure custom accounts with a custom balance + // // see https://embark.status.im/docs/contracts_testing.html#Configuring-accounts + // ] + //}, + contracts: { + "SimpleStorage": { + args: [100] + } + } +}, (_err, web3_accounts) => { + accounts = web3_accounts +}); + +contract("SimpleStorage", function () { + this.timeout(0); + + it("should set constructor value", async function () { + let result = await SimpleStorage.methods.storedData().call(); + assert.strictEqual(parseInt(result, 10), 100); + }); + + it("set storage value", async function () { + await SimpleStorage.methods.set(150).send(); + let result = await SimpleStorage.methods.get().call(); + assert.strictEqual(parseInt(result, 10), 150); + }); + + it("should have account with balance", async function() { + let balance = await web3.eth.getBalance(accounts[0]); + assert.ok(parseInt(balance, 10) > 0); + }); +}); diff --git a/test_apps/test_app/app/contracts/simple_storage.sol b/test_apps/test_app/app/contracts/simple_storage.sol index 43bd0d4e..cf3bafd1 100644 --- a/test_apps/test_app/app/contracts/simple_storage.sol +++ b/test_apps/test_app/app/contracts/simple_storage.sol @@ -1,46 +1,22 @@ -pragma solidity ^0.4.17; +pragma solidity ^0.4.25; -import "ownable.sol"; - -library Assert { - event TestEvent(bool passed, string message); - - function triggerEvent(bool passed, string message) internal { - emit TestEvent(passed, message); - } -} - -contract SimpleStorage is Ownable { +contract SimpleStorage { uint public storedData; - address public registar; - event EventOnSet2(bool passed, string message); - - function() public payable { } + address owner; constructor(uint initialValue) public { storedData = initialValue; + owner = msg.sender; } function set(uint x) public { storedData = x; - Assert.triggerEvent(true, "hi"); - } - - function set2(uint x) public onlyOwner { - storedData = x; - emit EventOnSet2(true, "hi"); + require(msg.sender == 0x0); + storedData = x + 2; } function get() public view returns (uint retVal) { return storedData; } - function getS() public pure returns (string d) { - return "hello"; - } - - function setRegistar(address x) public { - registar = x; - } - } diff --git a/test_apps/test_app/app/contracts/simple_storage_test.sol b/test_apps/test_app/app/contracts/simple_storage_test.sol new file mode 100644 index 00000000..709a6691 --- /dev/null +++ b/test_apps/test_app/app/contracts/simple_storage_test.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.4.25; + +import "ownable.sol"; + +contract SimpleStorageTest is Ownable { + uint public storedData; + address owner; + + constructor(uint initialValue) public { + storedData = initialValue; + owner = msg.sender; + } + + function set(uint x) public onlyOwner { + storedData = x; + require(msg.sender != owner); + storedData = x + 2; + } + + function test(uint x) public { + uint value = 1; + assembly { + let a := 1 + let b := 2 + revert(0, 0) + } + value = 2; + } + + function get() public view returns (uint retVal) { + return storedData; + } + +} diff --git a/test_apps/test_app/app/js/index.js b/test_apps/test_app/app/js/index.js index 7859f119..85f9d6a2 100644 --- a/test_apps/test_app/app/js/index.js +++ b/test_apps/test_app/app/js/index.js @@ -4,7 +4,10 @@ import React, { Component } from 'react'; import EmbarkJS from 'Embark/EmbarkJS'; import SimpleStorage from 'Embark/contracts/SimpleStorage'; import Test from 'Embark/contracts/Test'; -import Assert from 'Embark/contracts/Assert'; +//import Assert from 'Embark/contracts/Assert'; + +import SimpleStorageTest from 'Embark/contracts/SimpleStorageTest'; +window.SimpleStorageTest = SimpleStorageTest import ReactDOM from 'react-dom'; @@ -23,7 +26,7 @@ import { Navbar, Jumbotron, Button } from 'react-bootstrap'; window.EmbarkJS = EmbarkJS; window.SimpleStorage = SimpleStorage; window.Test = Test; -window.Assert = Assert; +//window.Assert = Assert; window.React = React; diff --git a/test_apps/test_app/config/contracts.js b/test_apps/test_app/config/contracts.js index 61d2031e..c4f3c743 100644 --- a/test_apps/test_app/config/contracts.js +++ b/test_apps/test_app/config/contracts.js @@ -3,7 +3,13 @@ module.exports = { deployment: { host: "localhost", port: 8546, - type: "ws" + type: "ws", + accounts: [ + { + mnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm", + balance: "5 ether" + } + ] }, dappConnection: [ "ws://localhost:8546", @@ -17,6 +23,9 @@ module.exports = { Ownable: { deploy: false }, + SimpleStorageTest: { + args: [100] + }, SimpleStorage: { fromIndex: 0, args: [100], diff --git a/test_apps/test_app/embark.json b/test_apps/test_app/embark.json index a4c2f1d2..b4567493 100644 --- a/test_apps/test_app/embark.json +++ b/test_apps/test_app/embark.json @@ -15,7 +15,7 @@ "buildDir": "dist/", "config": "config/", "versions": { - "solc": "0.4.24", + "solc": "0.4.25", "web3": "1.0.0-beta", "ipfs-api": "17.2.7" }, diff --git a/test_apps/test_app/test.file b/test_apps/test_app/test.file new file mode 100755 index 00000000..e592c1f4 Binary files /dev/null and b/test_apps/test_app/test.file differ