Merge pull request #533 from ninabreznik/style-guide

Style guide
pull/1/head
yann300 8 years ago committed by GitHub
commit 4e97db9f01
  1. 2
      .travis.yml
  2. 72
      assets/css/browser-solidity.css
  3. 52
      assets/css/universal-dapp.css
  4. 7
      ci/browser_tests.sh
  5. 81
      index.html
  6. 7
      nightwatch.js
  7. 52
      package.json
  8. 36
      src/app.js
  9. 41
      src/app/analysis-tab.js
  10. 93
      src/app/contract-tab.js
  11. 16
      src/app/debugger-tab.js
  12. 3
      src/app/editor.js
  13. 2
      src/app/execution-context.js
  14. 4
      src/app/file-panel.js
  15. 45
      src/app/files-tab.js
  16. 78
      src/app/renderer.js
  17. 69
      src/app/settings-tab.js
  18. 4
      src/app/staticanalysis/modules/gasCosts.js
  19. 4
      src/app/staticanalysis/modules/thisLocal.js
  20. 2
      src/app/staticanalysis/modules/txOrigin.js
  21. 26
      src/app/staticanalysis/staticAnalysisView.js
  22. 153
      src/app/style-guide.js
  23. 108
      src/universal-dapp.js
  24. 4
      test-browser/helpers/contracts.js

@ -2,7 +2,7 @@ language: node_js
node_js:
- stable
script:
- npm run lint && npm run csslint && npm run test && npm run downloadsolc && npm run make-mock-compiler && npm run build
- npm run lint && npm run test && npm run downloadsolc && npm run make-mock-compiler && npm run build
- ./ci/browser_tests.sh
deploy:
provider: script

