From 31a0f5ef287a28fc34305989ee2de2545a32e765 Mon Sep 17 00:00:00 2001 From: kaikun213 Date: Thu, 27 Jul 2017 13:24:23 +0200 Subject: [PATCH] contractDevelop Debugger (Bonds) in progress --- js/packages/dapp-develop/contractDevelop.js | 132 +++++++-- .../dapp-develop/webpack_config_parityjs.js | 276 ++++++++++++++++++ 2 files changed, 379 insertions(+), 29 deletions(-) create mode 100644 js/packages/dapp-develop/webpack_config_parityjs.js diff --git a/js/packages/dapp-develop/contractDevelop.js b/js/packages/dapp-develop/contractDevelop.js index 18eb2580e..bb001aa80 100644 --- a/js/packages/dapp-develop/contractDevelop.js +++ b/js/packages/dapp-develop/contractDevelop.js @@ -1,4 +1,4 @@ - // Copyright 2015-2017 Parity Technologies (UK) Ltd. +// Copyright 2015-2017 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import moment from 'moment'; import { throttle } from 'lodash'; -import { Actionbar, ActionbarExport, ActionbarImport, Button, Dropdown, Input, Loading, Page, Toggle } from '@parity/ui'; +import { Actionbar, ActionbarExport, ActionbarImport, Button, Dropdown, Input, Loading, Page, Toggle, Tab } from '@parity/ui'; import { CancelIcon, ListIcon, SaveIcon, SendIcon, SettingsIcon } from '@parity/ui/Icons'; import Editor from '@parity/ui/Editor'; @@ -33,6 +33,12 @@ import SaveContract from './SaveContract'; import ContractDevelopStore from './store'; import styles from './contractDevelop.css'; +import { Debugger, TransactButton, Contract, DropdownBond } from 'parity-reactive-ui'; +import { Bond } from 'oo7'; +import { bonds } from 'oo7-parity'; + +const traceOptions = [{ text: 'trace', value: 'trace' }, { text: 'vmTrace', value: 'vmTrace' }, { text: 'stateDiff', value: 'stateDiff' }]; + @observer class ContractDevelop extends Component { static propTypes = { @@ -48,13 +54,14 @@ class ContractDevelop extends Component { size: 65 }; + debugDeploy = this.debugDeploy.bind(this); + componentWillMount () { const { worker } = this.props; if (worker !== undefined) { this.store.setWorker(worker); } - this.throttledResize = throttle(this.applyResize, 100, { leading: true }); } @@ -83,6 +90,7 @@ class ContractDevelop extends Component { } render () { + console.log('render contractDevelopment'); const { sourcecode } = this.store; const { size, resizing } = this.state; @@ -90,6 +98,16 @@ class ContractDevelop extends Component { .slice() .filter((a) => a.contract === ''); + const panes = [ + { menuItem: 'Parameters', render: () =>
+ { this.renderParameters() } +
}, + { menuItem: 'Debugger', render: () => this.renderDebugger() }, + { menuItem: 'ShowTrace', render: () => } ] } + /> + } + ]; + return (
{ this.renderDeployModal() } @@ -99,9 +117,6 @@ class ContractDevelop extends Component {
-

- -

- { this.renderParameters() } +
@@ -183,6 +192,68 @@ class ContractDevelop extends Component { ); } + debugDeploy (contract) { + const { contracts, contractIndex } = this.store; + + const bytecode = contract.bytecode; + const abi = contract.interface; + + if (!contract.deployed) { + let tx = bonds.deployContract(bytecode, JSON.parse(abi)); + + tx.done(s => { + console.log('txDone!'); + // address is undefined from s (How to become ? => TuT) , error because of triggering while triggering => can makeContract call? between here and next printout + let address = s.deployed.address; + + contract.deployed = bonds.makeContract(address, JSON.parse(abi), [], true); + contract.address = address; + contract.trace = new Bond(); + contract.trace.tie(v => { + console.log('TIED to BOND', v); + // v.then(console.log); + }); + contracts[contractIndex] = contract; + console.log('New Contract', contract, 'index', contractIndex); + }); + + return tx; + } else { + return null; + } + } + + renderDebugger () { + const { contracts, compiled } = this.store; + let traceMode = new Bond(); + + const contractKeys = Object.keys(contracts); + + return (
+ {compiled ?
+ + {contractKeys.map((name, i) => { + let c = contracts[name]; + + console.log('contract', c, 'index', i, 'name', name); + + return ( +
+ { c.deployed + ? + : this.debugDeploy(c) } statusText disabled={ c.deployed } />} +
+ ); + })} +
: null} +
); + } + renderActionBar () { const { sourcecode, selectedContract } = this.store; @@ -346,21 +417,24 @@ class ContractDevelop extends Component { { contract ? ( -
@@ -721,6 +795,6 @@ function mapStateToProps (state) { } export default connect( - mapStateToProps, - null +mapStateToProps, +null )(ContractDevelop); diff --git a/js/packages/dapp-develop/webpack_config_parityjs.js b/js/packages/dapp-develop/webpack_config_parityjs.js new file mode 100644 index 000000000..cfb609ff2 --- /dev/null +++ b/js/packages/dapp-develop/webpack_config_parityjs.js @@ -0,0 +1,276 @@ + +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity 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. + +// Parity 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 Parity. If not, see . + +const webpack = require('webpack'); +const path = require('path'); +// const ReactIntlAggregatePlugin = require('react-intl-aggregate-webpack-plugin'); +const WebpackErrorNotificationPlugin = require('webpack-error-notification'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin'); +const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin'); + +const rulesEs6 = require('./rules/es6'); +const rulesParity = require('./rules/parity'); +const Shared = require('./shared'); + +const DAPPS_BUILTIN = require('../packages/shared/config/dappsBuiltin.json'); +const DAPPS_VIEWS = require('../packages/shared/config/dappsViews.json').map((dapp) => { + dapp.commons = true; + return dapp; +}); + +const FAVICON = path.resolve(__dirname, '../packages/shared/assets/images/parity-logo-black-no-text.png'); + +const DEST = process.env.BUILD_DEST || '.build'; +const ENV = process.env.NODE_ENV || 'development'; +const EMBED = process.env.EMBED; + +const isProd = ENV === 'production'; +const isEmbed = EMBED === '1' || EMBED === 'true'; +const isAnalize = process.env.WPANALIZE === '1'; + +const entry = isEmbed + ? { + embed: './embed.js' + } + : Object.assign({}, Shared.dappsEntry, { + index: './index.js' + }); + +module.exports = { + cache: !isProd, + devtool: isProd ? '#hidden-source-map' : '#source-map', + + context: path.join(__dirname, '../src'), + entry: entry, + output: { + // publicPath: '/', + path: path.join(__dirname, '../', DEST), + filename: '[name].[hash:10].js' + }, + + module: { + rules: [ + rulesParity, + rulesEs6, + { + test: /\.js$/, + exclude: /(node_modules)/, + use: [ 'happypack/loader?id=babel-js' ] + }, + { + test: /\.json$/, + use: [ 'json-loader' ] + }, + { + test: /\.ejs$/, + use: [ 'ejs-loader' ] + }, + { + test: /\.html$/, + use: [ + 'file-loader?name=[name].[ext]!extract-loader', + { + loader: 'html-loader', + options: { + root: path.resolve(__dirname, '../assets/images'), + attrs: ['img:src', 'link:href'] + } + } + ] + }, + { + test: /\.md$/, + use: [ + { + loader: 'html-loader', + options: {} + }, + { + loader: 'markdown-loader', + options: {} + } + ] + }, + { + test: /\.css$/, + include: [ /packages/, /src/ ], + loader: (isProd && !isEmbed) + ? ExtractTextPlugin.extract([ + // 'style-loader', + 'css-loader?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]', + 'postcss-loader' + ]) + : undefined, + use: (isProd && !isEmbed) + ? undefined + : [ 'happypack/loader?id=css' ] + }, + + { + test: /\.css$/, + exclude: [ /packages/, /src/ ], + use: [ 'style-loader', 'css-loader' ] + }, + { + test: /\.(png|jpg)$/, + use: [ 'file-loader?&name=assets/[name].[hash:10].[ext]' ] + }, + { + test: /\.(woff|woff2|ttf|eot|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/, + use: [ 'file-loader?name=fonts/[name][hash:10].[ext]' ] + }, + { + test: /parity-logo-white-no-text\.svg/, + use: [ 'url-loader' ] + }, + { + test: /\.svg(\?v=[0-9]\.[0-9]\.[0-9])?$/, + exclude: [ /parity-logo-white-no-text\.svg/ ], + use: [ 'file-loader?name=assets/[name].[hash:10].[ext]' ] + } + ], + noParse: [ + /node_modules\/sinon/ + ] + }, + + resolve: { + alias: { + '~/packages/api/local': path.resolve(__dirname, '../packages/api/local/localAccountsMiddleware.js'), + '~': path.resolve(__dirname, '..'), + '@parity/wordlist': path.resolve(__dirname, '../node_modules/@parity/wordlist'), + '@parity': path.resolve(__dirname, '../packages'), + '@parity/parity.js': path.resolve(__dirname, '../src/library.parity.js'), + 'oo7-parity': path.resolve(__dirname, '../oo7-parity'), + 'oo7-react': path.resolve(__dirname, '../oo7-react'), + 'oo7': path.resolve(__dirname, '../oo7'), + 'parity-reactive-ui': path.resolve(__dirname, '../parity-reactive-ui') + }, + modules: [ + path.join(__dirname, '../node_modules') + ], + extensions: ['.json', '.js', '.jsx'], + unsafeCache: true + }, + + node: { + fs: 'empty' + }, + + plugins: (function () { + const DappsHTMLInjection = [] + .concat(DAPPS_BUILTIN, DAPPS_VIEWS) + .filter((dapp) => !dapp.skipBuild) + .map((dapp) => { + return new HtmlWebpackPlugin({ + title: dapp.name, + filename: dapp.url + '.html', + template: '../packages/dapps/index.ejs', + favicon: FAVICON, + secure: dapp.secure, + chunks: [ !isProd || dapp.commons ? 'commons' : null, dapp.url ] + }); + }); + + let plugins = Shared.getPlugins().concat( + new WebpackErrorNotificationPlugin() + ); + + if (!isEmbed) { + plugins = [].concat( + plugins, + + new HtmlWebpackPlugin({ + title: 'Parity', + filename: 'index.html', + template: './index.ejs', + favicon: FAVICON, + chunks: [ + isProd ? null : 'commons', + 'index' + ] + }), + + new ServiceWorkerWebpackPlugin({ + entry: path.join(__dirname, '../src/serviceWorker.js') + }), + + DappsHTMLInjection, + + new webpack.DllReferencePlugin({ + context: '.', + manifest: require(`../${DEST}/vendor-manifest.json`) + }), + + new ScriptExtHtmlWebpackPlugin({ + sync: [ 'commons', 'vendor.js' ], + defaultAttribute: 'defer' + }), + + new CopyWebpackPlugin([ + { from: './error_pages.css', to: 'styles.css' }, + { from: '../packages/dapps/static' } + ], {}) + ); + } + + if (isEmbed) { + plugins.push( + new HtmlWebpackPlugin({ + title: 'Parity Bar', + filename: 'embed.html', + template: './index.ejs', + favicon: FAVICON, + chunks: [ + isProd ? null : 'commons', + 'embed' + ] + }) + ); + } + + if (!isAnalize && !isProd) { + // const DEST_I18N = path.join(__dirname, '..', DEST, 'i18n'); + + plugins.push( + // new ReactIntlAggregatePlugin({ + // messagesPattern: DEST_I18N + '/i18n/**/*.json', + // aggregateOutputDir: DEST_I18N + '/i18n/', + // aggregateFilename: 'en' + // }), + + new webpack.optimize.CommonsChunkPlugin({ + filename: 'commons.[hash:10].js', + name: 'commons', + minChunks: 2 + }) + ); + } + + if (isProd) { + plugins.push(new ExtractTextPlugin({ + filename: 'styles/[name].[hash:10].css', + allChunks: true + })); + } + + return plugins; + }()) +};