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. 69
      src/universal-dapp.js
  4. 2
      test-browser/mockcompiler/compiler.js

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

@ -1,6 +1,7 @@
'use strict'
var solc = require('solc/wrapper')
var solcABI = require('solc/abi')
var webworkify = require('webworkify')
var utils = require('./utils')
@ -20,6 +21,8 @@ function Compiler (editor, handleGithubCall) {
var cachedRemoteFiles = {}
var worker = null
var currentVersion
var optimize = false
this.setOptimize = function (_optimize) {
@ -53,6 +56,7 @@ function Compiler (editor, handleGithubCall) {
this.setCompileJSON = setCompileJSON // this is exposed for testing
function onCompilerLoaded (version) {
currentVersion = version
self.event.trigger('compilerLoaded', [version])
}
@ -123,6 +127,8 @@ function Compiler (editor, handleGithubCall) {
// try compiling again with the new set of inputs
internalCompile(source.sources, missingInputs)
} else {
data = updateInterface(data)
self.lastCompilationResult = {
data: data,
source: source
@ -270,6 +276,24 @@ function Compiler (editor, handleGithubCall) {
} while (reloop)
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

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

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

Loading…
Cancel
Save