@ -136,11 +136,6 @@ body {
box-sizing: border-box;
}
#output {
display: block;
padding: 1em;
}
#header {
font-size: 13px;
height: 100%;
@ -166,6 +161,8 @@ body {
list-style: none;
margin: 0;
padding: 0;
display: flex;
justify-content: space-between;
}
#header #options li.active {
@ -185,7 +182,6 @@ body {
#header #optionViews > div {
display: none;
padding: .5em .5em .5em;
}
#header #optionViews.txView #txView {
@ -198,7 +194,6 @@ body {
#header #optionViews.publishView #publishView {
display: block;
padding: 3em;
}
#header #optionViews.envView #envView {
@ -207,7 +202,6 @@ body {
#header #optionViews.debugView #debugView {
display: block;
padding: 3em;
}
#header #optionViews.verificationView #verificationView {
@ -216,8 +210,6 @@ body {
#header #optionViews.staticanalysisView #staticanalysisView {
display: block;
padding: 3em;
line-height: 1.5em;
}
#header #optionViews.txView input,
@ -264,12 +256,12 @@ body {
#publishView button {
background-color: #C6CFF7;
font-size: 12px;
padding: 0.25em;
margin-bottom: .5em;
color: black;
border:0 none;
border-radius: 3px;
width: 8em;
height: 20px;
margin-right: 1em;
cursor: pointer;
}
@ -303,24 +295,13 @@ body {
display: block;
}
#header .origin,
#header #executionContext {
#header .origin {
display: block;
word-wrap: break-word;
padding: 1.5em;
font-weight: bold;
}
#selectExEnv {
text-decoration: none;
background-color: #C6CFF7;
cursor: pointer;
font-size: 12px;
color: black;
border-radius: 3px;
border: 0 none;
}
#header #versionSelector {
text-decoration: none;
background-color: #C6CFF7;
@ -331,15 +312,6 @@ body {
border: 0 none;
}
.col1 {
width: 30%;
float: left;
}
.col2 {
width: 70%;
float: left;
}
#formalVerificationInput {
height: 4.5em;
width: 100%;
@ -354,18 +326,6 @@ body {
display: none;
}
.udapp .contract > .title {
cursor:pointer;
}
.udapp .contract > .title:before {
content: "\25BC";
opacity: 0.5;
margin-right: 0.4em;
font-size: 10px;
margin-top: 0.2em;
}
.contract.hidesub > .title:before {
content: "\25B6";
}
@ -380,11 +340,13 @@ body {
overflow: auto;
display: block;
clear: both;
margin: 1.5em;
margin: .5em .5em 0 .5em;
padding: .5em;
font-weight: bold;
}
.crow #txorigin {
margin-left: 0.5em;
text-decoration: none;
background-color: #C6CFF7;
cursor: pointer;
@ -412,9 +374,10 @@ body {
word-wrap: break-word;
cursor: pointer;
position: relative;
margin: 0.5em;
border-radius: 0.6em;
padding: 1em 1.5em;
margin: 0.5em 0 1em 0;
border-radius: 5px;
line-height: 20px;
padding: 8px 15px;
}
.sol.error pre,
@ -438,11 +401,13 @@ body {
}
.sol.error {
background-color: rgba(255, 0, 0, 0.4);
background-color: hsla(0, 100%, 75%, 0.1);
border: .2em dotted #FF8080;
}
.sol.warning {
background-color: rgba(210, 202, 36, 0.4);
background-color: hsla(59, 56%, 78%, 0.5);
border: .2em dotted #ffbd01;
}
#ghostbar {
@ -465,7 +430,7 @@ body {
bottom: 0;
cursor: col-resize;
z-index: 999;
border-right: 2px solid #C6CFF7;
border-right: 2px solid hsla(215, 81%, 79%, .3);
}
#editor .ace-tm .ace_gutter,
@ -475,11 +440,10 @@ body {
}
input[readonly] {
padding: .4em;
border: 1px solid #ccc;
box-sizing: border-box;
display: block;
width: 100%;
height: 7px;
padding: .8em;
}
input[type="file"] {

@ -1,6 +1,4 @@
.udapp {
padding: .5em;
border: 1px dotted #4D5686;
position: relative;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
box-sizing: border-box;
@ -16,7 +14,6 @@
color: #7A7AE2;
}
.udapp input,
.udapp button,
.udapp-setup textarea,
.udapp-setup button {
@ -47,30 +44,7 @@
.udapp .create {
overflow: auto;
margin-bottom: 1em;
}
.udapp .title {
margin-bottom: 0.4em;
padding: 1em;
background-color: #C6CFF7;
font-weight: bold;
display: flex;
justify-content: space-between;
word-wrap: break-word;
position: relative;
border-radius: 3px;
}
.udapp .definitionTitle {
background-color: #C6CFD9;
}
.udapp .title:hover {
opacity: 0.8;
}
.udapp .title .size {
font-weight: normal;
margin: 1em;
}
.udapp .output {
@ -205,12 +179,8 @@
border-radius: 3px;
}
.udapp input {
border-left: 0 none;
}
.udapp button {
background-color: #666;
padding: .36em;
color: #4C4B4B;
cursor: pointer;
overflow: hidden;
@ -310,15 +280,24 @@
}
.udapp .legend {
font-size: 12px;
float: left;
color: #666;
background-color: white;
line-height: 20px;
border: .2em dotted lightGrey;
padding: 8px 15px;
border-radius: 5px;
margin-bottom: 1em;
display: flex;
justify-content: initial;
flex-wrap: wrap;
}
.udapp .legend div {
display: inline-block;
margin-right: 0.5em;
margin-bottom: 1em;
display: flex;
align-items: center;
line-height: 0px;
padding: 5px;
}
.udapp .legend div:before {
@ -329,6 +308,7 @@
height: 1em;
margin-right: 0.5em;
width: 1em;
border-radius: 50%;
}
.udapp .legend .publish:before {

@ -19,8 +19,11 @@ while [ ! -f "$SAUCECONNECT_READYFILE" ]; do
sleep .5
done
# npm run browser-test-remote-parallel || TEST_EXITCODE=1
npm run nightwatch_remote_parallel || TEST_EXITCODE=1
npm run nightwatch_remote_chrome || TEST_EXITCODE=1
npm run nightwatch_remote_firefox || TEST_EXITCODE=1
npm run nightwatch_remote_safari || TEST_EXITCODE=1
# npm run nightwatch_remote_ie || TEST_EXITCODE=1
# npm run nightwatch_remote_parallel || TEST_EXITCODE=1
node ci/sauceDisconnect.js "$SAUCECONNECT_USERNAME" "$SAUCECONNECT_ACCESSKEY" "$SAUCECONNECT_JOBIDENTIFIER"

@ -4,7 +4,6 @@
<head>
<meta charset="utf-8">
<!--
The MIT License (MIT)
Copyright (c) 2014, 2015, the individual contributors
@ -26,7 +25,6 @@
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>Remix</title>
@ -57,6 +55,7 @@
<div id="righthand-panel">
<div id="header">
<div id="menu">
<img id="solIcon" title="Solidity realtime compiler and runtime" src="assets/img/remix_logo_512x512.svg" alt="Solidity realtime compiler and runtime">
<ul id="options">
<li class="settingsView active" title="Settings">Settings</li>
<li class="publishView" title="Publish" >Files</li>
@ -65,88 +64,14 @@
<li class="staticanalysisView" title="Static Analysis">Analysis</li>
<li id="helpButton"><a href="https://solidity.readthedocs.org" target="_blank" title="Open Documentation">Docs</a></li>
</ul>
<img id="solIcon" title="Solidity realtime compiler and runtime" src="assets/img/remix_logo_512x512.svg" alt="Solidity realtime compiler and runtime">
</div>
<div id="optionViews" class="settingsView">
<div id="txView"></div>
<div id="settingsView">
<div class="version crow"><strong>Current Solidity version:</strong> <span id="version">( Loading... )</span></div>
<div class="crow">Switch version: <select id="versionSelector"></select></div>
<div class="crow">
<label for="editorWrap"><input id="editorWrap" type="checkbox">Text Wrap</label>
<label for="optimize"><input id="optimize" type="checkbox">Enable Optimization</label>
<label for="autoCompile"><input id="autoCompile" type="checkbox" checked>Auto Compile</label>
<button id="compile" title="Compile source code">Compile</button>
</div>
</div>
<div id="publishView">
<p>
<button id="gist" title="Publish all files as public gist on github.com"><i class="fa fa-github"></i> Publish Gist</button>Publish all open files to an anonymous github gist.<br/>
<button id="copyOver" title="Copy all files to another instance of browser-solidity.">Copy files</button> Copy all files to another instance of Browser-solidity.
</p>
<p>You can also load a gist by adding the following <span class="pre">#gist=GIST_ID</span> to your url, where GIST_ID is the id of the gist to load.</p>
</div>
<div id="envView">
<div class="crow">
<label for="txorigin">Transaction origin:<select name="txorigin" id="txorigin"></select></label>
</div>
<div class="crow">
<label for="gasLimit"><input type="number" id="gasLimit" value="3000000"> Transaction gas limit</label>
</div>
<div class="crow hide">
<label for="gasPrice"><input type="number" id="gasPrice" value="0"> Gas Price</label>
</div>
<div class="crow">
<label for="value"><input type="text" id="value" value="0"> Value (e.g. .7 ether or 5 wei, defaults to ether)</label>
</div>
<span id="executionContext">
Select execution environment: <br><br>
<select id='selectExEnv'>
<option id="vm-mode"
title="Execution environment does not connect to any node, everything is local and in memory only."
value="vm"
checked name="executionContext">
JavaScript VM
</option>
<option id="injected-mode"
title="Execution environment has been provided by Mist or similar provider."
value="injected"
checked name="executionContext">
Injected Web3
</option>
<option id="web3-mode"
title="Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse!
If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http."
value="web3"
name="executionContext">
Web3 Provider
</option>
</select>
</span>
<div id="output"></div>
</div>
<div id="debugView">
<div id="debugger"></div>
</div>
<div id="staticanalysisView">
<p>
This tab provides support for <b>formal verification</b> of Solidity contracts.<br/>
This feature is still in development and thus also not yet well documented,
but you can find some information
<a href="http://solidity.readthedocs.io/en/latest/security-considerations.html#formal-verification">here</a>.
The compiler generates input to be verified
(or report errors). Please paste the text below into
<a href="http://why3.lri.fr/try/">http://why3.lri.fr/try/</a>
to actually perform the verification.
We plan to support direct integration in the future.
</p>
<textarea id="formalVerificationInput" readonly="readonly"></textarea>
<div id="formalVerificationErrors"></div>
</div>
<!-- contract-tab.js, settings-tab.js, debugger-tab.js, analysis-tab.js, files-tab.js -->
</div>
</div>
</div>
<script src="build/app.js"></script>
</body>
</html>

@ -50,8 +50,8 @@ module.exports = {
'desiredCapabilities': {
'browserName': 'safari',
'javascriptEnabled': true,
'platform': 'OS X 10.10',
'version': '8.0',
'platform': 'OS X 10.11',
'version': '10.0',
'acceptSslCerts': true,
'build': 'build-' + TRAVIS_JOB_NUMBER,
'tunnel-identifier': 'browsersolidity_tests_' + TRAVIS_JOB_NUMBER
@ -62,8 +62,9 @@ module.exports = {
'desiredCapabilities': {
'browserName': 'internet explorer',
'javascriptEnabled': true,
'platform': 'Windows 10',
'acceptSslCerts': true,
'version': '11',
'version': '11.103',
'build': 'build-' + TRAVIS_JOB_NUMBER,
'tunnel-identifier': 'browsersolidity_tests_' + TRAVIS_JOB_NUMBER
}

@ -13,6 +13,7 @@
"babelify": "^7.3.0",
"brace": "^0.8.0",
"browserify-reload": "^1.0.3",
"clipboard-copy": "^1.2.0",
"csjs-inject": "^1.0.1",
"csslint": "^1.0.2",
"ethereum-remix": "https://github.com/ethereum/remix",
@ -92,24 +93,39 @@
},
"browserify": {
"transform": [
["babelify", {
"sourceMapsAbsolute": false,
"sourceMaps": true,
"plugins": [
["fast-async", {
"runtimePattern": null,
"compiler": {
"es7": true,
"noRuntime": true,
"promises": true,
"wrapAwait": true
}
}],
["yo-yoify"], ["transform-object-assign"]
],
"presets": ["es2015"]
}],
["uglifyify"]
[
"babelify",
{
"sourceMapsAbsolute": false,
"sourceMaps": true,
"plugins": [
[
"fast-async",
{
"runtimePattern": null,
"compiler": {
"es7": true,
"noRuntime": true,
"promises": true,
"wrapAwait": true
}
}
],
[
"yo-yoify"
],
[
"transform-object-assign"
]
],
"presets": [
"es2015"
]
}
],
[
"uglifyify"
]
]
},
"scripts": {

@ -29,6 +29,29 @@ var FilePanel = require('./app/file-panel')
var examples = require('./app/example-contracts')
var contractTab = require('./app/contract-tab.js')
var settingsTab = require('./app/settings-tab.js')
var analysisTab = require('./app/analysis-tab.js')
var debuggerTab = require('./app/debugger-tab.js')
var filesTab = require('./app/files-tab.js')
/* ----------------------------------------------
TABS - Righthand pannel
---------------------------------------------- */
var contractView = contractTab()
document.querySelector('#optionViews').appendChild(contractView)
var settingsView = settingsTab()
document.querySelector('#optionViews').appendChild(settingsView)
var analysisView = analysisTab()
document.querySelector('#optionViews').appendChild(analysisView)
var debuggerView = debuggerTab()
document.querySelector('#optionViews').appendChild(debuggerView)
var filesView = filesTab()
document.querySelector('#optionViews').appendChild(filesView)
// The event listener needs to be registered as early as possible, because the
// parent will send the message upon the "load" event.
var filesToLoad = null
@ -406,12 +429,6 @@ var run = function () {
return $filesEl.position().left
}
function activeFilePos () {
var el = $filesEl.find('.active')
var l = el.position().left
return l
}
function reAdjust () {
if (widthOfList() + getLeftPosi() > widthOfVisible()) {
$scrollerRight.fadeIn('fast')
@ -785,7 +802,8 @@ var run = function () {
}
}
var staticanalysis = new StaticAnalysis(staticAnalysisAPI, compiler.event)
$('#staticanalysisView').append(staticanalysis.render())
var node = document.getElementById('staticanalysisView')
node.insertBefore(staticanalysis.render(), node.childNodes[0])
// ----------------- autoCompile -----------------
var autoCompile = document.querySelector('#autoCompile').checked
@ -876,7 +894,7 @@ var run = function () {
})
compiler.event.register('loadingCompiler', this, function (url, usingWorker) {
setVersionText(usingWorker ? '(loading using worker)' : '( Loading... Please, wait a moment. )')
setVersionText(usingWorker ? '(loading using worker)' : ' Loading... please, wait a moment! ')
})
compiler.event.register('compilerLoaded', this, function (version) {
@ -956,7 +974,7 @@ var run = function () {
loadVersion($('#versionSelector').val())
})
var header = new Option('Click to select new compiler version')
var header = new Option('Select new compiler version')
header.disabled = true
header.selected = true
$('#versionSelector').append(header)

@ -0,0 +1,41 @@
var yo = require('yo-yo')
// -------------- styling ----------------------
var csjs = require('csjs-inject')
var styleGuide = require('./style-guide')
var styles = styleGuide()
var css = csjs`
.analysisTabView {
padding: 2%;
margin-top: 1em;
}
.infoBox extends ${styles.infoTextBox} {
margin-bottom: 1em;
}
.textBox extends ${styles.textBoxL} {
margin-bottom: 1em;
}
`
module.exports = analysisTab
function analysisTab () {
return yo`
<div class="${css.analysisTabView} "id="staticanalysisView">
<div class="${css.infoBox}">
This tab provides support for <b>formal verification</b> of Solidity contracts.<br>
This feature is still in development and thus also not yet well documented,
but you can find some information
<a href="http://solidity.readthedocs.io/en/latest/security-considerations.html#formal-verification">here</a>.
The compiler generates input to be verified
(or report errors). Please paste the text below into
<a href="http://why3.lri.fr/try/">http://why3.lri.fr/try/</a>
to actually perform the verification.
We plan to support direct integration in the future.
</div>
<textarea class="${css.textBox}" id="formalVerificationInput" readonly="readonly"></textarea>
<div id="formalVerificationErrors"></div>
</div>
`
}

@ -0,0 +1,93 @@
var yo = require('yo-yo')
// -------------- styling ----------------------
var csjs = require('csjs-inject')
var styleGuide = require('./style-guide')
var styles = styleGuide()
var css = csjs`
.contractTabView {
padding: 2%;
}
.crow {
margin-top: 1em;
display: flex;
}
.col1 extends ${styles.titleL} {
width: 30%;
float: left;
align-self: center;
}
.col1_1 extends ${styles.titleM} {
width: 30%;
float: left;
align-self: center;
}
.col2 extends ${styles.textBoxL}{
width: 70%;
height: 7px;
float: left;
padding: .8em;
}
.select extends ${styles.dropdown} {
width: 70%;
float: left;
text-align: center;
}
.contract {
display: block;
margin: 4em 0 2em 0;
}
`
module.exports = contractTab
function contractTab () {
return yo`
<div class="${css.contractTabView}" id="envView">
<div class="${css.crow}">
<div id="selectExEnv" class="${css.col1_1}">
Execution environment
</div>
<select id="selectExEnvOptions" class="${css.select}">
<option id="vm-mode"
title="Execution environment does not connect to any node, everything is local and in memory only."
value="vm"
checked name="executionContext">
JavaScript VM
</option>
<option id="injected-mode"
title="Execution environment has been provided by Mist or similar provider."
value="injected"
checked name="executionContext">
Injected Web3
</option>
<option id="web3-mode"
title="Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse!
If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http."
value="web3"
name="executionContext">
Web3 Provider
</option>
</select>
</div>
<div class="${css.crow}">
<div class="${css.col1_1}">Transaction origin</div>
<select name="txorigin" class="${css.select}" id="txorigin"></select>
</div>
<div class="${css.crow}">
<div class="${css.col1_1}">Transaction gas limit</div>
<input type="number" class="${css.col2}" id="gasLimit" value="3000000">
</div>
<div class="${css.crow} hide">
<div class="${css.col1_1}">Gas Price</div>
<input type="number" class="${css.col2}" id="gasPrice" value="0">
</div>
<div class="${css.crow}">
<div class="${css.col1_1}"> Value</div>
<input type="text" class="${css.col2}" id="value" value="0" title="(e.g. .7 ether ...)">
</div>
<div id="output" class="${css.contract}"></div>
</div>
`
}

@ -0,0 +1,16 @@
var yo = require('yo-yo')
// -------------- styling ----------------------
var csjs = require('csjs-inject')
var css = csjs`
.debuggerTabView {
padding: 2%;
}
`
module.exports = debuggerTab
function debuggerTab () {
return yo` <div class="${css.debuggerTabView} "id="debugView"><div id="debugger"></div></div>`
}

@ -19,8 +19,7 @@ var css = csjs`
}
.ace-editor {
top : 4px;
border-top : 3px solid transparent;
font-size : 15px;
font-size : 2vmin;
width : 100%;
}
`

@ -136,7 +136,7 @@ function ExecutionContext () {
DROPDOWN
--------------------------------------------------------------------------- */
var selectExEnv = document.querySelector('#selectExEnv')
var selectExEnv = document.querySelector('#selectExEnvOptions')
selectExEnv.addEventListener('change', function (event) {
if (!executionContextChange(selectExEnv.options[selectExEnv.selectedIndex].value)) {
selectExEnv.value = executionContext

@ -55,10 +55,10 @@ var css = csjs`
}
.dragbar {
position : relative;
top : 6px;
top : 4px;
cursor : col-resize;
z-index : 999;
border-right : 2px solid #C6CFF7;
border-right : 2px solid hsla(215, 81%, 79%, .3);
}
.ghostbar {
width : 3px;

@ -0,0 +1,45 @@
var yo = require('yo-yo')
// -------------- styling ----------------------
var csjs = require('csjs-inject')
var styleGuide = require('./style-guide')
var styles = styleGuide()
var css = csjs`
.filesTabView {
padding: 2%;
}
.crow {
margin-top: 1em;
display: flex;
}
.infoBox extends ${styles.infoTextBox} {
margin-top: 2em;
}
`
module.exports = filesTab
function filesTab () {
return yo`
<div class="${css.filesTabView}" id="publishView">
<div class="${css.crow}">
<button id="gist" title="Publish all files as public gist on github.com">
<i class="fa fa-github"></i>
Publish Gist
</button>
Publish all open files to an anonymous github gist.<br>
</div>
<div class="${css.crow}">
<button id="copyOver" title="Copy all files to another instance of browser-solidity.">
Copy files
</button>
Copy all files to another instance of Browser-solidity.
</div>
<div class="${css.infoBox}">You can also load a gist by adding the following
<span class="pre">#gist=GIST_ID</span>
to your url, where GIST_ID is the id of the gist to load.
</div>
</div>
`
}

@ -4,6 +4,40 @@ var $ = require('jquery')
var utils = require('./utils')
// -------------- styling ----------------------
var csjs = require('csjs-inject')
var styleGuide = require('./style-guide')
var styles = styleGuide()
var css = csjs`
.col2 {
width: 70%;
float: left;
}
.col1 extends ${styles.titleL} {
width: 30%;
float: left;
}
.toggleText {
text-decoration: underline;
margin-left: 2px;
font-size: .9em;
}
.toggle {
font-size: 1.1em;
color: ${styles.colors.blue};
margin: 1em;
cursor: pointer;
font-weight: 400;
display: flex;
align-items: center;
}
.toggle:hover {
opacity: .8;
}
`
// ----------------------------------------------
function Renderer (appAPI, formalVerificationEvent, compilerEvent) {
this.appAPI = appAPI
var self = this
@ -96,16 +130,17 @@ Renderer.prototype.contracts = function (data, source) {
}
var tableRowItems = function (first, second, cls) {
second.get(0).classList.add(styles.textBoxL) // replace <pre> styling with textBoxL
return $('<div class="crow"/>')
.addClass(cls)
.append($('<div class="col1">').append(first))
.append($('<div class="col2">').append(second))
.append($(`<div class="${css.col1}">`).append(first))
.append($(`<div class="${css.col2}">`).append(second))
}
var tableRow = function (description, data) {
return tableRowItems(
$('<span/>').text(description),
$('<input readonly="readonly"/>').val(data))
$(`<input class="${css.col2} ${styles.textBoxL}" readonly="readonly"/>`).val(data))
}
var preRow = function (description, data) {
@ -219,9 +254,25 @@ Renderer.prototype.contracts = function (data, source) {
var detailsOpen = {}
var getDetails = function (contract, source, contractName) {
var button = $('<button>Toggle Details</button>')
var button = $(`<div class="${css.toggle}"><i class="fa fa-info-circle" aria-hidden="true"></i><div class="${css.toggleText}">Contract details (bytecode, interface etc.)</div></div>`)
var details = $('<div style="display: none;"/>')
if (contract.bytecode) {
details.append(preRow('Bytecode', contract.bytecode))
}
details.append(preRow('Interface', contract['interface']))
if (contract.bytecode) {
details.append(preRow('Web3 deploy', gethDeploy(contractName.toLowerCase(), contract['interface'], contract.bytecode), 'deploy'))
// check if there's a metadata hash appended
var metadataHash = retrieveMetadataHash(contract.bytecode)
if (metadataHash) {
details.append(preRow('Metadata location', 'bzzr://' + metadataHash))
}
}
if (contract.metadata) {
details.append(preRow('Metadata', contract.metadata))
}
@ -264,22 +315,6 @@ Renderer.prototype.contracts = function (data, source) {
var self = this
var renderOutputModifier = function (contractName, $contractOutput) {
var contract = data.contracts[contractName]
if (contract.bytecode) {
$contractOutput.append(tableRow('Bytecode', contract.bytecode))
}
$contractOutput.append(tableRow('Interface', contract['interface']))
if (contract.bytecode) {
$contractOutput.append(preRow('Web3 deploy', gethDeploy(contractName.toLowerCase(), contract['interface'], contract.bytecode), 'deploy'))
// check if there's a metadata hash appended
var metadataHash = retrieveMetadataHash(contract.bytecode)
if (metadataHash) {
$contractOutput.append(tableRow('Metadata location', 'bzzr://' + metadataHash))
}
}
var ctrSource = self.appAPI.currentCompiledSourceCode()
if (ctrSource) {
$contractOutput.append(getDetails(contract, ctrSource, contractName))
@ -306,9 +341,8 @@ Renderer.prototype.contracts = function (data, source) {
}
})
$contractOutput.find('.title').click(function (ev) { $(this).closest('.contract').toggleClass('hidesub') })
$('#output').append($contractOutput)
$('.col2 input,textarea').click(function () { this.select() })
$('.' + css.col2 + ' input,textarea').click(function () { this.select() })
}
module.exports = Renderer

@ -0,0 +1,69 @@
var yo = require('yo-yo')
// -------------- styling ----------------------
var csjs = require('csjs-inject')
var styleGuide = require('./style-guide')
var styles = styleGuide()
var css = csjs`
.settingsTabView {
padding: 2%;
display: flex;
}
.info extends ${styles.infoTextBox} {
margin-bottom: 2em;
}
.crow {
margin-top: 1em;
display: flex;
}
.select extends ${styles.dropdown} {
float: left;
max-width: 90%;
}
.button extends ${styles.button} {
background-color: #C6CFF7;
width: 100%;
align-self: center;
text-align: -webkit-center;
}
.col1 extends ${styles.titleL} {
float: left;
align-self: center;
}
.checkboxText {
margin-left: 3px;
}
}
`
module.exports = settingsTab
function settingsTab () {
return yo`
<div class="${css.settingsTabView} "id="settingsView">
<div class="${css.info}">
<div>Your current Solidity version is</div>
<div id="version"></div>
</div>
<div class="${css.crow}">
<select class="${css.select}" id="versionSelector"></select>
</div>
<div class="${css.crow}">
<div><input class="${css.col1}" id="editorWrap" type="checkbox"></div>
<span class="${css.checkboxText}">Text Wrap</span>
</div>
<div class="${css.crow}">
<div><input class="${css.col1}" id="optimize" type="checkbox"></div>
<span class="${css.checkboxText}">Enable Optimization</span>
</div>
<div class="${css.crow}">
<div><input class="${css.col1}" id="autoCompile" type="checkbox" checked></div>
<span class="${css.checkboxText}">Auto Compile</span>
</div>
</div>
<div class="${css.crow}">
<div class="${css.button} "id="compile" title="Compile source code">Compile</div>
</div>
</div>
`
}

@ -1,5 +1,5 @@
var name = 'gas costs'
var desc = 'Warn if the gas requiremets of functions are too high.'
var name = 'gas costs: '
var desc = 'warn if the gas requiremets of functions are too high'
var categories = require('./categories')
function gasCosts () {

@ -1,5 +1,5 @@
var name = 'this on local'
var desc = 'Invocation of local functions via this'
var name = 'this on local: '
var desc = 'invocation of local functions via this'
var categories = require('./categories')
var common = require('./staticAnalysisCommon')

@ -1,4 +1,4 @@
var name = 'tx origin'
var name = 'tx origin: '
var desc = 'warn if tx.origin is used'
var categories = require('./categories')

@ -7,9 +7,11 @@ var csjs = require('csjs-inject')
var css = csjs`
.analysis {
margin-top: 2em;
font-height: 1.5em;
}
.result {
margin-top: 1em;
}
`
function staticAnalysisView (appAPI, compilerEvent) {
@ -33,17 +35,19 @@ function staticAnalysisView (appAPI, compilerEvent) {
staticAnalysisView.prototype.render = function () {
var self = this
var view = yo`<div class="${css.analysis}">
<strong>Static Analysis</strong>
<label for="autorunstaticanalysis"><input id="autorunstaticanalysis" type="checkbox" style="vertical-align:bottom" checked="true">Auto run</label>
<div id="staticanalysismodules">
${this.modulesView}
</div>
<div>
<button onclick=${function () { self.run() }} >Run</button>
var view = yo`
<div class="${css.analysis}">
<strong class="${css.title}">Static Analysis</strong><br>
<label for="autorunstaticanalysis"><input id="autorunstaticanalysis" type="checkbox" style="vertical-align:bottom" checked="true">Auto run</label>
<div id="staticanalysismodules">
${this.modulesView}
</div>
<div>
<button onclick=${function () { self.run() }} >Run</button>
</div>
<div class="${css.result}" "id='staticanalysisresult'></div>
</div>
<div id='staticanalysisresult'></div>
</div>`
`
if (!this.view) {
this.view = view
}

@ -0,0 +1,153 @@
var csjs = require('csjs-inject')
module.exports = styleGuide
function styleGuide () {
/* --------------------------------------------------------------------------
COLORS
-------------------------------------------------------------------------- */
var colors = {
blue: '#9393bf',
lightBlue: '#F4F6FF',
greyBlue: '#102026',
grey: '#666',
lightGrey: '#dddddd',
red: '#FF8080',
lightRed: '#FFB9B9',
green: '#B1EAC5',
violet: '#C6CFF7',
pink: '#EC96EC',
yellow: '#ffbd01'
}
/* --------------------------------------------------------------------------
FONTS
-------------------------------------------------------------------------- */
var texts = csjs `
.title-XL {
font-size : 2em;
font-weight : 700;
letter-spacing : .05em;
}
.title-L {
font-size : 1em;
font-weight : 600;
}
.title-M {
font-size : 1em;
font-weight : 400;
}
.title-S {
font-size : .8em;
font-weight : 300;
}
.text {
font-size : .8em;
}
`
/* --------------------------------------------------------------------------
TEXT-BOXES
-------------------------------------------------------------------------- */
var textBoxes = csjs`
.display-box-L {
font-size : 1em;
padding : 8px 15px;
line-height : 20px;
background : #f8f8f8;
border-radius : 3px;
border : 1px solid #e5e5e5;
overflow-x : auto;
width : 100%;
}
.info-text-box {
background-color : white;
line-height : 20px;
border : .2em dotted lightGrey;
padding : 8px 15px;
border-radius : 5px;
margin-bottom : 1em;
}
.warning-text-box {
background-color : #E6E5A7; // yellow
line-height : 20px;
padding : 1em 1em .5em 1em;
border-radius : 3px;
box-shadow : rgba(0,0,0,.2) 0 1px 4px;
margin-bottom : 1em;
}
.error-text-box {
background-color : #FFB9B9; // light-red
line-height : 20px;
padding : 1em 1em .5em 1em;
border-radius : 3px;
box-shadow : rgba(0,0,0,.2) 0 1px 4px;
margin-bottom : 1em;
}
.title-box {
margin-bottom : 0.4em;
padding : 1em;
background-color : transparent;
font-weight : bold;
display : flex;
justify-content : space-between;
word-wrap : break-word;
position : relative;
border-radius : 3px;
}
`
/* --------------------------------------------------------------------------
BUTTONS
-------------------------------------------------------------------------- */
var buttons = csjs`
.button {
border-color : transparent;
border-radius : 3px;
cursor : pointer;
padding : .3em;
}
.button:hover {
opacity : 0.8;
}
.dropdown-menu {
font-size : 1em;
text-decoration : none;
background-color : #C6CFF7;
cursor : pointer;
font-size : 12px;
border : none;
height : 20px;
}
`
/* --------------------------------------------------------------------------
INPUT FIELDS
-------------------------------------------------------------------------- */
/*
.input-field {
border : 1px solid #f0f0f0; // light-grey
padding : .3em;
margin : .3em;
}
*/
return {
textBoxL: textBoxes['display-box-L'],
infoTextBox: textBoxes['info-text-box'],
titleL: texts['title-L'],
titleM: texts['title-M'],
dropdown: buttons['dropdown-menu'],
button: buttons['button'],
colors: colors,
titleBox: textBoxes['title-box']
}
}

@ -9,7 +9,15 @@ var EventManager = require('./lib/eventManager')
var crypto = require('crypto')
var async = require('async')
var TxRunner = require('./app/txRunner')
var yo = require('yo-yo')
// copy to copyToClipboard
const copy = require('clipboard-copy')
// -------------- styling ----------------------
var csjs = require('csjs-inject')
var styleGuide = require('./app/style-guide')
var styles = styleGuide()
var css = csjs`
.options {
@ -21,7 +29,75 @@ var css = csjs`
margin-right: 0.5em;
font-size: 1em;
}
.title extends ${styles.titleBox} {
cursor: pointer;
background-color: ${styles.colors.violet};
}
.title:hover {
opacity: .8;
}
.contract .title:before {
content: "\\25BE";
}
.contract.hidesub .title:before {
content: "\\25B8"
}
.contract.hidesub {
padding-bottom: 0;
margin: 0;
}
.contract.hidesub > *:not(.title) {
display: none;
}
`
var cssInstance = csjs`
.title {
display: flex;
justify-content: center;
margin-bottom: 1em;
padding: 1em;
font-size: .95em;
cursor: pointer;
background-color: ${styles.colors.violet};
border: 2px dotted ${styles.colors.blue};
border-radius: 5px;
}
.titleText {
margin-right: 1em;
word-break: break-all;
}
.titleText:hover {
opacity: .8;
}
.instance .title:before {
content: "\\25BE";
margin-right: .5em;
}
.instance.hidesub .title:before {
content: "\\25B8"
margin-right: .5em;
}
.instance.hidesub {
padding-bottom: 0;
margin: 0;
}
.instance.hidesub > *:not(.title) {
display: none;
}
.copy extends ${styles.button} {
border: 1px dotted ${styles.colors.grey};
border-radius: 5px;
text-align: center;
padding: 1em .3em;
min-width: 30%;
}
.copy:hover{
background-color: ${styles.colors.lightGrey};
opacity: .8;
}
`
;[...document.querySelectorAll('#header #options li')].forEach(addCss)
function addCss (el) { el.classList.add(css.options) }
@ -164,20 +240,20 @@ UniversalDApp.prototype.render = function () {
.append($('<div class="publish"/>').text('Publish'))
.append($('<div class="attach"/>').text('Attach'))
.append($('<div class="transact"/>').text('Transact'))
.append($('<div class="payable"/>').text('Transact (Payable)'))
.append($('<div class="payable"/>').text('Transact(Payable)'))
.append($('<div class="call"/>').text('Call'))
self.$el.append($legend)
for (var c in self.contracts) {
var $contractEl = $('<div class="contract"/>')
var $contractEl = $(`<div class="contract ${css.contract}"/>`)
if (self.contracts[c].address) {
self.getInstanceInterface(self.contracts[c], self.contracts[c].address, $contractEl)
} else {
var $title = $('<span class="title"/>').text(self.contracts[c].name)
var $title = $(`<span class="${css.title}"/>`).text(self.contracts[c].name)
$title.click(function (ev) { $(this).closest(`.${css.contract}`).toggleClass(`${css.hidesub}`) })
if (self.contracts[c].bytecode) {
$title.addClass('definitionTitle')
$title.append($('<div class="size"/>').text((self.contracts[c].bytecode.length / 2) + ' bytes'))
}
$contractEl.append($title).append(self.getCreateInterface($contractEl, self.contracts[c]))
@ -207,7 +283,7 @@ UniversalDApp.prototype.getCreateInterface = function ($container, contract) {
$createInterface.append($close)
}
var $publishButton = $('<button class="publishContract"/>').text('Publish').click(function () { self.event.trigger('publishContract', [contract]) })
var $publishButton = $(`<button class="publishContract"/>`).text('Publish').click(function () { self.event.trigger('publishContract', [contract]) })
$createInterface.append($publishButton)
var $atButton = $('<button class="atAddress"/>').text('At Address').click(function () { self.clickContractAt(self, $container.find('.createContract'), contract) })
@ -264,7 +340,7 @@ UniversalDApp.prototype.getInstanceInterface = function (contract, address, $tar
var $createInterface = $('<div class="createContract"/>')
var appendFunctions = function (address, $el) {
var $instance = $('<div class="instance"/>')
var $instance = $(`<div class="instance ${cssInstance.instance}"/>`)
if (self.options.removable_instances) {
var $close = $('<div class="udapp-close" />')
$close.click(function () { $instance.remove() })
@ -273,10 +349,19 @@ UniversalDApp.prototype.getInstanceInterface = function (contract, address, $tar
var context = self.executionContext.isVM() ? 'memory' : 'blockchain'
address = (address.slice(0, 2) === '0x' ? '' : '0x') + address.toString('hex')
var $title = $('<span class="title"/>').text(contract.name + ' at ' + address + ' (' + context + ')')
$title.click(function () {
$instance.toggleClass('hidesub')
})
var title = yo`
<div class="${cssInstance.title}">
<div class="${cssInstance.titleText}" onclick=${toggleClass}> ${contract.name} at ${address} (${context}) </div>
<div class="${cssInstance.copy}" onclick=${copyToClipboard}> <i class="fa fa-clipboard" aria-hidden="true"></i> Copy address </div>
</div>
`
function toggleClass () {
$instance.toggleClass(`${cssInstance.hidesub}`)
}
function copyToClipboard () {
copy(address)
}
var $events = $('<div class="events"/>')
@ -336,7 +421,7 @@ UniversalDApp.prototype.getInstanceInterface = function (contract, address, $tar
var eventFilter = self.web3.eth.contract(abi).at(address).allEvents()
eventFilter.watch(parseLogs)
}
$instance.append($title)
$instance.get(0).appendChild(title)
// Add the fallback function
var fallback = self.getFallbackInterface(abi)
@ -615,7 +700,6 @@ UniversalDApp.prototype.getCallButton = function (args) {
var outputObj = '0x' + result.vm.return.toString('hex')
clearOutput($result)
$result.append(getReturnOutput(outputObj)).append(getGasUsedOutput(result, result.vm))
decoded = decodeResponse(result.vm.return)
if (decoded) {
$result.append(decoded)

@ -6,7 +6,7 @@ module.exports = {
}
function checkCompiledContracts (browser, compiled, callback) {
browser.elements('css selector', '.udapp .contract .title', function (elements) {
browser.elements('css selector', '.udapp .title', function (elements) {
elements.value.map(function (item, i) {
browser.elementIdText(item.ELEMENT, function (text) {
browser.assert.equal(text.value.split('\n')[0], compiled[i])
@ -21,7 +21,7 @@ function testContracts (browser, contractCode, compiledContractNames, callback)
.clearValue('#input textarea')
.click('.newFile')
.setValue('#input textarea', contractCode, function () {})
.waitForElementPresent('.contract .create', 5000, true, function () {
.waitForElementPresent('.udapp .create', 5000, true, function () {
checkCompiledContracts(browser, compiledContractNames, callback)
})
}

Loading…
Cancel
Save