Commit fb3420b0 authored by d11e9's avatar d11e9

allow loading gists

parent 1438054a
...@@ -50,627 +50,648 @@ THE SOFTWARE. ...@@ -50,627 +50,648 @@ THE SOFTWARE.
</head> </head>
<body> <body>
<div id="editor"> <div id="editor">
<div id="files"> <div id="files">
<span class="newFile" title="New File"><i class="fa fa-file-text-o"></i></span> <span class="newFile" title="New File"><i class="fa fa-file-text-o"></i></span>
<span class="toggleRHP" title="Toggle right hand panel"><i class="fa fa-columns"></i></span> <span class="toggleRHP" title="Toggle right hand panel"><i class="fa fa-columns"></i></span>
</div> </div>
<div id="input"></div> <div id="input"></div>
<div id="dragbar"></div> <div id="dragbar"></div>
</div> </div>
<div id="righthand-panel"> <div id="righthand-panel">
<div id="header"> <div id="header">
<img id="solIcon" title="Solidity realtime compiler and runtime" src="assets/img/sol.gif"> <img id="solIcon" title="Solidity realtime compiler and runtime" src="assets/img/sol.gif">
<div class="info"> <div class="info">
<div class="version">Solidity version: <span id="version">(loading)</span> <br/>Change to: <select id="versionSelector"></select></div> <div class="version">Solidity version: <span id="version">(loading)</span> <br/>Change to: <select id="versionSelector"></select></div>
</div> </div>
<div id="optimizeBox"> <div id="optimizeBox">
<button id="gist" title="Publish all files as public gist on github.com"><i class="fa fa-github"></i> Publish gist</button> <button id="gist" title="Publish all files as public gist on github.com"><i class="fa fa-github"></i> Publish gist</button>
<label for="editorWrap"><input id="editorWrap" type="checkbox">Text Wrap</label> <label for="editorWrap"><input id="editorWrap" type="checkbox">Text Wrap</label>
<label for="optimize"><input id="optimize" type="checkbox">Enable Optimization</label> <label for="optimize"><input id="optimize" type="checkbox">Enable Optimization</label>
<code class="origin">tx.origin: <span id="txorigin"/></code> <code class="origin">tx.origin: <span id="txorigin"/></code>
<span id="executionContext"> <span id="executionContext">
<label for="vm" title="Execution environment does not connect to any node, everything is local and in memory only."> <label for="vm" title="Execution environment does not connect to any node, everything is local and in memory only.">
<input id="vm" type="radio" value="vm" checked name="executionContext"> <input id="vm" type="radio" value="vm" checked name="executionContext">
JavaScript VM JavaScript VM
</label> </label>
<label for="web3" title="Execution environment connects to node at localhost, transactions will be sent to the network and can cause loss of money or worse!"> <label for="web3" title="Execution environment connects to node at localhost, transactions will be sent to the network and can cause loss of money or worse!">
<input id="web3" type="radio" value="web3" name="executionContext"> <input id="web3" type="radio" value="web3" name="executionContext">
Web3 Provider Web3 Provider
</label> </label>
</span> </span>
</div> </div>
</div> </div>
<div id="output"></div> <div id="output"></div>
</div> </div>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
// ----------------- editor ---------------------- // ----------------- editor ----------------------
var SOL_CACHE_FILE_PREFIX = 'sol-cache-file-'; var SOL_CACHE_FILE_PREFIX = 'sol-cache-file-';
var SOL_CACHE_UNTITLED = SOL_CACHE_FILE_PREFIX + 'Untitled'; var SOL_CACHE_UNTITLED = SOL_CACHE_FILE_PREFIX + 'Untitled';
var SOL_CACHE_FILE = null; var SOL_CACHE_FILE = null;
var editor = ace.edit("input"); var editor = ace.edit("input");
var session = editor.getSession(); var session = editor.getSession();
var Range = ace.require('ace/range').Range; var Range = ace.require('ace/range').Range;
var errMarkerId = null; var errMarkerId = null;
var untitledCount = ''; var untitledCount = '';
if (!getFiles().length || window.localStorage['sol-cache']) { if (!getFiles().length || window.localStorage['sol-cache']) {
// Backwards-compatibility // Backwards-compatibility
while (window.localStorage[SOL_CACHE_UNTITLED + untitledCount]) while (window.localStorage[SOL_CACHE_UNTITLED + untitledCount])
untitledCount = (untitledCount - 0) + 1; untitledCount = (untitledCount - 0) + 1;
SOL_CACHE_FILE = SOL_CACHE_UNTITLED + untitledCount; SOL_CACHE_FILE = SOL_CACHE_UNTITLED + untitledCount;
window.localStorage[SOL_CACHE_FILE] = window.localStorage['sol-cache'] || BALLOT_EXAMPLE; window.localStorage[SOL_CACHE_FILE] = window.localStorage['sol-cache'] || BALLOT_EXAMPLE;
window.localStorage.removeItem('sol-cache'); window.localStorage.removeItem('sol-cache');
} }
SOL_CACHE_FILE = getFiles()[0]; SOL_CACHE_FILE = getFiles()[0];
editor.setValue( window.localStorage[SOL_CACHE_FILE], -1); editor.setValue( window.localStorage[SOL_CACHE_FILE], -1);
editor.resize(true); editor.resize(true);
session.setMode("ace/mode/javascript"); session.setMode("ace/mode/javascript");
session.setTabSize(4); session.setTabSize(4);
session.setUseSoftTabs(true); session.setUseSoftTabs(true);
// ----------------- execution context ------------- // ----------------- execution context -------------
var $vmToggle = $('#vm'); var $vmToggle = $('#vm');
var $web3Toggle = $('#web3'); var $web3Toggle = $('#web3');
var executionContext = 'vm'; var executionContext = 'vm';
$vmToggle.get(0).checked = true; $vmToggle.get(0).checked = true;
$vmToggle.on('change', executionContextChange ); $vmToggle.on('change', executionContextChange );
$web3Toggle.on('change', executionContextChange ); $web3Toggle.on('change', executionContextChange );
function executionContextChange (ev) { function executionContextChange (ev) {
if (ev.target.value == 'web3' && !confirm("Are you sure you want to connect to a local ethereum node?") ) { if (ev.target.value == 'web3' && !confirm("Are you sure you want to connect to a local ethereum node?") ) {
$vmToggle.get(0).checked = true; $vmToggle.get(0).checked = true;
executionContext = 'vm'; executionContext = 'vm';
} else executionContext = ev.target.value; } else executionContext = ev.target.value;
compile(); compile();
} }
// ------------------ gist publish --------------
// ------------------ gist load ----------------
$('#gist').click(function(){
if (confirm("Are you sure you want to publish all your files anonymously as a public gist on github.com")) { var location_hash_params = window.location.hash.substr(1).split("=");
if (location_hash_params.length == 2 && location_hash_params[0] == 'gist') {
var files = {}; $.ajax({
var filesArr = getFiles(); url: 'https://api.github.com/gists/'+location_hash_params[1],
var description = "Ethereum Contracts Gist created using soleditor at: https://chriseth.github.io/browser-solidity"; jsonp: 'callback',
dataType: 'jsonp',
for(var f in filesArr) { success: function(response){
files[fileNameFromKey(filesArr[f])] = { if (response.data) {
content: localStorage[filesArr[f]] for(var f in response.data.files) {
}; window.localStorage[fileKey(f)] = response.data.files[f].content;
} }
updateFiles();
$.ajax({ }
url: 'https://api.github.com/gists', }
type: 'POST', })
data: JSON.stringify({ }
description: description,
public: true,
files: files // ------------------ gist publish --------------
})
}).done(function(response) { $('#gist').click(function(){
if (response.html_url && confirm("Created a gist at " + response.html_url + " Would you like to open it in a new window?")) { if (confirm("Are you sure you want to publish all your files anonymously as a public gist on github.com")) {
window.open( response.html_url, '_blank' );
} var files = {};
}); var filesArr = getFiles();
} var description = "Ethereum Contracts Gist created using soleditor at: https://chriseth.github.io/browser-solidity to load gist in soleditor append #gist=gistid to the url, where gistid is the id in this gist url.";
})
for(var f in filesArr) {
files[fileNameFromKey(filesArr[f])] = {
// ----------------- file selector------------- content: localStorage[filesArr[f]]
};
var $filesEl = $('#files'); }
$filesEl.on('click','.newFile', function() { $.ajax({
while (window.localStorage[SOL_CACHE_UNTITLED + untitledCount]) url: 'https://api.github.com/gists',
untitledCount = (untitledCount - 0) + 1; type: 'POST',
SOL_CACHE_FILE = SOL_CACHE_UNTITLED + untitledCount; data: JSON.stringify({
window.localStorage[SOL_CACHE_FILE] = ''; description: description,
updateFiles(); public: true,
}) files: files
})
$filesEl.on('click', '.file:not(.active)', showFileHandler); }).done(function(response) {
if (response.html_url && confirm("Created a gist at " + response.html_url + " Would you like to open it in a new window?")) {
$filesEl.on('click', '.file.active', function(ev) { window.open( response.html_url, '_blank' );
var $fileTabEl = $(this); }
var originalName = $fileTabEl.find('.name').text(); });
ev.preventDefault(); }
if ($(this).find('input').length > 0) return false; })
var $fileNameInputEl = $('<input value="'+originalName+'"/>');
$fileTabEl.html($fileNameInputEl);
$fileNameInputEl.focus(); // ----------------- file selector-------------
$fileNameInputEl.select();
$fileNameInputEl.on('blur', handleRename); var $filesEl = $('#files');
$fileNameInputEl.keyup(handleRename);
$filesEl.on('click','.newFile', function() {
function handleRename(ev) { while (window.localStorage[SOL_CACHE_UNTITLED + untitledCount])
ev.preventDefault(); untitledCount = (untitledCount - 0) + 1;
if (ev.which && ev.which !== 13) return false; SOL_CACHE_FILE = SOL_CACHE_UNTITLED + untitledCount;
var newName = ev.target.value; window.localStorage[SOL_CACHE_FILE] = '';
$fileNameInputEl.off('blur'); updateFiles();
$fileNameInputEl.off('keyup'); })
if (newName !== originalName && confirm("Are you sure you want to rename: " + originalName + " to " + newName + '?')) { $filesEl.on('click', '.file:not(.active)', showFileHandler);
var content = window.localStorage.getItem( fileKey(originalName) );
window.localStorage[fileKey( newName )] = content; $filesEl.on('click', '.file.active', function(ev) {
window.localStorage.removeItem( fileKey( originalName) ); var $fileTabEl = $(this);
SOL_CACHE_FILE = fileKey( newName ); var originalName = $fileTabEl.find('.name').text();
} ev.preventDefault();
if ($(this).find('input').length > 0) return false;
updateFiles(); var $fileNameInputEl = $('<input value="'+originalName+'"/>');
return false; $fileTabEl.html($fileNameInputEl);
} $fileNameInputEl.focus();
$fileNameInputEl.select();
return false; $fileNameInputEl.on('blur', handleRename);
}) $fileNameInputEl.keyup(handleRename);
$filesEl.on('click', '.file .remove', function(ev) { function handleRename(ev) {
ev.preventDefault(); ev.preventDefault();
var name = $(this).parent().find('.name').text(); if (ev.which && ev.which !== 13) return false;
var index = getFiles().indexOf( fileKey(name) ); var newName = ev.target.value;
$fileNameInputEl.off('blur');
if (confirm("Are you sure you want to remove: " + name + " from local storage?")) { $fileNameInputEl.off('keyup');
window.localStorage.removeItem( fileKey( name ) );
SOL_CACHE_FILE = getFiles()[ Math.max(0, index - 1)]; if (newName !== originalName && confirm("Are you sure you want to rename: " + originalName + " to " + newName + '?')) {
updateFiles(); var content = window.localStorage.getItem( fileKey(originalName) );
} window.localStorage[fileKey( newName )] = content;
return false; window.localStorage.removeItem( fileKey( originalName) );
}); SOL_CACHE_FILE = fileKey( newName );
}
function showFileHandler(ev) {
ev.preventDefault(); updateFiles();
SOL_CACHE_FILE = fileKey( $(this).find('.name').text() ); return false;
updateFiles(); }
return false;
} return false;
})
function fileTabFromKey(key) {
var name = fileNameFromKey(key); $filesEl.on('click', '.file .remove', function(ev) {
return $('#files .file').filter(function(){ return $(this).find('.name').text() == name; }); ev.preventDefault();
} var name = $(this).parent().find('.name').text();
var index = getFiles().indexOf( fileKey(name) );
function updateFiles() { if (confirm("Are you sure you want to remove: " + name + " from local storage?")) {
$filesEl.find('.file').remove(); window.localStorage.removeItem( fileKey( name ) );
var files = getFiles(); SOL_CACHE_FILE = getFiles()[ Math.max(0, index - 1)];
for (var f in files) { updateFiles();
$filesEl.append(fileTabTemplate(files[f])); }
} return false;
});
if (SOL_CACHE_FILE) {
var active = fileTabFromKey(SOL_CACHE_FILE); function showFileHandler(ev) {
active.addClass('active'); ev.preventDefault();
editor.setValue( window.localStorage[SOL_CACHE_FILE] || '', -1); SOL_CACHE_FILE = fileKey( $(this).find('.name').text() );
editor.focus(); updateFiles();
$('#input').toggle( true ); return false;
} else { }
$('#input').toggle( false );
} function fileTabFromKey(key) {
} var name = fileNameFromKey(key);
return $('#files .file').filter(function(){ return $(this).find('.name').text() == name; });
function fileTabTemplate(key) { }
var name = fileNameFromKey(key);
return $('<span class="file"><span class="name">'+name+'</span><span class="remove"><i class="fa fa-close"></i></span></span>');
} function updateFiles() {
$filesEl.find('.file').remove();
function fileKey( name ) { var files = getFiles();
return SOL_CACHE_FILE_PREFIX + name; for (var f in files) {
} $filesEl.append(fileTabTemplate(files[f]));
}
function fileNameFromKey(key) {
return key.replace( SOL_CACHE_FILE_PREFIX, '' ); if (SOL_CACHE_FILE) {
} var active = fileTabFromKey(SOL_CACHE_FILE);
active.addClass('active');
function getFiles() { editor.setValue( window.localStorage[SOL_CACHE_FILE] || '', -1);
var files = []; editor.focus();
for (var f in localStorage ) { $('#input').toggle( true );
if (f.indexOf( SOL_CACHE_FILE_PREFIX, 0 ) === 0) { } else {
files.push(f); $('#input').toggle( false );
} }
} }
return files;
} function fileTabTemplate(key) {
var name = fileNameFromKey(key);
updateFiles(); return $('<span class="file"><span class="name">'+name+'</span><span class="remove"><i class="fa fa-close"></i></span></span>');
}
// ----------------- version selector-------------
function fileKey( name ) {
// var soljsonSources is provided by bin/list.js return SOL_CACHE_FILE_PREFIX + name;
$('option', '#versionSelector').remove(); }
$.each(soljsonSources, function(i, file) {
if (file) { function fileNameFromKey(key) {
var version = file.replace(/soljson-(.*).js/, "$1"); return key.replace( SOL_CACHE_FILE_PREFIX, '' );
$('#versionSelector').append(new Option(version, file)); }
}
}); function getFiles() {
$('#versionSelector').change(function() { var files = [];
Module = null; for (var f in localStorage ) {
compileJSON = null; if (f.indexOf( SOL_CACHE_FILE_PREFIX, 0 ) === 0) {
var script = document.createElement('script'); files.push(f);
script.type = 'text/javascript'; }
script.src = 'bin/' + $('#versionSelector').val(); }
$('head').append(script); return files;
onCompilerLoaded(); }
});
updateFiles();
// ----------------- resizeable ui ---------------
// ----------------- version selector-------------
var EDITOR_SIZE_CACHE_KEY = "editor-size-cache";
var dragging = false; // var soljsonSources is provided by bin/list.js
$('#dragbar').mousedown(function(e){ $('option', '#versionSelector').remove();
e.preventDefault(); $.each(soljsonSources, function(i, file) {
dragging = true; if (file) {
var main = $('#righthand-panel'); var version = file.replace(/soljson-(.*).js/, "$1");
var ghostbar = $('<div id="ghostbar">', { $('#versionSelector').append(new Option(version, file));
css: { }
top: main.offset().top, });
left: main.offset().left $('#versionSelector').change(function() {
} Module = null;
}).prependTo('body'); compileJSON = null;
var script = document.createElement('script');
$(document).mousemove(function(e){ script.type = 'text/javascript';
ghostbar.css("left",e.pageX+2); script.src = 'bin/' + $('#versionSelector').val();
}); $('head').append(script);
}); onCompilerLoaded();
});
var $body = $('body');
// ----------------- resizeable ui ---------------
function setEditorSize (delta) {
$('#righthand-panel').css("width", delta); var EDITOR_SIZE_CACHE_KEY = "editor-size-cache";
$('#editor').css("right", delta); var dragging = false;
onResize(); $('#dragbar').mousedown(function(e){
} e.preventDefault();
dragging = true;
function getEditorSize(){ var main = $('#righthand-panel');
window.localStorage[EDITOR_SIZE_CACHE_KEY] = $('#righthand-panel').width(); var ghostbar = $('<div id="ghostbar">', {
} css: {
top: main.offset().top,
$(document).mouseup(function(e){ left: main.offset().left
if (dragging) { }
var delta = $body.width() - e.pageX+2; }).prependTo('body');
$('#ghostbar').remove();
$(document).unbind('mousemove'); $(document).mousemove(function(e){
dragging = false; ghostbar.css("left",e.pageX+2);
setEditorSize(delta); });
window.localStorage.setItem(EDITOR_SIZE_CACHE_KEY, delta); });
}
}); var $body = $('body');
// set cached defaults function setEditorSize (delta) {
var cachedSize = window.localStorage.getItem(EDITOR_SIZE_CACHE_KEY); $('#righthand-panel').css("width", delta);
if (cachedSize) setEditorSize(cachedSize); $('#editor').css("right", delta);
else getEditorSize(); onResize();
}
// ----------------- toggle right hand panel function getEditorSize(){
window.localStorage[EDITOR_SIZE_CACHE_KEY] = $('#righthand-panel').width();
var toggledRHP = false; }
$('.toggleRHP').click(function(){
toggledRHP = !toggledRHP; $(document).mouseup(function(e){
setEditorSize( toggledRHP ? 0 : window.localStorage[EDITOR_SIZE_CACHE_KEY] ); if (dragging) {
$('.toggleRHP').toggleClass('toggled', toggledRHP) var delta = $body.width() - e.pageX+2;
}); $('#ghostbar').remove();
$(document).unbind('mousemove');
dragging = false;
// ----------------- editor resize --------------- setEditorSize(delta);
window.localStorage.setItem(EDITOR_SIZE_CACHE_KEY, delta);
function onResize() { }
editor.resize(); });
session.setUseWrapMode(document.querySelector('#editorWrap').checked);
if(session.getUseWrapMode()) { // set cached defaults
var characterWidth = editor.renderer.characterWidth; var cachedSize = window.localStorage.getItem(EDITOR_SIZE_CACHE_KEY);
var contentWidth = editor.container.ownerDocument.getElementsByClassName("ace_scroller")[0].clientWidth; if (cachedSize) setEditorSize(cachedSize);
else getEditorSize();
if(contentWidth > 0) {
session.setWrapLimit(parseInt(contentWidth / characterWidth, 10));
} // ----------------- toggle right hand panel
}
} var toggledRHP = false;
window.onresize = onResize; $('.toggleRHP').click(function(){
onResize(); toggledRHP = !toggledRHP;
setEditorSize( toggledRHP ? 0 : window.localStorage[EDITOR_SIZE_CACHE_KEY] );
document.querySelector('#editor').addEventListener('change', onResize); $('.toggleRHP').toggleClass('toggled', toggledRHP)
document.querySelector('#editorWrap').addEventListener('change', onResize); });
// ----------------- compiler ---------------------- // ----------------- editor resize ---------------
var compileJSON;
function onResize() {
var previousInput = ''; editor.resize();
var sourceAnnotations = []; session.setUseWrapMode(document.querySelector('#editorWrap').checked);
var compile = function() { if(session.getUseWrapMode()) {
var characterWidth = editor.renderer.characterWidth;
editor.getSession().clearAnnotations(); var contentWidth = editor.container.ownerDocument.getElementsByClassName("ace_scroller")[0].clientWidth;
sourceAnnotations = [];
editor.getSession().removeMarker(errMarkerId); if(contentWidth > 0) {
$('#output').empty(); session.setWrapLimit(parseInt(contentWidth / characterWidth, 10));
var input = editor.getValue(); }
window.localStorage.setItem(SOL_CACHE_FILE, input); }
}
var inputIncludingImports = includeLocalImports(input); window.onresize = onResize;
var optimize = document.querySelector('#optimize').checked; onResize();
try { document.querySelector('#editor').addEventListener('change', onResize);
var data = $.parseJSON(compileJSON(inputIncludingImports, optimize ? 1 : 0)); document.querySelector('#editorWrap').addEventListener('change', onResize);
} catch (exception) {
renderError("Uncaught JavaScript Exception:\n" + exception);
return; // ----------------- compiler ----------------------
} var compileJSON;
var noFatalErrors = true; // ie warnings are ok var previousInput = '';
var sourceAnnotations = [];
if (data['error'] !== undefined) { var compile = function() {
renderError(data['error']);
if (errortype(data['error']) !== 'warning') noFatalErrors = false; editor.getSession().clearAnnotations();
} sourceAnnotations = [];
if (data['errors'] != undefined) { editor.getSession().removeMarker(errMarkerId);
$.each(data['errors'], function(i, err) { $('#output').empty();
renderError(err); var input = editor.getValue();
if (errortype(err) !== 'warning') noFatalErrors = false; window.localStorage.setItem(SOL_CACHE_FILE, input);
});
} var inputIncludingImports = includeLocalImports(input);
var optimize = document.querySelector('#optimize').checked;
if (noFatalErrors) renderContracts(data, input);
try {
} var data = $.parseJSON(compileJSON(inputIncludingImports, optimize ? 1 : 0));
} catch (exception) {
var compileTimeout = null; renderError("Uncaught JavaScript Exception:\n" + exception);
var onChange = function() { return;
var input = editor.getValue(); }
if (input === "") {
window.localStorage.setItem(SOL_CACHE_FILE, ''); var noFatalErrors = true; // ie warnings are ok
return;
} if (data['error'] !== undefined) {
if (input === previousInput) renderError(data['error']);
return; if (errortype(data['error']) !== 'warning') noFatalErrors = false;
previousInput = input; }
if (compileTimeout) window.clearTimeout(compileTimeout); if (data['errors'] != undefined) {
compileTimeout = window.setTimeout(compile, 300); $.each(data['errors'], function(i, err) {
}; renderError(err);
if (errortype(err) !== 'warning') noFatalErrors = false;
var onCompilerLoaded = function() { });
compileJSON = Module.cwrap("compileJSON", "string", ["string", "number"]); }
$('#version').text(Module.cwrap("version", "string", [])());
previousInput = ''; if (noFatalErrors) renderContracts(data, input);
onChange();
}; }
function includeLocalImports(input) { var compileTimeout = null;
var importRegex = /import\s[\'\"]([^\'\"]+)[\'\"];/g; var onChange = function() {
var imports = []; var input = editor.getValue();
var matches = []; if (input === "") {
var match; window.localStorage.setItem(SOL_CACHE_FILE, '');
while ((match = importRegex.exec(input)) !== null) { return;
if (match[1] && getFiles().indexOf(fileKey(match[1])) !== -1) { }
imports.push(match[1]); if (input === previousInput)
matches.push(match[0]); return;
} previousInput = input;
} if (compileTimeout) window.clearTimeout(compileTimeout);
for (var i in imports) { compileTimeout = window.setTimeout(compile, 300);
imported = includeLocalImports(window.localStorage.getItem( fileKey(imports[i]) )); };
input = input.replace(matches[i], imported);
} var onCompilerLoaded = function() {
return input; compileJSON = Module.cwrap("compileJSON", "string", ["string", "number"]);
} $('#version').text(Module.cwrap("version", "string", [])());
previousInput = '';
if (Module) onChange();
onCompilerLoaded(); };
editor.getSession().on('change', onChange); function includeLocalImports(input) {
var importRegex = /import\s[\'\"]([^\'\"]+)[\'\"];/g;
document.querySelector('#optimize').addEventListener('change', compile); var imports = [];
var matches = [];
// ----------------- compiler output renderer ---------------------- var match;
var detailsOpen = {}; while ((match = importRegex.exec(input)) !== null) {
if (match[1] && getFiles().indexOf(fileKey(match[1])) !== -1) {
function errortype(message) { imports.push(match[1]);
return message.match(/^[0-9:]* Warning: /) ? 'warning' : 'error'; matches.push(match[0]);
} }
}
var renderError = function(message) { for (var i in imports) {
var type = errortype(message); imported = includeLocalImports(window.localStorage.getItem( fileKey(imports[i]) ));
var $pre = $("<pre />").text(message); input = input.replace(matches[i], imported);
var $error = $('<div class="sol ' + type + '"><div class="close"><i class="fa fa-close"></i></div></div>').prepend($pre); }
$('#output').append( $error ); return input;
var err = message.match(/^:([0-9]*):([0-9]*)/); }
if (err && err.length) {
var errLine = parseInt(err[1], 10) - 1; if (Module)
var errCol = err[2] ? parseInt(err[2], 10) : 0; onCompilerLoaded();
sourceAnnotations[sourceAnnotations.length] = {
row: errLine, editor.getSession().on('change', onChange);
column: errCol,
text: message, document.querySelector('#optimize').addEventListener('change', compile);
type: type
}; // ----------------- compiler output renderer ----------------------
editor.getSession().setAnnotations(sourceAnnotations); var detailsOpen = {};
$error.click(function(ev){
editor.focus(); function errortype(message) {
editor.gotoLine(errLine + 1, errCol - 1, true); return message.match(/^[0-9:]* Warning: /) ? 'warning' : 'error';
}); }
$error.find('.close').click(function(ev){
ev.preventDefault(); var renderError = function(message) {
$error.remove(); var type = errortype(message);
return false; var $pre = $("<pre />").text(message);
}); var $error = $('<div class="sol ' + type + '"><div class="close"><i class="fa fa-close"></i></div></div>').prepend($pre);
} $('#output').append( $error );
}; var err = message.match(/^:([0-9]*):([0-9]*)/);
if (err && err.length) {
var gethDeploy = function(contractName, interface, bytecode){ var errLine = parseInt(err[1], 10) - 1;
var code = ""; var errCol = err[2] ? parseInt(err[2], 10) : 0;
var funABI = getConstructorInterface($.parseJSON(interface)); sourceAnnotations[sourceAnnotations.length] = {
row: errLine,
$.each(funABI.inputs, function(i, inp) { column: errCol,
code += "var " + inp.name + " = /* var of type " + inp.type + " here */ ;\n"; text: message,
}); type: type
};
code += "var " + contractName + "Contract = web3.eth.contract(" + interface.replace("\n","") + ");" editor.getSession().setAnnotations(sourceAnnotations);
+"\nvar " + contractName + " = " + contractName + "Contract.new("; $error.click(function(ev){
editor.focus();
$.each(funABI.inputs, function(i, inp) { editor.gotoLine(errLine + 1, errCol - 1, true);
code += "\n " + inp.name + ","; });
}); $error.find('.close').click(function(ev){
ev.preventDefault();
code += "\n {"+ $error.remove();
"\n from: web3.eth.accounts[0], "+ return false;
"\n data: '"+bytecode+"', "+ });
"\n gas: 3000000"+ }
"\n }, function(e, contract){"+ };
"\n if (typeof contract.address != 'undefined') {"+
"\n console.log(e, contract);"+ var gethDeploy = function(contractName, interface, bytecode){
"\n console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);" + var code = "";
"\n }" + var funABI = getConstructorInterface($.parseJSON(interface));
"\n })";
$.each(funABI.inputs, function(i, inp) {
code += "var " + inp.name + " = /* var of type " + inp.type + " here */ ;\n";
return code; });
};
code += "var " + contractName + "Contract = web3.eth.contract(" + interface.replace("\n","") + ");"
var combined = function(contractName, interface, bytecode){ +"\nvar " + contractName + " = " + contractName + "Contract.new(";
return JSON.stringify([{name: contractName, interface: interface, bytecode: bytecode}]);
$.each(funABI.inputs, function(i, inp) {
}; code += "\n " + inp.name + ",";
});
var renderContracts = function(data, source) {
for (var contractName in data.contracts) { code += "\n {"+
var contract = data.contracts[contractName]; "\n from: web3.eth.accounts[0], "+
var dapp = new UniversalDApp([{ "\n data: '"+bytecode+"', "+
name: contractName, "\n gas: 3000000"+
interface: contract['interface'], "\n }, function(e, contract){"+
bytecode: contract.bytecode "\n if (typeof contract.address != 'undefined') {"+
}], { "\n console.log(e, contract);"+
vm: executionContext === 'vm', "\n console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);" +
removable: false, "\n }" +
removable_instances: true "\n })";
});
var $contractOutput = dapp.render();
$contractOutput return code;
.append(textRow('Bytecode', contract.bytecode)) };
.append(textRow('Interface', contract['interface']))
.append(textRow('Web3 deploy', gethDeploy(contractName.toLowerCase(),contract['interface'],contract.bytecode), 'deploy')) var combined = function(contractName, interface, bytecode){
.append(textRow('uDApp', combined(contractName,contract['interface'],contract.bytecode), 'deploy')) return JSON.stringify([{name: contractName, interface: interface, bytecode: bytecode}]);
.append(getDetails(contract, source, contractName));
};
if (executionContext === 'vm') $('#txorigin').text('0x' + dapp.address.toString('hex'));
else web3.eth.getAccounts( function(err,accounts) { var renderContracts = function(data, source) {
if (err) renderError(err.message); for (var contractName in data.contracts) {
$('#txorigin').text(accounts[0]); var contract = data.contracts[contractName];
}); var dapp = new UniversalDApp([{
name: contractName,
$contractOutput.find('.title').click(function(ev){ $(this).closest('.udapp').toggleClass('hide') }); interface: contract['interface'],
$('#output').append( $contractOutput ); bytecode: contract.bytecode
} }], {
$('.col2 input,textarea').click(function() { this.select(); }); vm: executionContext === 'vm',
}; removable: false,
var tableRowItems = function(first, second, cls) { removable_instances: true
return $('<div class="row"/>') });
.addClass(cls) var $contractOutput = dapp.render();
.append($('<div class="col1">').append(first)) $contractOutput
.append($('<div class="col2">').append(second)); .append(textRow('Bytecode', contract.bytecode))
}; .append(textRow('Interface', contract['interface']))
var tableRow = function(description, data) { .append(textRow('Web3 deploy', gethDeploy(contractName.toLowerCase(),contract['interface'],contract.bytecode), 'deploy'))
return tableRowItems( .append(textRow('uDApp', combined(contractName,contract['interface'],contract.bytecode), 'deploy'))
$('<span/>').text(description), .append(getDetails(contract, source, contractName));
$('<input readonly="readonly"/>').val(data));
}; if (executionContext === 'vm') $('#txorigin').text('0x' + dapp.address.toString('hex'));
var textRow = function(description, data, cls) { else web3.eth.getAccounts( function(err,accounts) {
return tableRowItems( if (err) renderError(err.message);
$('<strong/>').text(description), $('#txorigin').text(accounts[0]);
$('<textarea readonly="readonly" class="gethDeployText"/>').val(data), });
cls);
}; $contractOutput.find('.title').click(function(ev){ $(this).closest('.udapp').toggleClass('hide') });
var getDetails = function(contract, source, contractName) { $('#output').append( $contractOutput );
var button = $('<button>Toggle Details</button>'); }
var details = $('<div style="display: none;"/>') $('.col2 input,textarea').click(function() { this.select(); });
.append(tableRow('Solidity Interface', contract.solidity_interface)) };
.append(tableRow('Opcodes', contract.opcodes)); var tableRowItems = function(first, second, cls) {
var funHashes = ''; return $('<div class="row"/>')
for (var fun in contract.functionHashes) .addClass(cls)
funHashes += contract.functionHashes[fun] + ' ' + fun + '\n'; .append($('<div class="col1">').append(first))
details.append($('<span class="col1">Functions</span>')); .append($('<div class="col2">').append(second));
details.append($('<pre/>').text(funHashes)); };
details.append($('<span class="col1">Gas Estimates</span>')); var tableRow = function(description, data) {
details.append($('<pre/>').text(formatGasEstimates(contract.gasEstimates))); return tableRowItems(
if (contract.runtimeBytecode && contract.runtimeBytecode.length > 0) $('<span/>').text(description),
details.append(tableRow('Runtime Bytecode', contract.runtimeBytecode)); $('<input readonly="readonly"/>').val(data));
if (contract.assembly !== null) };
{ var textRow = function(description, data, cls) {
details.append($('<span class="col1">Assembly</span>')); return tableRowItems(
var assembly = $('<pre/>').text(formatAssemblyText(contract.assembly, '', source)); $('<strong/>').text(description),
details.append(assembly); $('<textarea readonly="readonly" class="gethDeployText"/>').val(data),
} cls);
button.click(function() { detailsOpen[contractName] = !detailsOpen[contractName]; details.toggle(); }); };
if (detailsOpen[contractName]) var getDetails = function(contract, source, contractName) {
details.show(); var button = $('<button>Toggle Details</button>');
return $('<div class="contractDetails"/>').append(button).append(details); var details = $('<div style="display: none;"/>')
}; .append(tableRow('Solidity Interface', contract.solidity_interface))
var formatGasEstimates = function(data) { .append(tableRow('Opcodes', contract.opcodes));
var gasToText = function(g) { return g === null ? 'unknown' : g; } var funHashes = '';
var text = ''; for (var fun in contract.functionHashes)
if ('creation' in data) funHashes += contract.functionHashes[fun] + ' ' + fun + '\n';
text += 'Creation: ' + gasToText(data.creation[0]) + ' + ' + gasToText(data.creation[1]) + '\n'; details.append($('<span class="col1">Functions</span>'));
text += 'External:\n'; details.append($('<pre/>').text(funHashes));
for (var fun in data.external) details.append($('<span class="col1">Gas Estimates</span>'));
text += ' ' + fun + ': ' + gasToText(data.external[fun]) + '\n'; details.append($('<pre/>').text(formatGasEstimates(contract.gasEstimates)));
text += 'Internal:\n'; if (contract.runtimeBytecode && contract.runtimeBytecode.length > 0)
for (var fun in data.internal) details.append(tableRow('Runtime Bytecode', contract.runtimeBytecode));
text += ' ' + fun + ': ' + gasToText(data.internal[fun]) + '\n'; if (contract.assembly !== null)
return text; {
}; details.append($('<span class="col1">Assembly</span>'));
var formatAssemblyText = function(asm, prefix, source) { var assembly = $('<pre/>').text(formatAssemblyText(contract.assembly, '', source));
if (typeof(asm) == typeof('') || asm === null || asm === undefined) details.append(assembly);
return prefix + asm + '\n'; }
var text = prefix + '.code\n'; button.click(function() { detailsOpen[contractName] = !detailsOpen[contractName]; details.toggle(); });
$.each(asm['.code'], function(i, item) { if (detailsOpen[contractName])
var v = item.value === undefined ? '' : item.value; details.show();
var src = ''; return $('<div class="contractDetails"/>').append(button).append(details);
if (item.begin !== undefined && item.end != undefined) };
src = source.slice(item.begin, item.end).replace('\n', '\\n', 'g'); var formatGasEstimates = function(data) {
if (src.length > 30) var gasToText = function(g) { return g === null ? 'unknown' : g; }
src = src.slice(0, 30) + '...'; var text = '';
if (item.name != 'tag') if ('creation' in data)
text += ' '; text += 'Creation: ' + gasToText(data.creation[0]) + ' + ' + gasToText(data.creation[1]) + '\n';
text += prefix + item.name + ' ' + v + '\t\t\t' + src + '\n'; text += 'External:\n';
}); for (var fun in data.external)
text += prefix + '.data\n'; text += ' ' + fun + ': ' + gasToText(data.external[fun]) + '\n';
if (asm['.data']) text += 'Internal:\n';
$.each(asm['.data'], function(i, item) { for (var fun in data.internal)
text += ' ' + prefix + '' + i + ':\n'; text += ' ' + fun + ': ' + gasToText(data.internal[fun]) + '\n';
text += formatAssemblyText(item, prefix + ' ', source); return text;
}); };
var formatAssemblyText = function(asm, prefix, source) {
return text; if (typeof(asm) == typeof('') || asm === null || asm === undefined)
}; return prefix + asm + '\n';
var text = prefix + '.code\n';
$('.asmOutput button').click(function() {$(this).parent().find('pre').toggle(); }); $.each(asm['.code'], function(i, item) {
var v = item.value === undefined ? '' : item.value;
var getConstructorInterface = function(abi) { var src = '';
var funABI = {'name':'','inputs':[],'type':'constructor','outputs':[]}; if (item.begin !== undefined && item.end != undefined)
for (var i = 0; i < abi.length; i++) src = source.slice(item.begin, item.end).replace('\n', '\\n', 'g');
if (abi[i].type == 'constructor') { if (src.length > 30)
funABI.inputs = abi[i].inputs || []; src = src.slice(0, 30) + '...';
break; if (item.name != 'tag')
} text += ' ';
return funABI; text += prefix + item.name + ' ' + v + '\t\t\t' + src + '\n';
}; });
text += prefix + '.data\n';
}); if (asm['.data'])
$.each(asm['.data'], function(i, item) {
</script> text += ' ' + prefix + '' + i + ':\n';
text += formatAssemblyText(item, prefix + ' ', source);
});
return text;
};
$('.asmOutput button').click(function() {$(this).parent().find('pre').toggle(); });
var getConstructorInterface = function(abi) {
var funABI = {'name':'','inputs':[],'type':'constructor','outputs':[]};
for (var i = 0; i < abi.length; i++)
if (abi[i].type == 'constructor') {
funABI.inputs = abi[i].inputs || [];
break;
}
return funABI;
};
});
</script>
</body> </body>
</html> </html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment