Unverified Commit 50b2c875 authored by yann300's avatar yann300 Committed by GitHub

Merge pull request #2582 from ethereum/refactor_iuri

refactor, abstract and remove dependencies on executionContext and udapp - 2
parents c721844c 18008136
...@@ -22,9 +22,8 @@ var toolTip = require('./app/ui/tooltip') ...@@ -22,9 +22,8 @@ var toolTip = require('./app/ui/tooltip')
var CompilerMetadata = require('./app/files/compiler-metadata') var CompilerMetadata = require('./app/files/compiler-metadata')
var CompilerImport = require('./app/compiler/compiler-imports') var CompilerImport = require('./app/compiler/compiler-imports')
var executionContext = remixLib.execution.executionContext const Blockchain = require('./blockchain/blockchain.js')
const PluginUDapp = require('./blockchain/pluginUDapp.js')
const Blockchain = require('./app/tabs/runTab/model/blockchain.js')
const PluginManagerComponent = require('./app/components/plugin-manager-component') const PluginManagerComponent = require('./app/components/plugin-manager-component')
const CompilersArtefacts = require('./app/compiler/compiler-artefacts') const CompilersArtefacts = require('./app/compiler/compiler-artefacts')
...@@ -50,7 +49,6 @@ import { HiddenPanel } from './app/components/hidden-panel' ...@@ -50,7 +49,6 @@ import { HiddenPanel } from './app/components/hidden-panel'
import { VerticalIcons } from './app/components/vertical-icons' import { VerticalIcons } from './app/components/vertical-icons'
import { LandingPage } from './app/ui/landing-page/landing-page' import { LandingPage } from './app/ui/landing-page/landing-page'
import { MainPanel } from './app/components/main-panel' import { MainPanel } from './app/components/main-panel'
import { UniversalDApp } from 'remix-lib'
import migrateFileSystem from './migrateFileSystem' import migrateFileSystem from './migrateFileSystem'
...@@ -225,9 +223,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -225,9 +223,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
const fileManager = new FileManager(editor) const fileManager = new FileManager(editor)
registry.put({api: fileManager, name: 'filemanager'}) registry.put({api: fileManager, name: 'filemanager'})
// ----------------- universal dapp: run transaction, listen on transactions, decode events const blockchain = new Blockchain(registry.get('config').api)
const udapp = new UniversalDApp(registry.get('config').api, executionContext) const pluginUdapp = new PluginUDapp(blockchain)
const blockchain = new Blockchain(executionContext, udapp)
// ----------------- compilation metadata generation servive ---------------------------- // ----------------- compilation metadata generation servive ----------------------------
const compilerMetadataGenerator = new CompilerMetadata(blockchain, fileManager, registry.get('config').api) const compilerMetadataGenerator = new CompilerMetadata(blockchain, fileManager, registry.get('config').api)
...@@ -237,7 +234,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -237,7 +234,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
const {eventsDecoder, txlistener} = makeUdapp(blockchain, compilersArtefacts, (domEl) => mainview.getTerminal().logHtml(domEl)) const {eventsDecoder, txlistener} = makeUdapp(blockchain, compilersArtefacts, (domEl) => mainview.getTerminal().logHtml(domEl))
// ----------------- network service (resolve network id / name) ---------------------------- // ----------------- network service (resolve network id / name) ----------------------------
const networkModule = new NetworkModule(executionContext) const networkModule = new NetworkModule(blockchain)
// ----------------- convert offset to line/column service ---------------------------- // ----------------- convert offset to line/column service ----------------------------
var offsetToLineColumnConverter = new OffsetToLineColumnConverter() var offsetToLineColumnConverter = new OffsetToLineColumnConverter()
registry.put({api: offsetToLineColumnConverter, name: 'offsettolinecolumnconverter'}) registry.put({api: offsetToLineColumnConverter, name: 'offsettolinecolumnconverter'})
...@@ -300,8 +297,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -300,8 +297,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
) )
const run = new RunTab( const run = new RunTab(
blockchain, blockchain,
udapp, pluginUdapp,
executionContext,
registry.get('config').api, registry.get('config').api,
registry.get('filemanager').api, registry.get('filemanager').api,
registry.get('editor').api, registry.get('editor').api,
...@@ -311,7 +307,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -311,7 +307,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
mainview mainview
) )
const analysis = new AnalysisTab(registry) const analysis = new AnalysisTab(registry)
const debug = new DebuggerTab(executionContext) const debug = new DebuggerTab(blockchain)
const test = new TestTab( const test = new TestTab(
registry.get('filemanager').api, registry.get('filemanager').api,
filePanel, filePanel,
......
...@@ -21,10 +21,10 @@ const profile = { ...@@ -21,10 +21,10 @@ const profile = {
class DebuggerTab extends ViewPlugin { class DebuggerTab extends ViewPlugin {
constructor (executionContext) { constructor (blockchain) {
super(profile) super(profile)
this.el = null this.el = null
this.executionContext = executionContext this.blockchain = blockchain
} }
render () { render () {
...@@ -34,7 +34,7 @@ class DebuggerTab extends ViewPlugin { ...@@ -34,7 +34,7 @@ class DebuggerTab extends ViewPlugin {
<div class="${css.debuggerTabView}" id="debugView"> <div class="${css.debuggerTabView}" id="debugView">
<div id="debugger" class="${css.debugger}"></div> <div id="debugger" class="${css.debugger}"></div>
</div>` </div>`
this.debuggerUI = new DebuggerUI(this.el.querySelector('#debugger'), this.executionContext) this.debuggerUI = new DebuggerUI(this.el.querySelector('#debugger'), this.blockchain)
return this.el return this.el
} }
......
...@@ -30,9 +30,9 @@ var css = csjs` ...@@ -30,9 +30,9 @@ var css = csjs`
class DebuggerUI { class DebuggerUI {
constructor (container, executionContext) { constructor (container, blockchain) {
this.registry = globalRegistry this.registry = globalRegistry
this.executionContext = executionContext this.blockchain = blockchain
this.event = new EventManager() this.event = new EventManager()
this.isActive = false this.isActive = false
...@@ -105,13 +105,13 @@ class DebuggerUI { ...@@ -105,13 +105,13 @@ class DebuggerUI {
getDebugWeb3 () { getDebugWeb3 () {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.executionContext.detectNetwork((error, network) => { this.blockchain.detectNetwork((error, network) => {
let web3 let web3
if (error || !network) { if (error || !network) {
web3 = init.web3DebugNode(this.executionContext.web3()) web3 = init.web3DebugNode(this.blockchain.web3())
} else { } else {
const webDebugNode = init.web3DebugNode(network.name) const webDebugNode = init.web3DebugNode(network.name)
web3 = !webDebugNode ? this.executionContext.web3() : webDebugNode web3 = !webDebugNode ? this.blockchain.web3() : webDebugNode
} }
init.extendWeb3(web3) init.extendWeb3(web3)
resolve(web3) resolve(web3)
......
...@@ -14,11 +14,11 @@ export const profile = { ...@@ -14,11 +14,11 @@ export const profile = {
// - methods: ['getNetworkProvider', 'getEndpoint', 'detectNetwork', 'addNetwork', 'removeNetwork'] // - methods: ['getNetworkProvider', 'getEndpoint', 'detectNetwork', 'addNetwork', 'removeNetwork']
export class NetworkModule extends Plugin { export class NetworkModule extends Plugin {
constructor (executionContext) { constructor (blockchain) {
super(profile) super(profile)
this.executionContext = executionContext this.blockchain = blockchain
// TODO: See with remix-lib to make sementic coherent // TODO: See with remix-lib to make sementic coherent
this.executionContext.event.register('contextChanged', (provider) => { this.blockchain.event.register('contextChanged', (provider) => {
this.emit('providerChanged', provider) this.emit('providerChanged', provider)
}) })
/* /*
...@@ -37,13 +37,13 @@ export class NetworkModule extends Plugin { ...@@ -37,13 +37,13 @@ export class NetworkModule extends Plugin {
/** Return the current network provider (web3, vm, injected) */ /** Return the current network provider (web3, vm, injected) */
getNetworkProvider () { getNetworkProvider () {
return this.executionContext.getProvider() return this.blockchain.getProvider()
} }
/** Return the current network */ /** Return the current network */
detectNetwork () { detectNetwork () {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.executionContext.detectNetwork((error, network) => { this.blockchain.detectNetwork((error, network) => {
error ? reject(error) : resolve(network) error ? reject(error) : resolve(network)
}) })
}) })
...@@ -51,20 +51,20 @@ export class NetworkModule extends Plugin { ...@@ -51,20 +51,20 @@ export class NetworkModule extends Plugin {
/** Return the url only if network provider is 'web3' */ /** Return the url only if network provider is 'web3' */
getEndpoint () { getEndpoint () {
const provider = this.executionContext.getProvider() const provider = this.blockchain.getProvider()
if (provider !== 'web3') { if (provider !== 'web3') {
throw new Error('no endpoint: current provider is either injected or vm') throw new Error('no endpoint: current provider is either injected or vm')
} }
return this.executionContext.web3().currentProvider.host return this.blockchain.web3().currentProvider.host
} }
/** Add a custom network to the list of available networks */ /** Add a custom network to the list of available networks */
addNetwork (customNetwork) { addNetwork (customNetwork) {
this.executionContext.addProvider(customNetwork) this.blockchain.addProvider(customNetwork)
} }
/** Remove a network to the list of availble networks */ /** Remove a network to the list of availble networks */
removeNetwork (name) { removeNetwork (name) {
this.executionContext.removeProvider(name) this.blockchain.removeProvider(name)
} }
} }
const remixLib = require('remix-lib')
const txFormat = remixLib.execution.txFormat
const txExecution = remixLib.execution.txExecution
const typeConversion = remixLib.execution.typeConversion
const Txlistener = remixLib.execution.txListener
const EventManager = remixLib.EventManager
const ethJSUtil = require('ethereumjs-util')
const Personal = require('web3-eth-personal')
const Web3 = require('web3')
class Blockchain {
constructor (executionContext, udapp) {
this.event = new EventManager()
this.executionContext = executionContext
this.udapp = udapp
this.networkcallid = 0
this.setupEvents()
}
setupEvents () {
this.executionContext.event.register('contextChanged', (context, silent) => {
this.event.trigger('contextChanged', [context, silent])
})
this.executionContext.event.register('addProvider', (network) => {
this.event.trigger('addProvider', [network])
})
this.executionContext.event.register('removeProvider', (name) => {
this.event.trigger('removeProvider', [name])
})
this.udapp.event.register('initiatingTransaction', (timestamp, tx, payLoad) => {
this.event.trigger('initiatingTransaction', [timestamp, tx, payLoad])
})
this.udapp.event.register('transactionExecuted', (error, from, to, data, call, txResult, timestamp) => {
this.event.trigger('transactionExecuted', [error, from, to, data, call, txResult, timestamp])
})
this.udapp.event.register('transactionBroadcasted', (txhash, networkName) => {
this.event.trigger('transactionBroadcasted', [txhash, networkName])
})
}
async deployContract (selectedContract, args, contractMetadata, compilerContracts, callbacks, confirmationCb) {
const { continueCb, promptCb, statusCb, finalCb } = callbacks
var constructor = selectedContract.getConstructorInterface()
if (!contractMetadata || (contractMetadata && contractMetadata.autoDeployLib)) {
return txFormat.buildData(selectedContract.name, selectedContract.object, compilerContracts, true, constructor, args, (error, data) => {
if (error) return statusCb(`creation of ${selectedContract.name} errored: ` + error)
statusCb(`creation of ${selectedContract.name} pending...`)
this.createContract(selectedContract, data, continueCb, promptCb, confirmationCb, finalCb)
}, statusCb, (data, runTxCallback) => {
// called for libraries deployment
this.runTransaction(data, continueCb, promptCb, confirmationCb, runTxCallback)
})
}
if (Object.keys(selectedContract.bytecodeLinkReferences).length) statusCb(`linking ${JSON.stringify(selectedContract.bytecodeLinkReferences, null, '\t')} using ${JSON.stringify(contractMetadata.linkReferences, null, '\t')}`)
txFormat.encodeConstructorCallAndLinkLibraries(selectedContract.object, args, constructor, contractMetadata.linkReferences, selectedContract.bytecodeLinkReferences, (error, data) => {
if (error) return statusCb(`creation of ${selectedContract.name} errored: ` + error)
statusCb(`creation of ${selectedContract.name} pending...`)
this.createContract(selectedContract, data, continueCb, promptCb, confirmationCb, finalCb)
})
}
runTransaction (data, continueCb, promptCb, confirmationCb, finalCb) {
this.udapp.runTx(data, confirmationCb, continueCb, promptCb, finalCb)
}
createContract (selectedContract, data, continueCb, promptCb, confirmationCb, finalCb) {
if (data) {
data.contractName = selectedContract.name
data.linkReferences = selectedContract.bytecodeLinkReferences
data.contractABI = selectedContract.abi
}
this.udapp.createContract(data, confirmationCb, continueCb, promptCb,
(error, txResult) => {
if (error) {
return finalCb(`creation of ${selectedContract.name} errored: ${error}`)
}
var isVM = this.executionContext.isVM()
if (isVM) {
var vmError = txExecution.checkVMError(txResult)
if (vmError.error) {
return finalCb(vmError.message)
}
}
if (txResult.result.status === false || txResult.result.status === '0x0') {
return finalCb(`creation of ${selectedContract.name} errored: transaction execution failed`)
}
var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress
finalCb(null, selectedContract, address)
}
)
}
determineGasPrice (cb) {
this.getGasPrice((error, gasPrice) => {
var warnMessage = ' Please fix this issue before sending any transaction. '
if (error) {
return cb('Unable to retrieve the current network gas price.' + warnMessage + error)
}
try {
var gasPriceValue = this.fromWei(gasPrice, false, 'gwei')
cb(null, gasPriceValue)
} catch (e) {
cb(warnMessage + e.message, null, false)
}
})
}
getGasPrice (cb) {
return this.executionContext.web3().eth.getGasPrice(cb)
}
fromWei (value, doTypeConversion, unit) {
if (doTypeConversion) {
return Web3.utils.fromWei(typeConversion.toInt(value), unit || 'ether')
}
return Web3.utils.fromWei(value.toString(10), unit || 'ether')
}
toWei (value, unit) {
return Web3.utils.toWei(value, unit || 'gwei')
}
calculateFee (gas, gasPrice, unit) {
return Web3.utils.toBN(gas).mul(Web3.utils.toBN(Web3.utils.toWei(gasPrice.toString(10), unit || 'gwei')))
}
determineGasFees (tx) {
const determineGasFeesCb = (gasPrice, cb) => {
let txFeeText, priceStatus
// TODO: this try catch feels like an anti pattern, can/should be
// removed, but for now keeping the original logic
try {
var fee = this.calculateFee(tx.gas, gasPrice)
txFeeText = ' ' + this.fromWei(fee, false, 'ether') + ' Ether'
priceStatus = true
} catch (e) {
txFeeText = ' Please fix this issue before sending any transaction. ' + e.message
priceStatus = false
}
cb(txFeeText, priceStatus)
}
return determineGasFeesCb
}
getAddressFromTransactionResult (txResult) {
return this.executionContext.isVM() ? txResult.result.createdAddress : txResult.result.contractAddress
}
changeExecutionContext (context, confirmCb, infoCb, cb) {
return this.executionContext.executionContextChange(context, null, confirmCb, infoCb, cb)
}
setProviderFromEndpoint (target, context, cb) {
return this.executionContext.setProviderFromEndpoint(target, context, cb)
}
getProvider () {
return this.executionContext.getProvider()
}
getAccountBalanceForAddress (address, cb) {
return this.udapp.getBalanceInEther(address, cb)
}
updateNetwork (cb) {
this.networkcallid++
((callid) => {
this.executionContext.detectNetwork((err, { id, name } = {}) => {
if (this.networkcallid > callid) return
this.networkcallid++
if (err) {
return cb(err)
}
cb(null, {id, name})
})
})(this.networkcallid)
}
detectNetwork (cb) {
return this.executionContext.detectNetwork(cb)
}
newAccount (passphraseCb, cb) {
return this.udapp.newAccount('', passphraseCb, cb)
}
getAccounts (cb) {
return this.udapp.getAccounts(cb)
}
isWeb3Provider () {
var isVM = this.executionContext.isVM()
var isInjected = this.executionContext.getProvider() === 'injected'
return (!isVM && !isInjected)
}
isInjectedWeb3 () {
return this.executionContext.getProvider() === 'injected'
}
signMessage (message, account, passphrase, cb) {
var isVM = this.executionContext.isVM()
var isInjected = this.executionContext.getProvider() === 'injected'
if (isVM) {
const personalMsg = ethJSUtil.hashPersonalMessage(Buffer.from(message))
var privKey = this.udapp.accounts[account].privateKey
try {
var rsv = ethJSUtil.ecsign(personalMsg, privKey)
var signedData = ethJSUtil.toRpcSig(rsv.v, rsv.r, rsv.s)
cb(null, '0x' + personalMsg.toString('hex'), signedData)
} catch (e) {
cb(e.message)
}
return
}
if (isInjected) {
const hashedMsg = Web3.utils.sha3(message)
try {
this.executionContext.web3().eth.sign(account, hashedMsg, (error, signedData) => {
cb(error.message, hashedMsg, signedData)
})
} catch (e) {
cb(e.message)
}
return
}
const hashedMsg = Web3.utils.sha3(message)
try {
var personal = new Personal(this.executionContext.web3().currentProvider)
personal.sign(hashedMsg, account, passphrase, (error, signedData) => {
cb(error.message, hashedMsg, signedData)
})
} catch (e) {
cb(e.message)
}
}
web3 () {
return this.executionContext.web3()
}
getTxListener (opts) {
opts.event = {
udapp: this.udapp.event
}
const txlistener = new Txlistener(opts, this.executionContext)
return txlistener
}
startListening (txlistener) {
this.udapp.startListening(txlistener)
}
}
module.exports = Blockchain
...@@ -251,6 +251,7 @@ class SettingsUI { ...@@ -251,6 +251,7 @@ class SettingsUI {
newAccount () { newAccount () {
this.blockchain.newAccount( this.blockchain.newAccount(
'',
(cb) => { (cb) => {
modalDialogCustom.promptPassphraseCreation((error, passphrase) => { modalDialogCustom.promptPassphraseCreation((error, passphrase) => {
if (error) { if (error) {
......
...@@ -33,12 +33,10 @@ const profile = { ...@@ -33,12 +33,10 @@ const profile = {
export class RunTab extends LibraryPlugin { export class RunTab extends LibraryPlugin {
constructor (blockchain, udapp, executionContext, config, fileManager, editor, filePanel, compilersArtefacts, networkModule, mainView) { constructor (blockchain, pluginUDapp, config, fileManager, editor, filePanel, compilersArtefacts, networkModule, mainView) {
super(udapp, profile) super(pluginUDapp, profile)
this.event = new EventManager() this.event = new EventManager()
this.config = config this.config = config
this.udapp = udapp
this.executionContext = executionContext
this.blockchain = blockchain this.blockchain = blockchain
this.fileManager = fileManager this.fileManager = fileManager
this.editor = editor this.editor = editor
...@@ -48,37 +46,6 @@ export class RunTab extends LibraryPlugin { ...@@ -48,37 +46,6 @@ export class RunTab extends LibraryPlugin {
this.networkModule = networkModule this.networkModule = networkModule
} }
onActivationInternal () {
this.udappUI = new UniversalDAppUI(this.udapp, this.logCallback, this.executionContext)
this.udapp.resetAPI({
getAddress: (cb) => {
cb(null, $('#txorigin').val())
},
getValue: (cb) => {
try {
const number = document.querySelector('#value').value
const select = document.getElementById('unit')
const index = select.selectedIndex
const selectedUnit = select.querySelectorAll('option')[index].dataset.unit
let unit = 'ether' // default
if (['ether', 'finney', 'gwei', 'wei'].indexOf(selectedUnit) >= 0) {
unit = selectedUnit
}
cb(null, Web3.utils.toWei(number, unit))
} catch (e) {
cb(e)
}
},
getGasLimit: (cb) => {
try {
cb(null, '0x' + new ethJSUtil.BN($('#gasLimit').val(), 10).toString(16))
} catch (e) {
cb(e.message)
}
}
})
}
renderContainer () { renderContainer () {
this.container = yo`<div class="${css.runTabView} py-0 px-2" id="runTabView" ></div>` this.container = yo`<div class="${css.runTabView} py-0 px-2" id="runTabView" ></div>`
...@@ -200,11 +167,34 @@ export class RunTab extends LibraryPlugin { ...@@ -200,11 +167,34 @@ export class RunTab extends LibraryPlugin {
} }
render () { render () {
this.onActivationInternal() this.udappUI = new UniversalDAppUI(this.blockchain, this.logCallback)
this.executionContext.init(this.config) this.blockchain.resetAndInit(this.config, {
this.executionContext.stopListenOnLastBlock() getAddress: (cb) => {
this.executionContext.listenOnLastBlock() cb(null, $('#txorigin').val())
this.udapp.resetEnvironment() },
getValue: (cb) => {
try {
const number = document.querySelector('#value').value
const select = document.getElementById('unit')
const index = select.selectedIndex
const selectedUnit = select.querySelectorAll('option')[index].dataset.unit
let unit = 'ether' // default
if (['ether', 'finney', 'gwei', 'wei'].indexOf(selectedUnit) >= 0) {
unit = selectedUnit
}
cb(null, Web3.utils.toWei(number, unit))
} catch (e) {
cb(e)
}
},
getGasLimit: (cb) => {
try {
cb(null, '0x' + new ethJSUtil.BN($('#gasLimit').val(), 10).toString(16))
} catch (e) {
cb(e.message)
}
}
})
this.renderInstanceContainer() this.renderInstanceContainer()
this.renderSettings() this.renderSettings()
this.renderDropdown(this.udappUI, this.fileManager, this.compilersArtefacts, this.config, this.editor, this.logCallback) this.renderDropdown(this.udappUI, this.fileManager, this.compilersArtefacts, this.config, this.editor, this.logCallback)
......
...@@ -10,16 +10,15 @@ var copyToClipboard = require('./copy-to-clipboard') ...@@ -10,16 +10,15 @@ var copyToClipboard = require('./copy-to-clipboard')
var css = require('../../universal-dapp-styles') var css = require('../../universal-dapp-styles')
var MultiParamManager = require('./multiParamManager') var MultiParamManager = require('./multiParamManager')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var txExecution = remixLib.execution.txExecution
var txFormat = remixLib.execution.txFormat var txFormat = remixLib.execution.txFormat
const txHelper = remixLib.execution.txHelper
var TreeView = require('./TreeView') var TreeView = require('./TreeView')
var txCallBacks = require('./sendTxCallbacks') var txCallBacks = require('./sendTxCallbacks')
function UniversalDAppUI (udapp, logCallback, executionContext) { function UniversalDAppUI (blockchain, logCallback) {
this.udapp = udapp this.blockchain = blockchain
this.logCallback = logCallback this.logCallback = logCallback
this.compilerData = {contractsDetails: {}} this.compilerData = {contractsDetails: {}}
this.executionContext = executionContext
} }
function decodeResponseToTreeView (response, fnabi) { function decodeResponseToTreeView (response, fnabi) {
...@@ -43,7 +42,7 @@ UniversalDAppUI.prototype.renderInstance = function (contract, address, contract ...@@ -43,7 +42,7 @@ UniversalDAppUI.prototype.renderInstance = function (contract, address, contract
if (noInstances) { if (noInstances) {
noInstances.parentNode.removeChild(noInstances) noInstances.parentNode.removeChild(noInstances)
} }
var abi = this.udapp.getABI(contract) const abi = txHelper.sortAbiFunction(contract.abi)
return this.renderInstanceFromABI(abi, address, contractName) return this.renderInstanceFromABI(abi, address, contractName)
} }
...@@ -52,11 +51,11 @@ UniversalDAppUI.prototype.renderInstance = function (contract, address, contract ...@@ -52,11 +51,11 @@ UniversalDAppUI.prototype.renderInstance = function (contract, address, contract
// basically this has to be called for the "atAddress" (line 393) and when a contract creation succeed // basically this has to be called for the "atAddress" (line 393) and when a contract creation succeed
// this returns a DOM element // this returns a DOM element
UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address, contractName) { UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address, contractName) {
var self = this let self = this
address = (address.slice(0, 2) === '0x' ? '' : '0x') + address.toString('hex') address = (address.slice(0, 2) === '0x' ? '' : '0x') + address.toString('hex')
address = ethJSUtil.toChecksumAddress(address) address = ethJSUtil.toChecksumAddress(address)
var instance = yo`<div class="instance ${css.instance} ${css.hidesub}" id="instance${address}"></div>` var instance = yo`<div class="instance ${css.instance} ${css.hidesub}" id="instance${address}"></div>`
var context = self.udapp.context() const context = this.blockchain.context()
var shortAddress = helper.shortenAddress(address) var shortAddress = helper.shortenAddress(address)
var title = yo` var title = yo`
...@@ -160,8 +159,8 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address ...@@ -160,8 +159,8 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address
} }
setLLIError('') setLLIError('')
const fallback = self.udapp.getFallbackInterface(contractABI) const fallback = self.blockchain.getFallbackInterface(contractABI)
const receive = self.udapp.getReceiveInterface(contractABI) const receive = self.blockchain.getReceiveInterface(contractABI)
const args = { const args = {
funABI: fallback || receive, funABI: fallback || receive,
address: address, address: address,
...@@ -221,7 +220,7 @@ UniversalDAppUI.prototype.getCallButton = function (args) { ...@@ -221,7 +220,7 @@ UniversalDAppUI.prototype.getCallButton = function (args) {
lookupOnly, lookupOnly,
args.funABI, args.funABI,
(valArray, inputsValues) => self.runTransaction(lookupOnly, args, valArray, inputsValues, outputOverride), (valArray, inputsValues) => self.runTransaction(lookupOnly, args, valArray, inputsValues, outputOverride),
self.udapp.getInputs(args.funABI) self.blockchain.getInputs(args.funABI)
) )
const contractActionsContainer = yo`<div class="${css.contractActionsContainer}" >${multiParamManager.render()}</div>` const contractActionsContainer = yo`<div class="${css.contractActionsContainer}" >${multiParamManager.render()}</div>`
...@@ -231,55 +230,20 @@ UniversalDAppUI.prototype.getCallButton = function (args) { ...@@ -231,55 +230,20 @@ UniversalDAppUI.prototype.getCallButton = function (args) {
} }
UniversalDAppUI.prototype.runTransaction = function (lookupOnly, args, valArr, inputsValues, outputOverride) { UniversalDAppUI.prototype.runTransaction = function (lookupOnly, args, valArr, inputsValues, outputOverride) {
let self = this
const functionName = args.funABI.type === 'function' ? args.funABI.name : `(${args.funABI.type})` const functionName = args.funABI.type === 'function' ? args.funABI.name : `(${args.funABI.type})`
const logMsg = `${lookupOnly ? 'call' : 'transact'} to ${args.contractName}.${functionName}` const logMsg = `${lookupOnly ? 'call' : 'transact'} to ${args.contractName}.${functionName}`
var value = inputsValues const callbacksInContext = txCallBacks.getCallBacksWithContext(this, this.executionContext)
const outputCb = (decoded) => { const outputCb = (returnValue) => {
if (outputOverride) { if (outputOverride) {
const decoded = decodeResponseToTreeView(returnValue, args.funABI)
outputOverride.innerHTML = '' outputOverride.innerHTML = ''
outputOverride.appendChild(decoded) outputOverride.appendChild(decoded)
} }
} }
// contractsDetails is used to resolve libraries const params = args.funABI.type !== 'fallback' ? inputsValues : ''
const callbacksInContext = txCallBacks.getCallBacksWithContext(self, self.executionContext) this.blockchain.runOrCallContractMethod(args.contractName, args.contractAbi, args.funABI, inputsValues, args.address, params, lookupOnly, logMsg, this.logCallback, outputCb, callbacksInContext)
txFormat.buildData(args.contractName, args.contractABI, {}, false, args.funABI, args.funABI.type !== 'fallback' ? value : '', (error, data) => {
if (!error) {
if (!lookupOnly) {
self.logCallback(`${logMsg} pending ... `)
} else {
self.logCallback(`${logMsg}`)
}
if (args.funABI.type === 'fallback') data.dataHex = value
self.udapp.callFunction(args.address, data, args.funABI, callbacksInContext.confirmationCb.bind(callbacksInContext), callbacksInContext.continueCb.bind(callbacksInContext), callbacksInContext.promptCb.bind(callbacksInContext), (error, txResult) => {
if (!error) {
var isVM = self.executionContext.isVM()
if (isVM) {
var vmError = txExecution.checkVMError(txResult)
if (vmError.error) {
self.logCallback(`${logMsg} errored: ${vmError.message} `)
return
}
}
if (lookupOnly) {
const decoded = decodeResponseToTreeView(self.executionContext.isVM() ? txResult.result.execResult.returnValue : ethJSUtil.toBuffer(txResult.result), args.funABI)
outputCb(decoded)
}
} else {
self.logCallback(`${logMsg} errored: ${error} `)
}
})
} else {
self.logCallback(`${logMsg} errored: ${error} `)
}
}, (msg) => {
self.logCallback(msg)
}, (data, runTxCallback) => {
// called for libraries deployment
self.udapp.runTx(data, callbacksInContext.confirmationCb.bind(callbacksInContext), runTxCallback)
})
} }
module.exports = UniversalDAppUI module.exports = UniversalDAppUI
This diff is collapsed.
const { EventEmitter } = require('events')
class PluginUdapp {
constructor (blockchain) {
this.blockchain = blockchain
this.events = new EventEmitter()
this.setupEvents()
}
setupEvents () {
this.blockchain.event.register('newTransaction', (tx, receipt) => {
this.events.trigger('newTransaction', [tx, receipt])
})
}
createVMAccount (newAccount) {
return this.blockchain.createVMAccount(newAccount)
}
sendTransaction (tx) {
return this.blockchain.sendTransaction(tx)
}
getAccounts (cb) {
return this.blockchain.getAccounts(cb)
}
pendingTransactionsCount () {
return this.blockchain.pendingTransactionsCount()
}
}
module.exports = PluginUdapp
'use strict'
const { bufferToHex, isHexString } = require('ethereumjs-util')
function convertToPrefixedHex (input) {
if (input === undefined || input === null || isHexString(input)) {
return input
} else if (Buffer.isBuffer(input)) {
return bufferToHex(input)
}
return '0x' + input.toString(16)
}
/*
txResult.result can be 3 different things:
- VM call or tx: ethereumjs-vm result object
- Node transaction: object returned from eth.getTransactionReceipt()
- Node call: return value from function call (not an object)
Also, VM results use BN and Buffers, Node results use hex strings/ints,
So we need to normalize the values to prefixed hex strings
*/
function resultToRemixTx (txResult) {
const { result, transactionHash } = txResult
const { status, execResult, gasUsed, createdAddress, contractAddress } = result
let returnValue, errorMessage
if (isHexString(result)) {
returnValue = result
} else if (execResult !== undefined) {
returnValue = execResult.returnValue
errorMessage = execResult.exceptionError
}
return {
transactionHash,
status,
gasUsed: convertToPrefixedHex(gasUsed),
error: errorMessage,
return: convertToPrefixedHex(returnValue),
createdAddress: convertToPrefixedHex(createdAddress || contractAddress)
}
}
module.exports = {
resultToRemixTx
}
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