Merge pull request #331 from ethereum/interface-abi

Properly handle the interface ABI
pull/1/head
yann300 8 years ago committed by GitHub
commit 9e192eb673
  1. 1
      ci/makeMockCompiler.js
  2. 24
      src/app/compiler.js
  3. 93
      src/universal-dapp.js
  4. 2
      test-browser/mockcompiler/compiler.js

@ -63,6 +63,7 @@ function replaceSolCompiler (results) {
process.exit(1) process.exit(1)
return return
} }
data = data + '\n\nvar mockCompilerVersion = \'' + compiler.version() + '\''
data = data + '\n\nvar mockData = ' + JSON.stringify(results) + ';\n' data = data + '\n\nvar mockData = ' + JSON.stringify(results) + ';\n'
fs.writeFile('./soljson.js', data, 'utf8', function (error) { fs.writeFile('./soljson.js', data, 'utf8', function (error) {
if (error) { if (error) {

@ -1,6 +1,7 @@
'use strict' 'use strict'
var solc = require('solc/wrapper') var solc = require('solc/wrapper')
var solcABI = require('solc/abi')
var webworkify = require('webworkify') var webworkify = require('webworkify')
var utils = require('./utils') var utils = require('./utils')
@ -20,6 +21,8 @@ function Compiler (editor, handleGithubCall) {
var cachedRemoteFiles = {} var cachedRemoteFiles = {}
var worker = null var worker = null
var currentVersion
var optimize = false var optimize = false
this.setOptimize = function (_optimize) { this.setOptimize = function (_optimize) {
@ -53,6 +56,7 @@ function Compiler (editor, handleGithubCall) {
this.setCompileJSON = setCompileJSON // this is exposed for testing this.setCompileJSON = setCompileJSON // this is exposed for testing
function onCompilerLoaded (version) { function onCompilerLoaded (version) {
currentVersion = version
self.event.trigger('compilerLoaded', [version]) self.event.trigger('compilerLoaded', [version])
} }
@ -123,6 +127,8 @@ function Compiler (editor, handleGithubCall) {
// try compiling again with the new set of inputs // try compiling again with the new set of inputs
internalCompile(source.sources, missingInputs) internalCompile(source.sources, missingInputs)
} else { } else {
data = updateInterface(data)
self.lastCompilationResult = { self.lastCompilationResult = {
data: data, data: data,
source: source source: source
@ -270,6 +276,24 @@ function Compiler (editor, handleGithubCall) {
} while (reloop) } while (reloop)
cb(null, { 'sources': files }) cb(null, { 'sources': files })
} }
function truncateVersion (version) {
var tmp = /^(\d+.\d+.\d+)/.exec(version)
if (tmp) {
return tmp[1]
}
return version
}
function updateInterface (data) {
for (var contract in data.contracts) {
var abi = JSON.parse(data.contracts[contract].interface)
abi = solcABI.update(truncateVersion(currentVersion), abi)
data.contracts[contract].interface = JSON.stringify(abi)
}
return data
}
} }
module.exports = Compiler module.exports = Compiler

@ -196,6 +196,10 @@ UniversalDApp.prototype.getCreateInterface = function ($container, contract) {
$createInterface.append($atButton) $createInterface.append($atButton)
var $newButton = self.getInstanceInterface(contract) var $newButton = self.getInstanceInterface(contract)
if (!$newButton) {
return $createInterface
}
$createInterface.append($newButton) $createInterface.append($newButton)
// Only display creation interface for non-abstract contracts. // Only display creation interface for non-abstract contracts.
@ -228,7 +232,12 @@ UniversalDApp.prototype.getInstanceInterface = function (contract, address, $tar
return 1 return 1
} }
}) })
var funABI = self.getConstructorInterface(abi) var funABI = self.getConstructorInterface(abi)
if (!funABI) {
return
}
var $createInterface = $('<div class="createContract"/>') var $createInterface = $('<div class="createContract"/>')
var appendFunctions = function (address, $el) { var appendFunctions = function (address, $el) {
@ -307,13 +316,16 @@ UniversalDApp.prototype.getInstanceInterface = function (contract, address, $tar
$instance.append($title) $instance.append($title)
// Add the fallback function // Add the fallback function
$instance.append(self.getCallButton({ var fallback = self.getFallbackInterface(abi)
abi: { constant: false, inputs: [], name: '(fallback)', outputs: [], type: 'function' }, if (fallback) {
encode: function (args) { $instance.append(self.getCallButton({
return '' abi: fallback,
}, encode: function (args) {
address: address return ''
})) },
address: address
}))
}
$.each(abi, function (i, funABI) { $.each(abi, function (i, funABI) {
if (funABI.type !== 'function') { if (funABI.type !== 'function') {
@ -362,16 +374,22 @@ UniversalDApp.prototype.getInstanceInterface = function (contract, address, $tar
return $createInterface return $createInterface
} }
// either return the supplied constructor or a mockup (we assume everything can be instantiated)
UniversalDApp.prototype.getConstructorInterface = function (abi) { UniversalDApp.prototype.getConstructorInterface = function (abi) {
var funABI = { 'name': '', 'inputs': [], 'type': 'constructor', 'outputs': [] }
for (var i = 0; i < abi.length; i++) { for (var i = 0; i < abi.length; i++) {
if (abi[i].type === 'constructor') { if (abi[i].type === 'constructor') {
funABI.inputs = abi[i].inputs || [] return abi[i]
break }
}
return { 'type': 'constructor', 'payable': false, 'inputs': [] }
}
UniversalDApp.prototype.getFallbackInterface = function (abi) {
for (var i = 0; i < abi.length; i++) {
if (abi[i].type === 'fallback') {
return abi[i]
} }
} }
return funABI
} }
UniversalDApp.prototype.getCallButton = function (args) { UniversalDApp.prototype.getCallButton = function (args) {
@ -382,12 +400,14 @@ UniversalDApp.prototype.getCallButton = function (args) {
var lookupOnly = (args.abi.constant && !isConstructor) var lookupOnly = (args.abi.constant && !isConstructor)
var inputs = '' var inputs = ''
$.each(args.abi.inputs, function (i, inp) { if (args.abi.inputs) {
if (inputs !== '') { $.each(args.abi.inputs, function (i, inp) {
inputs += ', ' if (inputs !== '') {
} inputs += ', '
inputs += inp.type + ' ' + inp.name }
}) inputs += inp.type + ' ' + inp.name
})
}
var inputField = $('<input/>').attr('placeholder', inputs).attr('title', inputs) var inputField = $('<input/>').attr('placeholder', inputs).attr('title', inputs)
var $outputOverride = $('<div class="value" />') var $outputOverride = $('<div class="value" />')
var outputSpan = $('<div class="output"/>') var outputSpan = $('<div class="output"/>')
@ -517,7 +537,7 @@ UniversalDApp.prototype.getCallButton = function (args) {
var decodeResponse = function (response) { var decodeResponse = function (response) {
// Only decode if there supposed to be fields // Only decode if there supposed to be fields
if (args.abi.outputs.length > 0) { if (args.abi.outputs && args.abi.outputs.length > 0) {
try { try {
var i var i
@ -548,7 +568,7 @@ UniversalDApp.prototype.getCallButton = function (args) {
} }
var decoded var decoded
self.runTx({ to: args.address, data: data, useCall: args.abi.constant && !isConstructor }, function (err, txResult) { self.runTx({ to: args.address, data: data, useCall: lookupOnly }, function (err, txResult) {
if (!txResult) { if (!txResult) {
replaceOutput($result, $('<span/>').text('callback contain no result ' + err).addClass('error')) replaceOutput($result, $('<span/>').text('callback contain no result ' + err).addClass('error'))
return return
@ -577,12 +597,12 @@ UniversalDApp.prototype.getCallButton = function (args) {
if (decoded) { if (decoded) {
$result.append(decoded) $result.append(decoded)
} }
if (args.abi.constant) { if (lookupOnly) {
$result.append(getDebugCall(txResult)) $result.append(getDebugCall(txResult))
} else { } else {
$result.append(getDebugTransaction(txResult)) $result.append(getDebugTransaction(txResult))
} }
} else if (args.abi.constant && !isConstructor) { } else if (lookupOnly) {
clearOutput($result) clearOutput($result)
$result.append(getReturnOutput(result)).append(getGasUsedOutput({})) $result.append(getReturnOutput(result)).append(getGasUsedOutput({}))
@ -598,10 +618,19 @@ UniversalDApp.prototype.getCallButton = function (args) {
}) })
} }
var title
if (isConstructor) {
title = 'Create'
} else if (args.abi.name) {
title = args.abi.name
} else {
title = '(fallback)'
}
var button = $('<button />') var button = $('<button />')
.addClass('call') .addClass('call')
.attr('title', args.abi.name) .attr('title', title)
.text(args.bytecode ? 'Create' : args.abi.name) .text(title)
.click(handleCallButtonClick) .click(handleCallButtonClick)
if (lookupOnly && !inputs.length) { if (lookupOnly && !inputs.length) {
@ -610,11 +639,21 @@ UniversalDApp.prototype.getCallButton = function (args) {
var $contractProperty = $('<div class="contractProperty"/>') var $contractProperty = $('<div class="contractProperty"/>')
$contractProperty $contractProperty
.toggleClass('constant', !isConstructor && args.abi.constant)
.toggleClass('hasArgs', args.abi.inputs.length > 0)
.toggleClass('constructor', isConstructor)
.append(button) .append(button)
.append((lookupOnly && !inputs.length) ? $outputOverride : inputField) .append((lookupOnly && !inputs.length) ? $outputOverride : inputField)
if (isConstructor) {
$contractProperty.addClass('constructor')
}
if (lookupOnly) {
$contractProperty.addClass('constant')
}
if (args.abi.inputs && args.abi.inputs.length > 0) {
$contractProperty.addClass('hasArgs')
}
return $contractProperty.append(outputSpan) return $contractProperty.append(outputSpan)
} }

@ -39,5 +39,5 @@ function compile (source, optimization, missingInputs) {
} }
function version () { function version () {
return 'mock compiler' return mockCompilerVersion // eslint-disable-line
} }

Loading…
Cancel
Save