From 8deda6e697487e9128c200c6209d3d7982afa576 Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Thu, 26 Apr 2018 00:32:54 +0530 Subject: [PATCH 1/9] clear unnecessary logging --- lib/web3/methods.js | 6 ++++-- lib/web3/web3.js | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/web3/methods.js b/lib/web3/methods.js index 2891172..b55988e 100644 --- a/lib/web3/methods.js +++ b/lib/web3/methods.js @@ -81,7 +81,7 @@ export default class Web3Helpers { } async getSyncStat() { try { - return this.web3.eth.isSyncing(); + return await this.web3.eth.isSyncing(); } catch(e) { throw e; } @@ -162,13 +162,15 @@ export default class Web3Helpers { } async call({...arguments}) { console.log("%c Web3 calling functions... ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); + console.log(arguments); const coinbase = arguments.coinbase; const password = arguments.password; const contract = arguments.contract; const abiItem = arguments.abiItem; var params = arguments.params || []; - this.web3.eth.defaultAccount = coinbase; + //this.web3.eth.defaultAccount = coinbase; + console.log(coinbase); try { // Prepare params for call params = params.map(param => { diff --git a/lib/web3/web3.js b/lib/web3/web3.js index 8d4b37b..5971947 100644 --- a/lib/web3/web3.js +++ b/lib/web3/web3.js @@ -270,7 +270,6 @@ export default class Web3Env { var sources = {}; sources[filename] = { content: editor.getText() } sources = await combineSource(dir, sources); - console.log(sources); try { // Reset redux store this.store.dispatch({ type: SET_COMPILED, payload: null }); From c979403a2966a874df0a6f3d9d673b92145b0184 Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Mon, 7 May 2018 04:20:23 +0530 Subject: [PATCH 2/9] add web3Utils & contracts --- contracts/main.sol | 18 +++ contracts/mortal.sol | 12 ++ lib/components/FunctionABI/index.js | 9 +- lib/components/TabView/index.js | 7 + lib/components/TxAnalyzer/index.js | 8 +- lib/components/Web3Utilities/index.js | 209 ++++++++++++++++++++++++++ lib/web3/methods.js | 134 ++++++++++++++--- 7 files changed, 373 insertions(+), 24 deletions(-) create mode 100644 contracts/main.sol create mode 100644 contracts/mortal.sol create mode 100644 lib/components/Web3Utilities/index.js diff --git a/contracts/main.sol b/contracts/main.sol new file mode 100644 index 0000000..8b040c8 --- /dev/null +++ b/contracts/main.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.23; +import '../contracts/mortal.sol'; + +contract Main is Mortal { + mapping (bytes32 => string) public fiddle_data; + event NewFiddle(bytes32 indexed _id); + + // share some given input + function share(string _code) public { + bytes32 _id = keccak256(msg.sender, _code); + fiddle_data[_id] = _code; + emit NewFiddle(_id); + } + // get code for given bytes32 id + function get_fiddle(bytes32 _id) view public returns (string) { + return fiddle_data[_id]; + } +} diff --git a/contracts/mortal.sol b/contracts/mortal.sol new file mode 100644 index 0000000..51d1631 --- /dev/null +++ b/contracts/mortal.sol @@ -0,0 +1,12 @@ +pragma solidity ^0.4.18; + +contract Mortal { + /* Define variable owner of the type address */ + address owner; + + /* This function is executed at initialization and sets the owner of the contract */ + function mortal() public { owner = msg.sender; } + + /* Function to recover the funds on the contract */ + function kill() public { if (msg.sender == owner) selfdestruct(owner); } +} diff --git a/lib/components/FunctionABI/index.js b/lib/components/FunctionABI/index.js index 72a3054..a63e2c8 100644 --- a/lib/components/FunctionABI/index.js +++ b/lib/components/FunctionABI/index.js @@ -37,7 +37,8 @@ class FunctionABI extends React.Component { const contract = instances[contractName]; try { const result = await this.helpers.call({ coinbase, password, contract, abiItem }); - this.helpers.showOutput({ address: contract.options.address, data: result }); + const block = await this.helpers.getBlock(result.blockNumber); + this.helpers.showOutput({ address: contract.options.address, data: result, block: block }); } catch(e) { console.log(e); this.helpers.showPanelError(e); @@ -54,7 +55,13 @@ class FunctionABI extends React.Component { } } const result = await this.helpers.call({ coinbase, password, contract, abiItem: methodItem, params }); + if(result.blockNumber) { + const block = await this.helpers.getBlock(result.blockNumber); + this.helpers.showOutput({ address: contract.options.address, data: result, block: block }); + return; + } this.helpers.showOutput({ address: contract.options.address, data: result }); + return; } catch (e) { console.log(e); this.helpers.showPanelError(e); diff --git a/lib/components/TabView/index.js b/lib/components/TabView/index.js index 4c58f86..553fec9 100644 --- a/lib/components/TabView/index.js +++ b/lib/components/TabView/index.js @@ -21,6 +21,7 @@ import Contracts from '../Contracts' import TxAnalyzer from '../TxAnalyzer' import Events from '../Events' import NodeControl from '../NodeControl' +import Web3Utilities from '../Web3Utilities' class TabView extends React.Component { constructor(props) { @@ -79,6 +80,9 @@ class TabView extends React.Component { } + +
Web3 Utilities
+
Node
@@ -97,6 +101,9 @@ class TabView extends React.Component { + + + diff --git a/lib/components/TxAnalyzer/index.js b/lib/components/TxAnalyzer/index.js index 0185ab5..0ee3147 100644 --- a/lib/components/TxAnalyzer/index.js +++ b/lib/components/TxAnalyzer/index.js @@ -80,7 +80,13 @@ class TxAnalyzer extends React.Component {
- +
diff --git a/lib/components/Web3Utilities/index.js b/lib/components/Web3Utilities/index.js new file mode 100644 index 0000000..f2c6427 --- /dev/null +++ b/lib/components/Web3Utilities/index.js @@ -0,0 +1,209 @@ +'use babel' +// Copyright 2018 Etheratom Authors +// This file is part of Etheratom. + +// Etheratom is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Etheratom is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Etheratom. If not, see . +import React from 'react' +import { connect } from 'react-redux' +import { Collapse } from 'react-collapse' +import ReactJson from 'react-json-view' +import VirtualList from 'react-tiny-virtual-list' + +class Web3Utilities extends React.Component { + constructor(props) { + super(props); + this.helpers = props.helpers; + this.state = { + input: null, + output: null + }; + this._hexToUtf8 = this._hexToUtf8.bind(this); + this._handleInputChange = this._handleInputChange.bind(this); + this._toHex = this._toHex.bind(this); + this._toChecksumAddress = this._toChecksumAddress.bind(this); + this._hexToBytes = this._hexToBytes.bind(this); + this._hexToNumber = this._hexToNumber.bind(this); + this._bytesToHex = this._bytesToHex.bind(this); + this._padLeft32 = this._padLeft32.bind(this); + this._padRight32 = this._padRight32.bind(this); + this._padLeft64 = this._padLeft64.bind(this); + this._padRight64 = this._padRight64.bind(this); + this._hexToAscii = this._hexToAscii.bind(this); + } + _handleInputChange(event) { + this.setState({ input: event.target.value }); + } + async _hexToUtf8() { + try { + const { input } = this.state; + const decoded = await this.helpers.hexToUtf8(input); + this.setState({ output: decoded }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _hexToAscii() { + try { + const { input } = this.state; + const ascii = await this.helpers.hexToAscii(input); + this.setState({ output: ascii }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _toHex() { + try { + const { input } = this.state; + const encoded = await this.helpers.toHex(input); + this.setState({ output: encoded }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _toChecksumAddress() { + try { + const { input } = this.state; + const chkSmAddr = await this.helpers.toChecksumAddress(input); + this.setState({ output: chkSmAddr }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _hexToNumber() { + try { + const { input } = this.state; + const number = await this.helpers.hexToNumber(input); + this.setState({ output: number }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _hexToBytes() { + try { + const { input } = this.state; + const bytes = await this.helpers.hexToBytes(input); + this.setState({ output: bytes }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _bytesToHex() { + try { + const { input } = this.state; + const hex = await this.helpers.bytesToHex(input); + this.setState({ output: hex }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _padLeft32() { + try { + const { input } = this.state; + const leftPadded = await this.helpers.padLeft(input, 32); + this.setState({ output: leftPadded }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _padRight32() { + try { + const { input } = this.state; + const rightPadded = await this.helpers.padRight(input, 32); + this.setState({ output: rightPadded }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _padLeft64() { + try { + const { input } = this.state; + const leftPadded = await this.helpers.padLeft(input, 64); + this.setState({ output: leftPadded }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + async _padRight64() { + try { + const { input } = this.state; + const rightPadded = await this.helpers.padRight(input, 64); + this.setState({ output: rightPadded }); + } catch(e) { + this.helpers.showPanelError(e); + } + } + render() { + return ( +
+
+
+ +
+
+ + + + + + + + + + + +
+
+ { + this.state.output && +
+
{this.state.output}
+
+ } +
+ ); + } +} +const mapStateToProps = () => { + return { }; +} + +export default connect(mapStateToProps, {})(Web3Utilities); diff --git a/lib/web3/methods.js b/lib/web3/methods.js index b55988e..c0a7700 100644 --- a/lib/web3/methods.js +++ b/lib/web3/methods.js @@ -18,8 +18,6 @@ // methods.js are collection of various functions used to execute calls on web3 import Solc from 'solc' import Web3 from 'web3' -import ethJSABI from 'ethereumjs-abi' -import EthJSTX from 'ethereumjs-tx' import EventEmitter from 'events' import { MessagePanelView, PlainMessageView, LineMessageView } from 'atom-message-panel' @@ -163,14 +161,13 @@ export default class Web3Helpers { async call({...arguments}) { console.log("%c Web3 calling functions... ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); console.log(arguments); + const that = this; const coinbase = arguments.coinbase; const password = arguments.password; const contract = arguments.contract; const abiItem = arguments.abiItem; var params = arguments.params || []; - //this.web3.eth.defaultAccount = coinbase; - console.log(coinbase); try { // Prepare params for call params = params.map(param => { @@ -185,6 +182,7 @@ export default class Web3Helpers { // Handle fallback if(abiItem.type === 'fallback') { + console.log("%c Calling fallback function... ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); if(password) { await this.web3.eth.personal.unlockAccount(coinbase, password); } @@ -193,25 +191,31 @@ export default class Web3Helpers { to: contract.options.address, value: abiItem.payableValue || 0 }) + console.log(result); return result; } - - if(abiItem.constant === false || abiItem.payable === true) { - if(password) { - await this.web3.eth.personal.unlockAccount(coinbase, password); - } - if(params.length > 0) { - const result = await contract.methods[abiItem.name](...params).send({ from: coinbase, value: abiItem.payableValue }); - return result; - } - const result = await contract.methods[abiItem.name]().send({ from: coinbase, value: abiItem.payableValue }); - return result; - } - if(params.length > 0) { + // Handle constant calls + if(abiItem.constant === true) { + console.log("%c Calling constant function default... ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); const result = await contract.methods[abiItem.name](...params).call({ from: coinbase }); + console.log(result); return result; } - const result = await contract.methods[abiItem.name]().call({ from: coinbase }); + // handle default payable non-constant methods + if(password) { + await this.web3.eth.personal.unlockAccount(coinbase, password); + } + console.log("%c Calling payable function... ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); + const result = await contract.methods[abiItem.name](...params).send({ from: coinbase, value: abiItem.payableValue }) + .on('transactionHash', (hash) => { + // show method tx hash & pending loader + console.log(hash); + that.showPanelTx(hash); + }) + .on('receipt', (receipt) => { + return receipt; + }) + console.log(result); return result; } catch(e) { @@ -240,17 +244,33 @@ export default class Web3Helpers { messages.attach(); messages.add(new PlainMessageView({ message: err_message, className: 'red-message' })); } + showPanelTx(txHash) { + const messages = new MessagePanelView({ title: 'Etheratom transaction' }); + messages.attach(); + messages.add(new PlainMessageView({ message: 'New transaction: ' + txHash, className: 'green-message' })); + return; + } showOutput({...arguments}) { const address = arguments.address; const data = arguments.data; + const block = arguments.block; + const messages = new MessagePanelView({ title: 'Etheratom output' }); messages.attach(); messages.add(new PlainMessageView({ message: 'Contract address: ' + address, className: 'green-message' })); + if(block) { + const rawMessage = `
Block:
${JSON.stringify(block, null, 4)}
`; + messages.add(new PlainMessageView({ + message: rawMessage, + raw: true, + className: 'green-message' + })); + } if(data instanceof Object) { - const rawMessage = `
Contract output:
${JSON.stringify(data, null, 4)}
` + const rawMessage = `
Contract output:
${JSON.stringify(data, null, 4)}
`; messages.add(new PlainMessageView({ message: rawMessage, raw: true, @@ -286,21 +306,91 @@ export default class Web3Helpers { async getAccounts() { try { return await this.web3.eth.getAccounts(); - } catch (e) { + } catch(e) { throw e; } } async getMining() { try { return await this.web3.eth.isMining(); - } catch (e) { + } catch(e) { throw e; } } async getHashrate() { try { return await this.web3.eth.getHashrate(); - } catch (e) { + } catch(e) { + throw e; + } + } + async getBlock(blockNumber) { + try { + return await this.web3.eth.getBlock(blockNumber); + } catch(e) { + throw e; + } + } + async hexToUtf8(input) { + try { + return await this.web3.utils.hexToUtf8(input); + } catch(e) { + throw e; + } + } + async hexToAscii(input) { + try { + return await this.web3.utils.hexToAscii(input); + } catch(e) { + throw e; + } + } + async toHex(input) { + try { + return await this.web3.utils.toHex(input); + } catch(e) { + throw e; + } + } + async toChecksumAddress(input) { + try { + return await this.web3.utils.toChecksumAddress(input); + } catch(e) { + throw e; + } + } + async hexToNumber(input) { + try { + return await this.web3.utils.hexToNumber(input); + } catch(e) { + throw e; + } + } + async hexToBytes(input) { + try { + return await this.web3.utils.hexToBytes(input); + } catch(e) { + throw e; + } + } + async bytesToHex(input) { + try { + return await this.web3.utils.bytesToHex(input); + } catch(e) { + throw e; + } + } + async padLeft(input, padding) { + try { + return await this.web3.utils.padLeft(input, padding); + } catch(e) { + throw e; + } + } + async padRight(input, padding) { + try { + return await this.web3.utils.padRight(input, padding); + } catch(e) { throw e; } } From 68a3054bcefedbb0a1d990bdfc72bb4019f1a2bf Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Mon, 7 May 2018 20:38:12 +0530 Subject: [PATCH 3/9] Add share box --- lib/components/ShareBox/index.js | 109 +++++++++++++++++++++++++++++++ lib/ethereum-interface-view.js | 7 ++ lib/web3/methods.js | 48 +++++++++++++- lib/web3/view.js | 2 + lib/web3/web3.js | 8 +-- styles/atom-solidity.less | 4 ++ 6 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 lib/components/ShareBox/index.js diff --git a/lib/components/ShareBox/index.js b/lib/components/ShareBox/index.js new file mode 100644 index 0000000..8057336 --- /dev/null +++ b/lib/components/ShareBox/index.js @@ -0,0 +1,109 @@ +'use babel' +// Copyright 2018 Etheratom Authors +// This file is part of Etheratom. + +// Etheratom is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Etheratom is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Etheratom. If not, see . +import React from 'react' +import { connect } from 'react-redux' + +class ShareBox extends React.Component { + constructor(props) { + super(props); + this.helpers = props.helpers; + this.state = { + shared: false, + shareLink: null, + gas: 500000 + } + this._handleShare = this._handleShare.bind(this); + this._handleLoad = this._handleLoad.bind(this); + this._handleCopy = this._handleCopy.bind(this); + this._handleChange = this._handleChange.bind(this); + this._handleGasChange = this._handleGasChange.bind(this); + } + async _handleShare() { + const that = this; + const { coinbase, password } = this.props; + const { gas } = this.state; + let code = null; + atom.workspace.observeTextEditors(async (editor) => { + code = editor.getText(); + return; + }); + // Will upload code to smart contract + const shared = await that.helpers.shareCode(coinbase, password, code, gas); + console.log(shared); + //const shared = 'abcd'; + that.setState({ shared: true, shareLink: shared }); + return; + } + async _handleLoad() { + // Will load code from smart contract + } + async _handleCopy() { + const { shareLink } = this.state; + atom.clipboard.write(shareLink); + } + async _handleChange(event) { + this.setState({ shared: false, shareLink: event.target.value }); + } + async _handleGasChange(event) { + this.setState({ gas: event.target.value }); + } + render() { + const { shareLink, shared, gas } = this.state; + return ( +
+ + { + !shared && + + } + + { + shared && + + } + +
+ ); + } +} + +const mapStateToProps = ({ account }) => { + const { coinbase, password } = account; + return { coinbase, password }; +} + +export default connect(mapStateToProps, {})(ShareBox); diff --git a/lib/ethereum-interface-view.js b/lib/ethereum-interface-view.js index 8d9d637..6d15abf 100644 --- a/lib/ethereum-interface-view.js +++ b/lib/ethereum-interface-view.js @@ -104,6 +104,13 @@ export default AtomSolidityView = (() => { buttonNode.appendChild(compileButton); mainNode.appendChild(buttonNode); + shareNode = document.createElement('div'); + att = document.createAttribute('id'); + att.value = 'share-box'; + shareNode.setAttributeNode(att); + shareNode.classList.add('block'); + mainNode.appendChild(shareNode); + tabNode = document.createElement('div'); att = document.createAttribute('id'); att.value = 'tab_view'; diff --git a/lib/web3/methods.js b/lib/web3/methods.js index c0a7700..ea47798 100644 --- a/lib/web3/methods.js +++ b/lib/web3/methods.js @@ -105,7 +105,7 @@ export default class Web3Helpers { try { const gasPrice = await this.web3.eth.getGasPrice(); const contract = await new this.web3.eth.Contract(abi, { - from: this.web3.eth.defaultAccount, + from: coinbase, data: '0x' + code, gas: this.web3.utils.toHex(gasSupply), gasPrice: this.web3.utils.toHex(gasPrice) @@ -394,4 +394,50 @@ export default class Web3Helpers { throw e; } } + // Code sharing + async shareCode(coinbase, password, code, gas) { + const that = this; + const bytecode = '608060405234801561001057600080fd5b50610507806100206000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166327b53401811461007157806341c0e1b5146100fe57806348c5e7bc146101155780637f630b4c1461012d578063f1eae25c14610186575b600080fd5b34801561007d57600080fd5b5061008960043561019b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100c35781810151838201526020016100ab565b50505050905090810190601f1680156100f05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561010a57600080fd5b50610113610235565b005b34801561012157600080fd5b50610089600435610276565b34801561013957600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526101139436949293602493928401919081908401838280828437509497506103199650505050505050565b34801561019257600080fd5b50610113610409565b60016020818152600092835260409283902080548451600294821615610100026000190190911693909304601f810183900483028401830190945283835291929083018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b505050505081565b6000543373ffffffffffffffffffffffffffffffffffffffff908116911614156102745760005473ffffffffffffffffffffffffffffffffffffffff16ff5b565b60008181526001602081815260409283902080548451600260001995831615610100029590950190911693909304601f8101839004830284018301909452838352606093909183018282801561030d5780601f106102e25761010080835404028352916020019161030d565b820191906000526020600020905b8154815290600101906020018083116102f057829003601f168201915b50505050509050919050565b60003382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140182805190602001908083835b6020831061038d5780518252601f19909201916020918201910161036e565b51815160209384036101000a600019018019909216911617905260408051929094018290039091206000818152600183529390932088519397506103d996509450870192506104409050565b5060405181907f0f66da887a9c57b75a06c56ae415879ac0fa76f7e5fcb12af540c94fe85c2e5d90600090a25050565b6000805473ffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff16179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061048157805160ff19168380011785556104ae565b828001600101855582156104ae579182015b828111156104ae578251825591602001919060010190610493565b506104ba9291506104be565b5090565b6104d891905b808211156104ba57600081556001016104c4565b905600a165627a7a723058207d63bc55d7869b380b4dc0893827f66269543a40ff3b44414c2368d40e7c81000029'; + const abi = [{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"fiddle_data","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"bytes32"}],"name":"get_fiddle","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"string"}],"name":"share","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"mortal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_id","type":"bytes32"}],"name":"NewFiddle","type":"event"}]; + + return new Promise(async (resolve, reject) => { + if(!coinbase) { + const error = new Error('No coinbase selected!'); + reject(error); + } + try { + if(password) { + const unlocked = await that.web3.eth.personal.unlockAccount(coinbase, password); + } + const maxGas = await that.getGasLimit(); + const minGas = await that.getGasEstimate(coinbase, bytecode); + const gasPrice = await that.web3.eth.getGasPrice(); + const contract = await new that.web3.eth.Contract(abi, '0xc17744c2F1B77907574b7D49A00319Aa47e828B8', { + from: coinbase, + data: '0x' + bytecode, + gas: that.web3.utils.toHex(gas), + gasPrice: that.web3.utils.toHex(gasPrice) + }); + console.log(contract); + contract.events.NewFiddle() + .on('data', data => { + console.log("Got new fiddle..."); + const fiddleId = data.returnValues._id; + console.log(fiddleId); + resolve(fiddleId); + }) + contract.methods.share(code).send({ from: coinbase }) + .on('transactionHash', txHash => { + console.log('transactionHash:'); + console.log(txHash); + }) + .on('error', e => { + reject(e); + }) + } catch (e) { + console.log(e); + reject(e); + } + }); + } } diff --git a/lib/web3/view.js b/lib/web3/view.js index cb3d77b..d9a9c75 100644 --- a/lib/web3/view.js +++ b/lib/web3/view.js @@ -24,6 +24,7 @@ import ClientSelector from '../components/ClientSelector' import TabView from '../components/TabView' import CoinbaseView from '../components/CoinbaseView' import CompileBtn from '../components/CompileBtn' +import ShareBox from '../components/ShareBox' import ErrorView from '../components/ErrorView' import { SET_ACCOUNTS, SET_COINBASE } from '../actions/types' @@ -52,6 +53,7 @@ export default class View { } createButtonsView() { ReactDOM.render(, document.getElementById('compile_btn')); + ReactDOM.render(, document.getElementById('share-box')); } createTabView() { ReactDOM.render(, document.getElementById('tab_view')); diff --git a/lib/web3/web3.js b/lib/web3/web3.js index 5971947..65bab1b 100644 --- a/lib/web3/web3.js +++ b/lib/web3/web3.js @@ -142,8 +142,8 @@ export default class Web3Env { // newBlockHeaders subscriber this.web3.eth.subscribe('newBlockHeaders') .on("data", (blocks) => { - console.log("%c newBlockHeaders:data ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); - console.log(blocks); + //console.log("%c newBlockHeaders:data ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); + //console.log(blocks); }) .on('error', (e) => { console.log("%c newBlockHeaders:error ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); @@ -152,8 +152,8 @@ export default class Web3Env { // pendingTransactions subscriber this.web3.eth.subscribe('pendingTransactions') .on("data", (transaction) => { - console.log("%c pendingTransactions:data ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); - console.log(transaction); + //console.log("%c pendingTransactions:data ", 'background: rgba(36, 194, 203, 0.3); color: #EF525B'); + //console.log(transaction); this.store.dispatch({ type: ADD_PENDING_TRANSACTION, payload: transaction }); }) .on('error', (e) => { diff --git a/styles/atom-solidity.less b/styles/atom-solidity.less index a08dea7..b576778 100644 --- a/styles/atom-solidity.less +++ b/styles/atom-solidity.less @@ -312,3 +312,7 @@ .no-header { text-align: center; } + +.gas-supply { + width: 25%; +} From 038f9ca0624c700e970bf77bbf87148a48d4c710 Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Tue, 8 May 2018 08:34:40 +0530 Subject: [PATCH 4/9] Show snippet code --- lib/components/ShareBox/index.js | 100 +++++++++++++++++++------------ lib/components/TabView/index.js | 7 +++ lib/ethereum-interface-view.js | 4 +- lib/web3/methods.js | 29 +++++++-- lib/web3/view.js | 2 - 5 files changed, 96 insertions(+), 46 deletions(-) diff --git a/lib/components/ShareBox/index.js b/lib/components/ShareBox/index.js index 8057336..e4588cb 100644 --- a/lib/components/ShareBox/index.js +++ b/lib/components/ShareBox/index.js @@ -24,7 +24,8 @@ class ShareBox extends React.Component { this.state = { shared: false, shareLink: null, - gas: 500000 + gas: 394504, // contract creation gas + snippet: null } this._handleShare = this._handleShare.bind(this); this._handleLoad = this._handleLoad.bind(this); @@ -32,6 +33,13 @@ class ShareBox extends React.Component { this._handleChange = this._handleChange.bind(this); this._handleGasChange = this._handleGasChange.bind(this); } + async componentWillReceiveProps(nextProps) { + const { accounts } = nextProps; + if(accounts.length > 0) { + const gasEstm = await this.helpers.getShareGasEstm(accounts[0]); + this.setState({ gas: gasEstm }); + } + } async _handleShare() { const that = this; const { coinbase, password } = this.props; @@ -41,15 +49,16 @@ class ShareBox extends React.Component { code = editor.getText(); return; }); - // Will upload code to smart contract const shared = await that.helpers.shareCode(coinbase, password, code, gas); - console.log(shared); - //const shared = 'abcd'; that.setState({ shared: true, shareLink: shared }); return; } async _handleLoad() { // Will load code from smart contract + const { shareLink } = this.state; + const { coinbase } = this.props; + const code = await this.helpers.getSnippet(coinbase, shareLink); + this.setState({ snippet: code }); } async _handleCopy() { const { shareLink } = this.state; @@ -62,48 +71,65 @@ class ShareBox extends React.Component { this.setState({ gas: event.target.value }); } render() { - const { shareLink, shared, gas } = this.state; + const { shareLink, shared, gas, snippet } = this.state; return ( -
- - { - !shared && - - } - + ); } } const mapStateToProps = ({ account }) => { - const { coinbase, password } = account; - return { coinbase, password }; + const { coinbase, password, accounts } = account; + return { coinbase, password, accounts }; } export default connect(mapStateToProps, {})(ShareBox); diff --git a/lib/components/TabView/index.js b/lib/components/TabView/index.js index 553fec9..7813ae7 100644 --- a/lib/components/TabView/index.js +++ b/lib/components/TabView/index.js @@ -22,6 +22,7 @@ import TxAnalyzer from '../TxAnalyzer' import Events from '../Events' import NodeControl from '../NodeControl' import Web3Utilities from '../Web3Utilities' +import ShareBox from '../ShareBox' class TabView extends React.Component { constructor(props) { @@ -83,6 +84,9 @@ class TabView extends React.Component {
Web3 Utilities
+ +
Share
+
Node
@@ -104,6 +108,9 @@ class TabView extends React.Component { + + + diff --git a/lib/ethereum-interface-view.js b/lib/ethereum-interface-view.js index 6d15abf..e45f90a 100644 --- a/lib/ethereum-interface-view.js +++ b/lib/ethereum-interface-view.js @@ -104,12 +104,12 @@ export default AtomSolidityView = (() => { buttonNode.appendChild(compileButton); mainNode.appendChild(buttonNode); - shareNode = document.createElement('div'); + /*shareNode = document.createElement('div'); att = document.createAttribute('id'); att.value = 'share-box'; shareNode.setAttributeNode(att); shareNode.classList.add('block'); - mainNode.appendChild(shareNode); + mainNode.appendChild(shareNode);*/ tabNode = document.createElement('div'); att = document.createAttribute('id'); diff --git a/lib/web3/methods.js b/lib/web3/methods.js index ea47798..145fc0a 100644 --- a/lib/web3/methods.js +++ b/lib/web3/methods.js @@ -24,6 +24,8 @@ import { MessagePanelView, PlainMessageView, LineMessageView } from 'atom-messag export default class Web3Helpers { constructor(web3) { this.web3 = web3; + this.bytecode = '608060405234801561001057600080fd5b50610507806100206000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166327b53401811461007157806341c0e1b5146100fe57806348c5e7bc146101155780637f630b4c1461012d578063f1eae25c14610186575b600080fd5b34801561007d57600080fd5b5061008960043561019b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100c35781810151838201526020016100ab565b50505050905090810190601f1680156100f05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561010a57600080fd5b50610113610235565b005b34801561012157600080fd5b50610089600435610276565b34801561013957600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526101139436949293602493928401919081908401838280828437509497506103199650505050505050565b34801561019257600080fd5b50610113610409565b60016020818152600092835260409283902080548451600294821615610100026000190190911693909304601f810183900483028401830190945283835291929083018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b505050505081565b6000543373ffffffffffffffffffffffffffffffffffffffff908116911614156102745760005473ffffffffffffffffffffffffffffffffffffffff16ff5b565b60008181526001602081815260409283902080548451600260001995831615610100029590950190911693909304601f8101839004830284018301909452838352606093909183018282801561030d5780601f106102e25761010080835404028352916020019161030d565b820191906000526020600020905b8154815290600101906020018083116102f057829003601f168201915b50505050509050919050565b60003382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140182805190602001908083835b6020831061038d5780518252601f19909201916020918201910161036e565b51815160209384036101000a600019018019909216911617905260408051929094018290039091206000818152600183529390932088519397506103d996509450870192506104409050565b5060405181907f0f66da887a9c57b75a06c56ae415879ac0fa76f7e5fcb12af540c94fe85c2e5d90600090a25050565b6000805473ffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff16179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061048157805160ff19168380011785556104ae565b828001600101855582156104ae579182015b828111156104ae578251825591602001919060010190610493565b506104ba9291506104be565b5090565b6104d891905b808211156104ba57600081556001016104c4565b905600a165627a7a723058207d63bc55d7869b380b4dc0893827f66269543a40ff3b44414c2368d40e7c81000029'; + this.abi = [{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"fiddle_data","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"bytes32"}],"name":"get_fiddle","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"string"}],"name":"share","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"mortal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_id","type":"bytes32"}],"name":"NewFiddle","type":"event"}]; } async compileWeb3(sources) { // compile solidity using solcjs @@ -395,10 +397,13 @@ export default class Web3Helpers { } } // Code sharing + async getShareGasEstm(coinbase) { + const { bytecode } = this; + return await this.getGasEstimate(coinbase, bytecode); + } async shareCode(coinbase, password, code, gas) { const that = this; - const bytecode = '608060405234801561001057600080fd5b50610507806100206000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166327b53401811461007157806341c0e1b5146100fe57806348c5e7bc146101155780637f630b4c1461012d578063f1eae25c14610186575b600080fd5b34801561007d57600080fd5b5061008960043561019b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100c35781810151838201526020016100ab565b50505050905090810190601f1680156100f05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561010a57600080fd5b50610113610235565b005b34801561012157600080fd5b50610089600435610276565b34801561013957600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526101139436949293602493928401919081908401838280828437509497506103199650505050505050565b34801561019257600080fd5b50610113610409565b60016020818152600092835260409283902080548451600294821615610100026000190190911693909304601f810183900483028401830190945283835291929083018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b505050505081565b6000543373ffffffffffffffffffffffffffffffffffffffff908116911614156102745760005473ffffffffffffffffffffffffffffffffffffffff16ff5b565b60008181526001602081815260409283902080548451600260001995831615610100029590950190911693909304601f8101839004830284018301909452838352606093909183018282801561030d5780601f106102e25761010080835404028352916020019161030d565b820191906000526020600020905b8154815290600101906020018083116102f057829003601f168201915b50505050509050919050565b60003382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140182805190602001908083835b6020831061038d5780518252601f19909201916020918201910161036e565b51815160209384036101000a600019018019909216911617905260408051929094018290039091206000818152600183529390932088519397506103d996509450870192506104409050565b5060405181907f0f66da887a9c57b75a06c56ae415879ac0fa76f7e5fcb12af540c94fe85c2e5d90600090a25050565b6000805473ffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff16179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061048157805160ff19168380011785556104ae565b828001600101855582156104ae579182015b828111156104ae578251825591602001919060010190610493565b506104ba9291506104be565b5090565b6104d891905b808211156104ba57600081556001016104c4565b905600a165627a7a723058207d63bc55d7869b380b4dc0893827f66269543a40ff3b44414c2368d40e7c81000029'; - const abi = [{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"fiddle_data","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"bytes32"}],"name":"get_fiddle","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"string"}],"name":"share","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"mortal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_id","type":"bytes32"}],"name":"NewFiddle","type":"event"}]; + const { bytecode, abi } = this; return new Promise(async (resolve, reject) => { if(!coinbase) { @@ -409,8 +414,6 @@ export default class Web3Helpers { if(password) { const unlocked = await that.web3.eth.personal.unlockAccount(coinbase, password); } - const maxGas = await that.getGasLimit(); - const minGas = await that.getGasEstimate(coinbase, bytecode); const gasPrice = await that.web3.eth.getGasPrice(); const contract = await new that.web3.eth.Contract(abi, '0xc17744c2F1B77907574b7D49A00319Aa47e828B8', { from: coinbase, @@ -418,7 +421,6 @@ export default class Web3Helpers { gas: that.web3.utils.toHex(gas), gasPrice: that.web3.utils.toHex(gasPrice) }); - console.log(contract); contract.events.NewFiddle() .on('data', data => { console.log("Got new fiddle..."); @@ -440,4 +442,21 @@ export default class Web3Helpers { } }); } + async getSnippet(coinbase, id) { + const { bytecode, abi } = this; + try { + const gas = await this.getGasEstimate(coinbase, bytecode); + const gasPrice = await this.web3.eth.getGasPrice(); + const contract = await new this.web3.eth.Contract(abi, '0xc17744c2F1B77907574b7D49A00319Aa47e828B8', { + from: coinbase, + data: '0x' + bytecode, + gas: this.web3.utils.toHex(gas), + gasPrice: this.web3.utils.toHex(gasPrice) + }); + const fiddle = contract.methods.get_fiddle(id).call({ from: coinbase }); + return fiddle; + } catch(e) { + throw e; + } + } } diff --git a/lib/web3/view.js b/lib/web3/view.js index d9a9c75..cb3d77b 100644 --- a/lib/web3/view.js +++ b/lib/web3/view.js @@ -24,7 +24,6 @@ import ClientSelector from '../components/ClientSelector' import TabView from '../components/TabView' import CoinbaseView from '../components/CoinbaseView' import CompileBtn from '../components/CompileBtn' -import ShareBox from '../components/ShareBox' import ErrorView from '../components/ErrorView' import { SET_ACCOUNTS, SET_COINBASE } from '../actions/types' @@ -53,7 +52,6 @@ export default class View { } createButtonsView() { ReactDOM.render(, document.getElementById('compile_btn')); - ReactDOM.render(, document.getElementById('share-box')); } createTabView() { ReactDOM.render(, document.getElementById('tab_view')); From 6ba7be4902e9632c936deb15fe0a1f600fa0aa97 Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Tue, 8 May 2018 09:27:05 +0530 Subject: [PATCH 5/9] Update readme with telegram group link --- README.md | 1 + lib/components/ShareBox/index.js | 13 ++++++++----- lib/web3/methods.js | 13 ++++--------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index bf404c7..582710f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Greenkeeper badge](https://badges.greenkeeper.io/0mkara/etheratom.svg)](https://greenkeeper.io/) [![Build Status](https://travis-ci.org/0mkara/etheratom.svg?branch=master)](https://travis-ci.org/0mkara/etheratom) +[![telegram](https://png.icons8.com/color/24/000000/telegram-app.png)](https://t.me/etheratom) Etheratom is a package for hackable Atom editor. It uses web3js to interact with Ethereum node. diff --git a/lib/components/ShareBox/index.js b/lib/components/ShareBox/index.js index e4588cb..1f17d1b 100644 --- a/lib/components/ShareBox/index.js +++ b/lib/components/ShareBox/index.js @@ -54,11 +54,14 @@ class ShareBox extends React.Component { return; } async _handleLoad() { - // Will load code from smart contract - const { shareLink } = this.state; - const { coinbase } = this.props; - const code = await this.helpers.getSnippet(coinbase, shareLink); - this.setState({ snippet: code }); + try { + const { shareLink } = this.state; + const { coinbase } = this.props; + const code = await this.helpers.getSnippet(coinbase, shareLink); + this.setState({ snippet: code }); + } catch(e) { + throw e; + } } async _handleCopy() { const { shareLink } = this.state; diff --git a/lib/web3/methods.js b/lib/web3/methods.js index 145fc0a..8eb3fe9 100644 --- a/lib/web3/methods.js +++ b/lib/web3/methods.js @@ -24,6 +24,7 @@ import { MessagePanelView, PlainMessageView, LineMessageView } from 'atom-messag export default class Web3Helpers { constructor(web3) { this.web3 = web3; + // Etheratom contract bytecode & abi this.bytecode = '608060405234801561001057600080fd5b50610507806100206000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166327b53401811461007157806341c0e1b5146100fe57806348c5e7bc146101155780637f630b4c1461012d578063f1eae25c14610186575b600080fd5b34801561007d57600080fd5b5061008960043561019b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100c35781810151838201526020016100ab565b50505050905090810190601f1680156100f05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561010a57600080fd5b50610113610235565b005b34801561012157600080fd5b50610089600435610276565b34801561013957600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526101139436949293602493928401919081908401838280828437509497506103199650505050505050565b34801561019257600080fd5b50610113610409565b60016020818152600092835260409283902080548451600294821615610100026000190190911693909304601f810183900483028401830190945283835291929083018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b505050505081565b6000543373ffffffffffffffffffffffffffffffffffffffff908116911614156102745760005473ffffffffffffffffffffffffffffffffffffffff16ff5b565b60008181526001602081815260409283902080548451600260001995831615610100029590950190911693909304601f8101839004830284018301909452838352606093909183018282801561030d5780601f106102e25761010080835404028352916020019161030d565b820191906000526020600020905b8154815290600101906020018083116102f057829003601f168201915b50505050509050919050565b60003382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140182805190602001908083835b6020831061038d5780518252601f19909201916020918201910161036e565b51815160209384036101000a600019018019909216911617905260408051929094018290039091206000818152600183529390932088519397506103d996509450870192506104409050565b5060405181907f0f66da887a9c57b75a06c56ae415879ac0fa76f7e5fcb12af540c94fe85c2e5d90600090a25050565b6000805473ffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff16179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061048157805160ff19168380011785556104ae565b828001600101855582156104ae579182015b828111156104ae578251825591602001919060010190610493565b506104ba9291506104be565b5090565b6104d891905b808211156104ba57600081556001016104c4565b905600a165627a7a723058207d63bc55d7869b380b4dc0893827f66269543a40ff3b44414c2368d40e7c81000029'; this.abi = [{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"fiddle_data","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"bytes32"}],"name":"get_fiddle","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"string"}],"name":"share","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"mortal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_id","type":"bytes32"}],"name":"NewFiddle","type":"event"}]; } @@ -443,18 +444,12 @@ export default class Web3Helpers { }); } async getSnippet(coinbase, id) { - const { bytecode, abi } = this; + const { abi } = this; try { - const gas = await this.getGasEstimate(coinbase, bytecode); - const gasPrice = await this.web3.eth.getGasPrice(); const contract = await new this.web3.eth.Contract(abi, '0xc17744c2F1B77907574b7D49A00319Aa47e828B8', { - from: coinbase, - data: '0x' + bytecode, - gas: this.web3.utils.toHex(gas), - gasPrice: this.web3.utils.toHex(gasPrice) + from: coinbase }); - const fiddle = contract.methods.get_fiddle(id).call({ from: coinbase }); - return fiddle; + return await contract.methods.get_fiddle(id).call({ from: coinbase }); } catch(e) { throw e; } From de37bac604ce346a9757af41e5dcf6e895045da5 Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Wed, 9 May 2018 02:15:07 +0530 Subject: [PATCH 6/9] watch events with filter --- contracts/main.sol | 4 +- lib/components/ShareBox/index.js | 103 ++++++++++++++++++++++++------- lib/web3/methods.js | 53 ++++++++-------- lib/web3/web3.js | 2 +- styles/atom-solidity.less | 11 ++++ 5 files changed, 122 insertions(+), 51 deletions(-) diff --git a/contracts/main.sol b/contracts/main.sol index 8b040c8..97f76f7 100644 --- a/contracts/main.sol +++ b/contracts/main.sol @@ -3,13 +3,13 @@ import '../contracts/mortal.sol'; contract Main is Mortal { mapping (bytes32 => string) public fiddle_data; - event NewFiddle(bytes32 indexed _id); + event NewFiddle(address indexed _user, bytes32 indexed _id); // share some given input function share(string _code) public { bytes32 _id = keccak256(msg.sender, _code); fiddle_data[_id] = _code; - emit NewFiddle(_id); + emit NewFiddle(msg.sender, _id); } // get code for given bytes32 id function get_fiddle(bytes32 _id) view public returns (string) { diff --git a/lib/components/ShareBox/index.js b/lib/components/ShareBox/index.js index 1f17d1b..b49022c 100644 --- a/lib/components/ShareBox/index.js +++ b/lib/components/ShareBox/index.js @@ -16,6 +16,7 @@ // along with Etheratom. If not, see . import React from 'react' import { connect } from 'react-redux' +import { Collapse } from 'react-collapse' class ShareBox extends React.Component { constructor(props) { @@ -24,34 +25,60 @@ class ShareBox extends React.Component { this.state = { shared: false, shareLink: null, - gas: 394504, // contract creation gas - snippet: null + gas: 0, + snippet: null, + txHash: null, + code: null, + isOpened: false, + toggleBtnStyle: 'btn icon icon-unfold inline-block-tight', + togglePreviewTxt: 'Preview Snippet' } this._handleShare = this._handleShare.bind(this); this._handleLoad = this._handleLoad.bind(this); this._handleCopy = this._handleCopy.bind(this); this._handleChange = this._handleChange.bind(this); this._handleGasChange = this._handleGasChange.bind(this); + this._togglePreview = this._togglePreview.bind(this); + this.watchSyncEvents(); } - async componentWillReceiveProps(nextProps) { - const { accounts } = nextProps; - if(accounts.length > 0) { - const gasEstm = await this.helpers.getShareGasEstm(accounts[0]); - this.setState({ gas: gasEstm }); - } - } - async _handleShare() { + async watchSyncEvents() { const that = this; - const { coinbase, password } = this.props; - const { gas } = this.state; - let code = null; - atom.workspace.observeTextEditors(async (editor) => { + const { coinbase } = this.props; + that.helpers.snptEvents.NewFiddle({ filter: { _user: coinbase } }) + .on('data', data => { + console.log(data); + const fiddleId = data.returnValues._id; + that.setState({ shared: true, shareLink: fiddleId }); + }) + .on('error', e => { + throw e; + }) + } + async componentDidMount() { + const { coinbase } = this.props; + const gasEstm = await this.helpers.getShareGasEstm(coinbase); + this.setState({ gas: gasEstm }); + atom.workspace.observeActiveTextEditor(async (editor) => { + if(!editor || !editor.getBuffer()) { + return + } code = editor.getText(); + this.setState({ code }); return; }); - const shared = await that.helpers.shareCode(coinbase, password, code, gas); - that.setState({ shared: true, shareLink: shared }); - return; + } + async _handleShare() { + const that = this; + const { coinbase, password } = this.props; + const { gas, code } = this.state; + this.setState({ txHash: null, shareLink: null, snippet: null }); + that.helpers.shareCode(coinbase, password, code, gas) + .then(txHash => { + this.setState({ txHash: txHash }); + }) + .catch(e => { + throw e; + }); } async _handleLoad() { try { @@ -73,8 +100,23 @@ class ShareBox extends React.Component { async _handleGasChange(event) { this.setState({ gas: event.target.value }); } + _togglePreview() { + const { isOpened } = this.state; + this.setState({ isOpened: !isOpened }); + if(!isOpened) { + this.setState({ + toggleBtnStyle: 'btn btn-success icon icon-fold inline-block-tight', + togglePreviewTxt: 'Hide Snippet' + }); + } else { + this.setState({ + toggleBtnStyle: 'btn icon icon-unfold inline-block-tight', + togglePreviewTxt: 'Preview Snippet' + }); + } + } render() { - const { shareLink, shared, gas, snippet } = this.state; + const { shareLink, shared, gas, snippet, txHash, code, toggleBtnStyle, togglePreviewTxt, isOpened } = this.state; return (