Commit d03fa09b authored by bunsenstraat's avatar bunsenstraat

Merge branch 'master' of https://github.com/ethereum/remix-project into fixflattener

parents 48c01aee 43d5937f
...@@ -16,6 +16,7 @@ export const DebuggerApiMixin = (Base) => class extends Base { ...@@ -16,6 +16,7 @@ export const DebuggerApiMixin = (Base) => class extends Base {
} }
} }
this._web3 = new Web3(this.web3Provider) this._web3 = new Web3(this.web3Provider)
remixDebug.init.extendWeb3(this._web3)
this.offsetToLineColumnConverter = { this.offsetToLineColumnConverter = {
async offsetToLineColumn (rawLocation, file, sources, asts) { async offsetToLineColumn (rawLocation, file, sources, asts) {
...@@ -118,17 +119,17 @@ export const DebuggerApiMixin = (Base) => class extends Base { ...@@ -118,17 +119,17 @@ export const DebuggerApiMixin = (Base) => class extends Base {
debug (hash) { debug (hash) {
this.debugHash = hash this.debugHash = hash
this.onDebugRequestedListener(hash) if (this.onDebugRequestedListener) this.onDebugRequestedListener(hash)
} }
onActivation () { onActivation () {
this.on('editor', 'breakpointCleared', (fileName, row) => this.onBreakpointClearedListener(fileName, row)) this.on('editor', 'breakpointCleared', (fileName, row) => { if (this.onBreakpointClearedListener) this.onBreakpointClearedListener(fileName, row) })
this.on('editor', 'breakpointAdded', (fileName, row) => this.onBreakpointAddedListener(fileName, row)) this.on('editor', 'breakpointAdded', (fileName, row) => { if (this.onBreakpointAddedListener) this.onBreakpointAddedListener(fileName, row) })
this.on('editor', 'contentChanged', () => this.onEditorContentChangedListener()) this.on('editor', 'contentChanged', () => { if (this.onEditorContentChangedListener) this.onEditorContentChangedListener() })
} }
onDeactivation () { onDeactivation () {
this.onRemoveHighlightsListener() if (this.onRemoveHighlightsListener) this.onRemoveHighlightsListener()
this.off('editor', 'breakpointCleared') this.off('editor', 'breakpointCleared')
this.off('editor', 'breakpointAdded') this.off('editor', 'breakpointAdded')
this.off('editor', 'contentChanged') this.off('editor', 'contentChanged')
......
...@@ -23,6 +23,7 @@ export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) { ...@@ -23,6 +23,7 @@ export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) {
fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise<CompilerAbstract> fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise<CompilerAbstract>
getFile: (path: string) => Promise<string> getFile: (path: string) => Promise<string>
setFile: (path: string, content: string) => Promise<void> setFile: (path: string, content: string) => Promise<void>
getDebugWeb3: () => any // returns an instance of web3.js getDebugWeb3: () => any // returns an instance of web3.js, if applicable (mainet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available)
web3: () => any // returns an instance of web3.js
} }
...@@ -32,6 +32,7 @@ module.exports = { ...@@ -32,6 +32,7 @@ module.exports = {
.click('[data-id="publishToStorage-modal-footer-ok-react"]') .click('[data-id="publishToStorage-modal-footer-ok-react"]')
}, },
/* Disableing the test untill refactoring and the new swarm usage
'Publish on Swarm': '' + function (browser: NightwatchBrowser) { 'Publish on Swarm': '' + function (browser: NightwatchBrowser) {
browser browser
.click('#publishOnSwarm') .click('#publishOnSwarm')
...@@ -47,6 +48,7 @@ module.exports = { ...@@ -47,6 +48,7 @@ module.exports = {
}) })
.click('[data-id="publishToStorage-modal-footer-ok-react"]') .click('[data-id="publishToStorage-modal-footer-ok-react"]')
}, },
*/
'Should publish contract metadata to ipfs on deploy': function (browser: NightwatchBrowser) { 'Should publish contract metadata to ipfs on deploy': function (browser: NightwatchBrowser) {
browser browser
......
...@@ -306,6 +306,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -306,6 +306,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
const contextualListener = new ContextualListener({ editor }) const contextualListener = new ContextualListener({ editor })
engine.register([ engine.register([
blockchain,
contentImport, contentImport,
themeModule, themeModule,
editor, editor,
......
...@@ -49,7 +49,7 @@ const profile = { ...@@ -49,7 +49,7 @@ const profile = {
name: 'editor', name: 'editor',
description: 'service - editor', description: 'service - editor',
version: packageJson.version, version: packageJson.version,
methods: ['highlight', 'discardHighlight', 'discardHighlightAt', 'clearAnnotations', 'addAnnotation'] methods: ['highlight', 'discardHighlight', 'discardHighlightAt', 'clearAnnotations', 'addAnnotation', 'gotoLine']
} }
class Editor extends Plugin { class Editor extends Plugin {
......
...@@ -52,15 +52,7 @@ class CompileTab extends ViewPlugin { ...@@ -52,15 +52,7 @@ class CompileTab extends ViewPlugin {
eventHandlers: {}, eventHandlers: {},
loading: false loading: false
} }
this.compileTabLogic = new CompileTabLogic( this.compileTabLogic = new CompileTabLogic(this, this.contentImport)
this.queryParams,
this.fileManager,
this.editor,
this.config,
this.fileProvider,
this.contentImport,
this.setCompileErrors.bind(this)
)
this.compiler = this.compileTabLogic.compiler this.compiler = this.compileTabLogic.compiler
this.compileTabLogic.init() this.compileTabLogic.init()
this.contractMap = {} this.contractMap = {}
...@@ -203,6 +195,10 @@ class CompileTab extends ViewPlugin { ...@@ -203,6 +195,10 @@ class CompileTab extends ViewPlugin {
return this.compileTabLogic.compiler.state.lastCompilationResult return this.compileTabLogic.compiler.state.lastCompilationResult
} }
addExternalFile (fileName, content) {
this.fileProvider.addExternal(fileName, content)
}
/** /**
* compile using @arg fileName. * compile using @arg fileName.
* The module UI will be updated accordingly to the new compilation result. * The module UI will be updated accordingly to the new compilation result.
...@@ -278,6 +274,50 @@ class CompileTab extends ViewPlugin { ...@@ -278,6 +274,50 @@ class CompileTab extends ViewPlugin {
, this.el) , this.el)
} }
getParameters () {
return this.queryParams.get()
}
setParameters (params) {
this.queryParams.update(params)
}
getConfiguration (name) {
return this.config.get(name)
}
setConfiguration (name, value) {
this.config.set(name, value)
}
fileProviderOf (fileName) {
return this.fileManager.fileProviderOf(fileName)
}
getFileManagerMode () {
return this.fileManager.mode
}
fileExists (fileName) {
return this.call('fileManager', 'exists', fileName)
}
writeFile (fileName, content) {
return this.call('fileManager', 'writeFile', fileName, content)
}
readFile (fileName) {
return this.call('fileManager', 'readFile', fileName)
}
saveCurrentFile () {
return this.fileManager.saveCurrentFile()
}
open (fileName) {
return this.call('fileManager', 'open', fileName)
}
onActivation () { onActivation () {
this.call('manager', 'activatePlugin', 'solidity-logic') this.call('manager', 'activatePlugin', 'solidity-logic')
this.listenToEvents() this.listenToEvents()
......
...@@ -27,7 +27,7 @@ var css = csjs` ...@@ -27,7 +27,7 @@ var css = csjs`
word-break: break-all; word-break: break-all;
} }
.label_key { .label_key {
min-width: 15%; min-width: max-content;
max-width: 80%; max-width: 80%;
word-break: break-word; word-break: break-word;
} }
......
...@@ -4,6 +4,9 @@ const copyToClipboard = require('./copy-to-clipboard') ...@@ -4,6 +4,9 @@ const copyToClipboard = require('./copy-to-clipboard')
const Web3 = require('web3') const Web3 = require('web3')
var css = csjs` var css = csjs`
#confirmsetting {
z-index: 1;
}
.txInfoBox { .txInfoBox {
} }
.wrapword { .wrapword {
...@@ -110,8 +113,8 @@ function confirmDialog (tx, network, amount, gasEstimation, newGasPriceCb, initi ...@@ -110,8 +113,8 @@ function confirmDialog (tx, network, amount, gasEstimation, newGasPriceCb, initi
</div> </div>
</div> </div>
<div class="d-flex py-1 align-items-center custom-control custom-checkbox ${css.checkbox}"> <div class="d-flex py-1 align-items-center custom-control custom-checkbox ${css.checkbox}">
<input class="form-check-input custom-control-input" id='confirmsetting' type="checkbox"> <input class="form-check-input custom-control-input" id="confirmsetting" type="checkbox">
<label class="m-0 form-check-label custom-control-label">Do not show this warning again.</label> <label class="m-0 form-check-label custom-control-label" for="confirmsetting">Do not show this warning again.</label>
</div> </div>
</div> </div>
` `
......
...@@ -538,7 +538,6 @@ export class LandingPage extends ViewPlugin { ...@@ -538,7 +538,6 @@ export class LandingPage extends ViewPlugin {
<div class="btn-group"> <div class="btn-group">
<button class="btn mr-1 btn-secondary" data-id="landingPageImportFromGistButton" onclick="${() => importFromGist()}">Gist</button> <button class="btn mr-1 btn-secondary" data-id="landingPageImportFromGistButton" onclick="${() => importFromGist()}">Gist</button>
<button class="btn mx-1 btn-secondary" onclick="${() => load('Github', 'github URL', ['https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/nf-token-metadata.sol', 'https://github.com/OpenZeppelin/openzeppelin-solidity/blob/67bca857eedf99bf44a4b6a0fc5b5ed553135316/contracts/access/Roles.sol'])}">GitHub</button> <button class="btn mx-1 btn-secondary" onclick="${() => load('Github', 'github URL', ['https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/nf-token-metadata.sol', 'https://github.com/OpenZeppelin/openzeppelin-solidity/blob/67bca857eedf99bf44a4b6a0fc5b5ed553135316/contracts/access/Roles.sol'])}">GitHub</button>
<button class="btn mx-1 btn-secondary" onclick="${() => load('Swarm', 'bzz-raw URL', ['bzz-raw://<swarm-hash>'])}">Swarm</button>
<button class="btn mx-1 btn-secondary" onclick="${() => load('Ipfs', 'ipfs URL', ['ipfs://<ipfs-hash>'])}">Ipfs</button> <button class="btn mx-1 btn-secondary" onclick="${() => load('Ipfs', 'ipfs URL', ['ipfs://<ipfs-hash>'])}">Ipfs</button>
<button class="btn mx-1 btn-secondary" onclick="${() => load('Https', 'http/https raw content', ['https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol'])}">https</button> <button class="btn mx-1 btn-secondary" onclick="${() => load('Https', 'http/https raw content', ['https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol'])}">https</button>
</div><!-- end of btn-group --> </div><!-- end of btn-group -->
......
import Web3 from 'web3' import Web3 from 'web3'
import { Plugin } from '@remixproject/engine'
import { toBuffer, addHexPrefix } from 'ethereumjs-util' import { toBuffer, addHexPrefix } from 'ethereumjs-util'
import { waterfall } from 'async' import { waterfall } from 'async'
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import { format } from 'util'
import { ExecutionContext } from './execution-context' import { ExecutionContext } from './execution-context'
import VMProvider from './providers/vm.js' import VMProvider from './providers/vm.js'
import InjectedProvider from './providers/injected.js' import InjectedProvider from './providers/injected.js'
...@@ -9,10 +11,20 @@ import NodeProvider from './providers/node.js' ...@@ -9,10 +11,20 @@ import NodeProvider from './providers/node.js'
import { execution, EventManager, helpers } from '@remix-project/remix-lib' import { execution, EventManager, helpers } from '@remix-project/remix-lib'
const { txFormat, txExecution, typeConversion, txListener: Txlistener, TxRunner, TxRunnerWeb3, txHelper } = execution const { txFormat, txExecution, typeConversion, txListener: Txlistener, TxRunner, TxRunnerWeb3, txHelper } = execution
const { txResultHelper: resultToRemixTx } = helpers const { txResultHelper: resultToRemixTx } = helpers
const packageJson = require('../../../../package.json')
const profile = {
name: 'blockchain',
displayName: 'Blockchain',
description: 'Blockchain - Logic',
methods: [],
version: packageJson.version
}
class Blockchain { class Blockchain extends Plugin {
// NOTE: the config object will need to be refactored out in remix-lib // NOTE: the config object will need to be refactored out in remix-lib
constructor (config) { constructor (config) {
super(profile)
this.event = new EventManager() this.event = new EventManager()
this.executionContext = new ExecutionContext() this.executionContext = new ExecutionContext()
...@@ -487,6 +499,24 @@ class Blockchain { ...@@ -487,6 +499,24 @@ class Blockchain {
let execResult let execResult
let returnValue = null let returnValue = null
if (isVM) { if (isVM) {
const hhlogs = await this.web3().eth.getHHLogsForTx(txResult.transactionHash)
if (hhlogs && hhlogs.length) {
let finalLogs = 'console.log:\n'
for (const log of hhlogs) {
let formattedLog
// Hardhat implements the same formatting options that can be found in Node.js' console.log,
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
}
finalLogs = finalLogs + formattedLog + '\n'
}
this.call('terminal', 'log', { type: 'info', value: finalLogs })
}
execResult = await this.web3().eth.getExecutionResultFromSimulator(txResult.transactionHash) execResult = await this.web3().eth.getExecutionResultFromSimulator(txResult.transactionHash)
if (execResult) { if (execResult) {
// if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value. // if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value.
......
...@@ -8,7 +8,7 @@ const _paq = window._paq = window._paq || [] ...@@ -8,7 +8,7 @@ const _paq = window._paq = window._paq || []
const requiredModules = [ // services + layout views + system views const requiredModules = [ // services + layout views + system views
'manager', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme', 'manager', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme',
'fileManager', 'contentImport', 'web3Provider', 'scriptRunner', 'fetchAndCompile', 'mainPanel', 'hiddenPanel', 'sidePanel', 'menuicons', 'fileManager', 'contentImport', 'blockchain', 'web3Provider', 'scriptRunner', 'fetchAndCompile', 'mainPanel', 'hiddenPanel', 'sidePanel', 'menuicons',
'filePanel', 'terminal', 'settings', 'pluginManager', 'tabs', 'udapp', 'dGitProvider'] 'filePanel', 'terminal', 'settings', 'pluginManager', 'tabs', 'udapp', 'dGitProvider']
const dependentModules = ['git', 'hardhat'] // module which shouldn't be manually activated (e.g git is activated by remixd) const dependentModules = ['git', 'hardhat'] // module which shouldn't be manually activated (e.g git is activated by remixd)
......
...@@ -33,7 +33,6 @@ export class Ethdebugger { ...@@ -33,7 +33,6 @@ export class Ethdebugger {
storageResolver storageResolver
callTree callTree
breakpointManager breakpointManager
statusMessage
constructor (opts) { constructor (opts) {
this.compilationResult = opts.compilationResult || function (contractAddress) { return null } this.compilationResult = opts.compilationResult || function (contractAddress) { return null }
...@@ -151,22 +150,19 @@ export class Ethdebugger { ...@@ -151,22 +150,19 @@ export class Ethdebugger {
this.event.trigger('traceUnloaded') this.event.trigger('traceUnloaded')
} }
debug (tx) { async debug (tx) {
if (this.traceManager.isLoading) { if (this.traceManager.isLoading) {
return return
} }
tx.to = tx.to || contractCreationToken('0') tx.to = tx.to || contractCreationToken('0')
this.tx = tx this.tx = tx
this.traceManager.resolveTrace(tx).then(async (result) => { await this.traceManager.resolveTrace(tx)
this.setCompilationResult(await this.compilationResult(tx.to)) this.setCompilationResult(await this.compilationResult(tx.to))
this.event.trigger('newTraceLoaded', [this.traceManager.trace]) this.event.trigger('newTraceLoaded', [this.traceManager.trace])
if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) { if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) {
this.breakpointManager.jumpNextBreakpoint(false) this.breakpointManager.jumpNextBreakpoint(false)
} }
this.storageResolver = new StorageResolver({ web3: this.traceManager.web3 }) this.storageResolver = new StorageResolver({ web3: this.traceManager.web3 })
}).catch((error) => {
this.statusMessage = error ? error.message : 'Trace not loaded'
})
} }
} }
...@@ -99,44 +99,31 @@ export class Debugger { ...@@ -99,44 +99,31 @@ export class Debugger {
this.debugger.web3 = web3 this.debugger.web3 = web3
} }
debug (blockNumber, txNumber, tx, loadingCb): Promise<void> { async debug (blockNumber, txNumber, tx, loadingCb) {
const web3 = this.debugger.web3 const web3 = this.debugger.web3
return new Promise((resolve, reject) => { if (this.debugger.traceManager.isLoading) {
if (this.debugger.traceManager.isLoading) { return
return resolve() }
}
if (tx) { if (tx) {
if (!tx.to) { if (!tx.to) {
tx.to = contractCreationToken('0') tx.to = contractCreationToken('0')
}
this.debugTx(tx, loadingCb)
return resolve()
} }
return await this.debugTx(tx, loadingCb)
}
try { if (txNumber.indexOf('0x') !== -1) {
if (txNumber.indexOf('0x') !== -1) { tx = await web3.eth.getTransaction(txNumber)
return web3.eth.getTransaction(txNumber, (_error, tx) => { if (!tx) throw new Error('cannot find transaction ' + txNumber)
if (_error) return reject(_error) } else {
if (!tx) return reject(new Error('cannot find transaction ' + txNumber)) tx = await web3.eth.getTransactionFromBlock(blockNumber, txNumber)
this.debugTx(tx, loadingCb) if (!tx) throw new Error('cannot find transaction ' + blockNumber + ' ' + txNumber)
return resolve() }
}) return await this.debugTx(tx, loadingCb)
}
web3.eth.getTransactionFromBlock(blockNumber, txNumber, (_error, tx) => {
if (_error) return reject(_error)
if (!tx) return reject(new Error('cannot find transaction ' + blockNumber + ' ' + txNumber))
this.debugTx(tx, loadingCb)
return resolve()
})
} catch (e) {
return reject(e.message)
}
})
} }
debugTx (tx, loadingCb) { async debugTx (tx, loadingCb) {
this.step_manager = new DebuggerStepManager(this.debugger, this.debugger.traceManager) this.step_manager = new DebuggerStepManager(this.debugger, this.debugger.traceManager)
this.debugger.codeManager.event.register('changed', this, (code, address, instIndex) => { this.debugger.codeManager.event.register('changed', this, (code, address, instIndex) => {
...@@ -162,7 +149,7 @@ export class Debugger { ...@@ -162,7 +149,7 @@ export class Debugger {
}) })
loadingCb() loadingCb()
this.debugger.debug(tx) await this.debugger.debug(tx)
} }
unload () { unload () {
......
...@@ -21,7 +21,7 @@ export async function solidityLocals (vmtraceIndex, internalTreeCall, stack, mem ...@@ -21,7 +21,7 @@ export async function solidityLocals (vmtraceIndex, internalTreeCall, stack, mem
locals[name] = await variable.type.decodeFromStack(variable.stackDepth, stack, memory, storageResolver, calldata, cursor, variable) locals[name] = await variable.type.decodeFromStack(variable.stackDepth, stack, memory, storageResolver, calldata, cursor, variable)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
locals[name] = '<decoding failed - ' + e.message + '>' locals[name] = { error: '<decoding failed - ' + e.message + '>' }
} }
} }
} }
......
...@@ -25,7 +25,7 @@ export async function decodeState (stateVars, storageResolver) { ...@@ -25,7 +25,7 @@ export async function decodeState (stateVars, storageResolver) {
ret[stateVar.name] = decoded ret[stateVar.name] = decoded
} catch (e) { } catch (e) {
console.log(e) console.log(e)
ret[stateVar.name] = '<decoding failed - ' + e.message + '>' ret[stateVar.name] = { error: '<decoding failed - ' + e.message + '>' }
} }
} }
return ret return ret
...@@ -64,6 +64,6 @@ export async function solidityState (storageResolver, astList, contractName) { ...@@ -64,6 +64,6 @@ export async function solidityState (storageResolver, astList, contractName) {
try { try {
return await decodeState(stateVars, storageResolver) return await decodeState(stateVars, storageResolver)
} catch (e) { } catch (e) {
return '<decoding failed - ' + e.message + '>' return { error: '<decoding failed - ' + e.message + '>' }
} }
} }
...@@ -36,7 +36,7 @@ export class ArrayType extends RefType { ...@@ -36,7 +36,7 @@ export class ArrayType extends RefType {
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { return {
value: '<decoding failed - ' + e.message + '>', error: '<decoding failed - ' + e.message + '>',
type: this.typeName type: this.typeName
} }
} }
...@@ -56,7 +56,7 @@ export class ArrayType extends RefType { ...@@ -56,7 +56,7 @@ export class ArrayType extends RefType {
ret.push(await this.underlyingType.decodeFromStorage(currentLocation, storageResolver)) ret.push(await this.underlyingType.decodeFromStorage(currentLocation, storageResolver))
} catch (e) { } catch (e) {
return { return {
value: '<decoding failed - ' + e.message + '>', error: '<decoding failed - ' + e.message + '>',
type: this.typeName type: this.typeName
} }
} }
...@@ -84,7 +84,7 @@ export class ArrayType extends RefType { ...@@ -84,7 +84,7 @@ export class ArrayType extends RefType {
} }
if (isNaN(length)) { if (isNaN(length)) {
return { return {
value: '<decoding failed - length is NaN>', error: '<decoding failed - length is NaN>',
type: 'Error' type: 'Error'
} }
} }
......
...@@ -16,7 +16,7 @@ export class DynamicByteArray extends RefType { ...@@ -16,7 +16,7 @@ export class DynamicByteArray extends RefType {
value = await extractHexValue(location, storageResolver, this.storageBytes) value = await extractHexValue(location, storageResolver, this.storageBytes)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { value: '<decoding failed - ' + e.message + '>', type: this.typeName } return { error: '<decoding failed - ' + e.message + '>', type: this.typeName }
} }
const length = new BN(value, 16) const length = new BN(value, 16)
if (length.testn(0)) { if (length.testn(0)) {
...@@ -27,7 +27,7 @@ export class DynamicByteArray extends RefType { ...@@ -27,7 +27,7 @@ export class DynamicByteArray extends RefType {
currentSlot = await readFromStorage(dataPos, storageResolver) currentSlot = await readFromStorage(dataPos, storageResolver)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { value: '<decoding failed - ' + e.message + '>', type: this.typeName } return { error: '<decoding failed - ' + e.message + '>', type: this.typeName }
} }
while (length.gt(new BN(ret.length)) && ret.length < 32000) { while (length.gt(new BN(ret.length)) && ret.length < 32000) {
currentSlot = currentSlot.replace('0x', '') currentSlot = currentSlot.replace('0x', '')
...@@ -37,7 +37,7 @@ export class DynamicByteArray extends RefType { ...@@ -37,7 +37,7 @@ export class DynamicByteArray extends RefType {
currentSlot = await readFromStorage(dataPos, storageResolver) currentSlot = await readFromStorage(dataPos, storageResolver)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { value: '<decoding failed - ' + e.message + '>', type: this.typeName } return { error: '<decoding failed - ' + e.message + '>', type: this.typeName }
} }
} }
return { value: '0x' + ret.replace(/(00)+$/, ''), length: '0x' + length.toString(16), type: this.typeName } return { value: '0x' + ret.replace(/(00)+$/, ''), length: '0x' + length.toString(16), type: this.typeName }
......
...@@ -15,17 +15,17 @@ export class StringType extends DynamicByteArray { ...@@ -15,17 +15,17 @@ export class StringType extends DynamicByteArray {
decoded = await super.decodeFromStorage(location, storageResolver) decoded = await super.decodeFromStorage(location, storageResolver)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return '<decoding failed - ' + e.message + '>' return { error: '<decoding failed - ' + e.message + '>' }
} }
return format(decoded) return format(decoded)
} }
async decodeFromStack (stackDepth, stack, memory, calldata, variableDetails?) { async decodeFromStack (stackDepth, stack, memory, storageResolver, calldata, cursor, variableDetails?) {
try { try {
return await super.decodeFromStack(stackDepth, stack, memory, null, calldata, variableDetails) return await super.decodeFromStack(stackDepth, stack, memory, storageResolver, calldata, cursor, variableDetails)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return '<decoding failed - ' + e.message + '>' return { error: '<decoding failed - ' + e.message + '>' }
} }
} }
......
...@@ -22,7 +22,7 @@ export class Struct extends RefType { ...@@ -22,7 +22,7 @@ export class Struct extends RefType {
ret[item.name] = await item.type.decodeFromStorage(globalLocation, storageResolver) ret[item.name] = await item.type.decodeFromStorage(globalLocation, storageResolver)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
ret[item.name] = '<decoding failed - ' + e.message + '>' ret[item.name] = { error: '<decoding failed - ' + e.message + '>' }
} }
} }
return { value: ret, type: this.typeName } return { value: ret, type: this.typeName }
......
...@@ -31,7 +31,7 @@ export class ValueType { ...@@ -31,7 +31,7 @@ export class ValueType {
return { value: this.decodeValue(value), type: this.typeName } return { value: this.decodeValue(value), type: this.typeName }
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { value: '<decoding failed - ' + e.message + '>', type: this.typeName } return { error: '<decoding failed - ' + e.message + '>', type: this.typeName }
} }
} }
...@@ -43,7 +43,7 @@ export class ValueType { ...@@ -43,7 +43,7 @@ export class ValueType {
* @param {String} - memory * @param {String} - memory
* @return {Object} - decoded value * @return {Object} - decoded value
*/ */
async decodeFromStack (stackDepth, stack, memory, calldata, variableDetails?) { async decodeFromStack (stackDepth, stack, memory, storageResolver, calldata, cursor, variableDetails?) {
let value let value
if (stackDepth >= stack.length) { if (stackDepth >= stack.length) {
value = this.decodeValue('') value = this.decodeValue('')
......
...@@ -30,9 +30,8 @@ export class TraceManager { ...@@ -30,9 +30,8 @@ export class TraceManager {
this.init() this.init()
if (!this.web3) throw new Error('web3 not loaded') if (!this.web3) throw new Error('web3 not loaded')
this.isLoading = true this.isLoading = true
const result = await this.getTrace(tx.hash)
try { try {
const result = await this.getTrace(tx.hash)
if (result['structLogs'].length > 0) { if (result['structLogs'].length > 0) {
this.trace = result['structLogs'] this.trace = result['structLogs']
......
This diff is collapsed.
import { hexListFromBNs, formatMemory } from '../util' import { hexListFromBNs, formatMemory } from '../util'
import { normalizeHexAddress } from '../helpers/uiHelper' import { normalizeHexAddress } from '../helpers/uiHelper'
import { ConsoleLogs } from '../helpers/hhconsoleSigs'
import { toChecksumAddress, BN, bufferToHex, Address } from 'ethereumjs-util' import { toChecksumAddress, BN, bufferToHex, Address } from 'ethereumjs-util'
import Web3 from 'web3' import Web3 from 'web3'
import { ethers } from 'ethers'
export class Web3VmProvider { export class Web3VmProvider {
web3 web3
...@@ -9,6 +11,7 @@ export class Web3VmProvider { ...@@ -9,6 +11,7 @@ export class Web3VmProvider {
vmTraces vmTraces
txs txs
txsReceipt txsReceipt
hhLogs
processingHash processingHash
processingAddress processingAddress
processingIndex processingIndex
...@@ -41,6 +44,7 @@ export class Web3VmProvider { ...@@ -41,6 +44,7 @@ export class Web3VmProvider {
this.vmTraces = {} this.vmTraces = {}
this.txs = {} this.txs = {}
this.txsReceipt = {} this.txsReceipt = {}
this.hhLogs = {}
this.processingHash = null this.processingHash = null
this.processingAddress = null this.processingAddress = null
this.processingIndex = null this.processingIndex = null
...@@ -206,6 +210,29 @@ export class Web3VmProvider { ...@@ -206,6 +210,29 @@ export class Web3VmProvider {
error: data.error === false ? undefined : data.error error: data.error === false ? undefined : data.error
} }
this.vmTraces[this.processingHash].structLogs.push(step) this.vmTraces[this.processingHash].structLogs.push(step)
// Track hardhat console.log call
if (step.op === 'STATICCALL' && step.stack[step.stack.length - 2] === '0x000000000000000000000000000000000000000000636f6e736f6c652e6c6f67') {
const stackLength = step.stack.length
const payloadStart = parseInt(step.stack[stackLength - 3], 16)
const memory = step.memory.join('')
let payload = memory.substring(payloadStart * 2, memory.length)
const fnselectorStr = payload.substring(0, 8)
const fnselectorStrInHex = '0x' + fnselectorStr
const fnselector = parseInt(fnselectorStrInHex)
const fnArgs = ConsoleLogs[fnselector]
const iface = new ethers.utils.Interface([`function log${fnArgs} view`])
const functionDesc = iface.getFunction(`log${fnArgs}`)
const sigHash = iface.getSighash(`log${fnArgs}`)
if (fnArgs.includes('uint') && sigHash !== fnselectorStrInHex) {
payload = payload.replace(fnselectorStr, sigHash)
} else {
payload = '0x' + payload
}
const consoleArgs = iface.decodeFunctionData(functionDesc, payload)
this.hhLogs[this.processingHash] = this.hhLogs[this.processingHash] ? this.hhLogs[this.processingHash] : []
this.hhLogs[this.processingHash].push(consoleArgs)
}
if (step.op === 'CREATE' || step.op === 'CALL') { if (step.op === 'CREATE' || step.op === 'CALL') {
if (step.op === 'CREATE') { if (step.op === 'CREATE') {
this.processingAddress = '(Contract Creation - Step ' + this.processingIndex + ')' this.processingAddress = '(Contract Creation - Step ' + this.processingIndex + ')'
......
...@@ -41,6 +41,7 @@ export class Blocks { ...@@ -41,6 +41,7 @@ export class Blocks {
} }
const b = { const b = {
baseFeePerGas: '0x01',
number: this.toHex(block.header.number), number: this.toHex(block.header.number),
hash: this.toHex(block.hash()), hash: this.toHex(block.hash()),
parentHash: this.toHex(block.header.parentHash), parentHash: this.toHex(block.header.parentHash),
...@@ -73,6 +74,7 @@ export class Blocks { ...@@ -73,6 +74,7 @@ export class Blocks {
const block = this.vmContext.blocks[payload.params[0]] const block = this.vmContext.blocks[payload.params[0]]
const b = { const b = {
baseFeePerGas: '0x01',
number: this.toHex(block.header.number), number: this.toHex(block.header.number),
hash: this.toHex(block.hash()), hash: this.toHex(block.hash()),
parentHash: this.toHex(block.header.parentHash), parentHash: this.toHex(block.header.parentHash),
......
...@@ -57,6 +57,7 @@ export class Transactions { ...@@ -57,6 +57,7 @@ export class Transactions {
eth_getTransactionByBlockHashAndIndex: this.eth_getTransactionByBlockHashAndIndex.bind(this), eth_getTransactionByBlockHashAndIndex: this.eth_getTransactionByBlockHashAndIndex.bind(this),
eth_getTransactionByBlockNumberAndIndex: this.eth_getTransactionByBlockNumberAndIndex.bind(this), eth_getTransactionByBlockNumberAndIndex: this.eth_getTransactionByBlockNumberAndIndex.bind(this),
eth_getExecutionResultFromSimulator: this.eth_getExecutionResultFromSimulator.bind(this), eth_getExecutionResultFromSimulator: this.eth_getExecutionResultFromSimulator.bind(this),
eth_getHHLogsForTx: this.eth_getHHLogsForTx.bind(this),
eth_getHashFromTagBySimulator: this.eth_getHashFromTagBySimulator.bind(this) eth_getHashFromTagBySimulator: this.eth_getHashFromTagBySimulator.bind(this)
} }
} }
...@@ -83,6 +84,11 @@ export class Transactions { ...@@ -83,6 +84,11 @@ export class Transactions {
cb(null, this.vmContext.exeResults[txHash]) cb(null, this.vmContext.exeResults[txHash])
} }
eth_getHHLogsForTx (payload, cb) {
const txHash = payload.params[0]
cb(null, this.vmContext.currentVm.web3vm.hhLogs[txHash] ? this.vmContext.currentVm.web3vm.hhLogs[txHash] : [])
}
eth_getTransactionReceipt (payload, cb) { eth_getTransactionReceipt (payload, cb) {
this.vmContext.web3().eth.getTransactionReceipt(payload.params[0], (error, receipt) => { this.vmContext.web3().eth.getTransactionReceipt(payload.params[0], (error, receipt) => {
if (error) { if (error) {
...@@ -187,6 +193,7 @@ export class Transactions { ...@@ -187,6 +193,7 @@ export class Transactions {
blockNumber: '0x' + txBlock.header.number.toString('hex'), blockNumber: '0x' + txBlock.header.number.toString('hex'),
from: receipt.from, from: receipt.from,
gas: Web3.utils.toHex(receipt.gas), gas: Web3.utils.toHex(receipt.gas),
chainId: '0xd05',
// 'gasPrice': '2000000000000', // 0x123 // 'gasPrice': '2000000000000', // 0x123
gasPrice: '0x4a817c800', // 20000000000 gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash, hash: receipt.transactionHash,
...@@ -233,6 +240,7 @@ export class Transactions { ...@@ -233,6 +240,7 @@ export class Transactions {
blockNumber: '0x' + txBlock.header.number.toString('hex'), blockNumber: '0x' + txBlock.header.number.toString('hex'),
from: receipt.from, from: receipt.from,
gas: Web3.utils.toHex(receipt.gas), gas: Web3.utils.toHex(receipt.gas),
chainId: '0xd05',
// 'gasPrice': '2000000000000', // 0x123 // 'gasPrice': '2000000000000', // 0x123
gasPrice: '0x4a817c800', // 20000000000 gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash, hash: receipt.transactionHash,
...@@ -276,6 +284,7 @@ export class Transactions { ...@@ -276,6 +284,7 @@ export class Transactions {
from: receipt.from, from: receipt.from,
gas: Web3.utils.toHex(receipt.gas), gas: Web3.utils.toHex(receipt.gas),
// 'gasPrice': '2000000000000', // 0x123 // 'gasPrice': '2000000000000', // 0x123
chainId: '0xd05',
gasPrice: '0x4a817c800', // 20000000000 gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash, hash: receipt.transactionHash,
input: receipt.input, input: receipt.input,
......
...@@ -103,6 +103,15 @@ export function extend (web3) { ...@@ -103,6 +103,15 @@ export function extend (web3) {
})) }))
} }
if (!(web3.eth && web3.eth.getHHLogsForTx)) {
methods.push(new web3.extend.Method({
name: 'getHHLogsForTx',
call: 'eth_getHHLogsForTx',
inputFormatter: [null],
params: 1
}))
}
if (!(web3.eth && web3.eth.getHashFromTagBySimulator)) { if (!(web3.eth && web3.eth.getHashFromTagBySimulator)) {
methods.push(new web3.extend.Method({ methods.push(new web3.extend.Method({
name: 'getHashFromTagBySimulator', name: 'getHashFromTagBySimulator',
......
...@@ -18,6 +18,7 @@ describe('blocks', () => { ...@@ -18,6 +18,7 @@ describe('blocks', () => {
const block = await web3.eth.getBlock(0) const block = await web3.eth.getBlock(0)
const expectedBlock = { const expectedBlock = {
baseFeePerGas: '0x01',
difficulty: '69762765929000', difficulty: '69762765929000',
extraData: '0x0', extraData: '0x0',
gasLimit: 8000000, gasLimit: 8000000,
......
...@@ -15,17 +15,19 @@ export const DebuggerUI = (props: DebuggerUIProps) => { ...@@ -15,17 +15,19 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
const debuggerModule = props.debuggerAPI const debuggerModule = props.debuggerAPI
const [state, setState] = useState({ const [state, setState] = useState({
isActive: false, isActive: false,
statusMessage: '',
debugger: null, debugger: null,
currentReceipt: { currentReceipt: {
contractAddress: null, contractAddress: null,
to: null to: null
}, },
currentBlock: null,
currentTransaction: null,
blockNumber: null, blockNumber: null,
txNumber: '', txNumber: '',
debugging: false, debugging: false,
opt: { opt: {
debugWithGeneratedSources: false debugWithGeneratedSources: false,
debugWithLocalNode: false
}, },
toastMessage: '', toastMessage: '',
validationError: '', validationError: '',
...@@ -132,12 +134,13 @@ export const DebuggerUI = (props: DebuggerUIProps) => { ...@@ -132,12 +134,13 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
return { return {
...prevState, ...prevState,
isActive: false, isActive: false,
statusMessage: '',
debugger: null, debugger: null,
currentReceipt: { currentReceipt: {
contractAddress: null, contractAddress: null,
to: null to: null
}, },
currentBlock: null,
currentTransaction: null,
blockNumber: null, blockNumber: null,
ready: { ready: {
vmDebugger: false, vmDebugger: false,
...@@ -166,7 +169,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => { ...@@ -166,7 +169,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
return return
} }
const web3 = await debuggerModule.getDebugWeb3() const web3 = state.opt.debugWithLocalNode ? await debuggerModule.web3() : await debuggerModule.getDebugWeb3()
try { try {
const networkId = await web3.eth.net.getId() const networkId = await web3.eth.net.getId()
_paq.push(['trackEvent', 'debugger', 'startDebugging', networkId]) _paq.push(['trackEvent', 'debugger', 'startDebugging', networkId])
...@@ -183,8 +186,12 @@ export const DebuggerUI = (props: DebuggerUIProps) => { ...@@ -183,8 +186,12 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
console.error(e) console.error(e)
} }
let currentReceipt let currentReceipt
let currentBlock
let currentTransaction
try { try {
currentReceipt = await web3.eth.getTransactionReceipt(txNumber) currentReceipt = await web3.eth.getTransactionReceipt(txNumber)
currentBlock = await web3.eth.getBlock(currentReceipt.blockHash)
currentTransaction = await web3.eth.getTransaction(txNumber)
} catch (e) { } catch (e) {
setState(prevState => { setState(prevState => {
return { return {
...@@ -211,33 +218,33 @@ export const DebuggerUI = (props: DebuggerUIProps) => { ...@@ -211,33 +218,33 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
debugWithGeneratedSources: state.opt.debugWithGeneratedSources debugWithGeneratedSources: state.opt.debugWithGeneratedSources
}) })
debuggerInstance.debug(blockNumber, txNumber, tx, () => { try {
listenToEvents(debuggerInstance, currentReceipt) await debuggerInstance.debug(blockNumber, txNumber, tx, () => {
setState(prevState => { listenToEvents(debuggerInstance, currentReceipt)
return {
...prevState,
blockNumber,
txNumber,
debugging: true,
currentReceipt,
debugger: debuggerInstance,
toastMessage: `debugging ${txNumber}`,
validationError: ''
}
})
}).catch((error) => {
if (JSON.stringify(error) !== '{}') {
let message = 'Error: ' + JSON.stringify(error)
message = message.split('\\"').join('\'')
setState(prevState => { setState(prevState => {
return { return {
...prevState, ...prevState,
validationError: message blockNumber,
txNumber,
debugging: true,
currentReceipt,
currentBlock,
currentTransaction,
debugger: debuggerInstance,
toastMessage: `debugging ${txNumber}`,
validationError: ''
} }
}) })
} })
} catch (error) {
unLoad() unLoad()
}) setState(prevState => {
return {
...prevState,
validationError: error.message || error
}
})
}
} }
const debug = (txHash) => { const debug = (txHash) => {
...@@ -277,19 +284,26 @@ export const DebuggerUI = (props: DebuggerUIProps) => { ...@@ -277,19 +284,26 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
<div className="mt-2 mb-2 debuggerConfig custom-control custom-checkbox"> <div className="mt-2 mb-2 debuggerConfig custom-control custom-checkbox">
<input className="custom-control-input" id="debugGeneratedSourcesInput" onChange={({ target: { checked } }) => { <input className="custom-control-input" id="debugGeneratedSourcesInput" onChange={({ target: { checked } }) => {
setState(prevState => { setState(prevState => {
return { ...prevState, opt: { debugWithGeneratedSources: checked } } return { ...prevState, opt: { ...prevState.opt, debugWithGeneratedSources: checked } }
}) })
}} type="checkbox" title="Debug with generated sources" /> }} type="checkbox" title="Debug with generated sources" />
<label data-id="debugGeneratedSourcesLabel" className="form-check-label custom-control-label" htmlFor="debugGeneratedSourcesInput">Use generated sources (from Solidity v0.7.2)</label> <label data-id="debugGeneratedSourcesLabel" className="form-check-label custom-control-label" htmlFor="debugGeneratedSourcesInput">Use generated sources (from Solidity v0.7.2)</label>
</div> </div>
<div className="mt-2 mb-2 debuggerConfig custom-control custom-checkbox">
<input className="custom-control-input" id="debugWithLocalNodeInput" onChange={({ target: { checked } }) => {
setState(prevState => {
return { ...prevState, opt: { ...prevState.opt, debugWithLocalNode: checked } }
})
}} type="checkbox" title="Force the debugger to use the current local node" />
<label data-id="debugLocaNodeLabel" className="form-check-label custom-control-label" htmlFor="debugWithLocalNodeInput">Force using local node</label>
</div>
{ state.validationError && <span className="w-100 py-1 text-danger validationError">{state.validationError}</span> } { state.validationError && <span className="w-100 py-1 text-danger validationError">{state.validationError}</span> }
</div> </div>
<TxBrowser requestDebug={ requestDebug } unloadRequested={ unloadRequested } updateTxNumberFlag={ updateTxNumberFlag } transactionNumber={ state.txNumber } debugging={ state.debugging } /> <TxBrowser requestDebug={ requestDebug } unloadRequested={ unloadRequested } updateTxNumberFlag={ updateTxNumberFlag } transactionNumber={ state.txNumber } debugging={ state.debugging } />
{ state.debugging && <StepManager stepManager={ stepManager } /> } { state.debugging && <StepManager stepManager={ stepManager } /> }
{ state.debugging && <VmDebuggerHead vmDebugger={ vmDebugger } /> } { state.debugging && <VmDebuggerHead vmDebugger={ vmDebugger } /> }
</div> </div>
{ state.debugging && <div className="statusMessage">{ state.statusMessage }</div> } { state.debugging && <VmDebugger vmDebugger={ vmDebugger } currentBlock={ state.currentBlock } currentReceipt={ state.currentReceipt } currentTransaction={ state.currentTransaction } /> }
{ state.debugging && <VmDebugger vmDebugger={ vmDebugger } /> }
</div> </div>
) )
} }
......
...@@ -62,6 +62,7 @@ export interface IDebuggerApi { ...@@ -62,6 +62,7 @@ export interface IDebuggerApi {
fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise<CompilationOutput> fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise<CompilationOutput>
getFile: (path: string) => Promise<string> getFile: (path: string) => Promise<string>
setFile: (path: string, content: string) => Promise<void> setFile: (path: string, content: string) => Promise<void>
getDebugWeb3: () => any // returns an instance of web3.js getDebugWeb3: () => any // returns an instance of web3.js, if applicable (mainet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available)
web3: () => any // returns an instance of web3.js
showMessage (title: string, message: string): void showMessage (title: string, message: string): void
} }
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
import { BN } from 'ethereumjs-util'
export const GlobalVariables = ({ block, receipt, tx }) => {
// see https://docs.soliditylang.org/en/latest/units-and-global-variables.html#block-and-transaction-properties
const globals = {
'block.basefee': (new BN(block.baseFeePerGas.replace('0x', ''), 'hex')).toString(10) + ` Wei (${block.baseFeePerGas})`,
'block.chainid': tx.chainId,
'block.coinbase': block.miner,
'block.difficulty': block.difficulty,
'block.gaslimit': block.gasLimit,
'block.number': block.number,
'block.timestamp': block.timestamp,
'msg.sender': tx.from,
'msg.sig': tx.input.substring(0, 10),
'msg.value': tx.value + ' Wei',
'tx.origin': tx.from
}
return (
<div id='globalvariable' data-id='globalvariable'>
<DropdownPanel hexHighlight={false} bodyStyle={{ fontFamily: 'monospace' }} dropdownName='Global Variables' calldata={globals || {}} />
</div>
)
}
export default GlobalVariables
...@@ -15,6 +15,7 @@ export const VmDebuggerHead = ({ vmDebugger: { registerEvent, triggerEvent } }) ...@@ -15,6 +15,7 @@ export const VmDebuggerHead = ({ vmDebugger: { registerEvent, triggerEvent } })
'remaining gas': '-', 'remaining gas': '-',
'loaded address': '-' 'loaded address': '-'
}) })
const [solidityState, setSolidityState] = useState({ const [solidityState, setSolidityState] = useState({
calldata: null, calldata: null,
message: null message: null
......
...@@ -6,8 +6,9 @@ import StackPanel from './stack-panel' // eslint-disable-line ...@@ -6,8 +6,9 @@ import StackPanel from './stack-panel' // eslint-disable-line
import StoragePanel from './storage-panel' // eslint-disable-line import StoragePanel from './storage-panel' // eslint-disable-line
import ReturnValuesPanel from './dropdown-panel' // eslint-disable-line import ReturnValuesPanel from './dropdown-panel' // eslint-disable-line
import FullStoragesChangesPanel from './full-storages-changes' // eslint-disable-line import FullStoragesChangesPanel from './full-storages-changes' // eslint-disable-line
import GlobalVariables from './global-variables' // eslint-disable-line
export const VmDebugger = ({ vmDebugger: { registerEvent } }) => { export const VmDebugger = ({ vmDebugger: { registerEvent }, currentBlock, currentReceipt, currentTransaction }) => {
const [calldataPanel, setCalldataPanel] = useState(null) const [calldataPanel, setCalldataPanel] = useState(null)
const [memoryPanel, setMemoryPanel] = useState(null) const [memoryPanel, setMemoryPanel] = useState(null)
const [callStackPanel, setCallStackPanel] = useState(null) const [callStackPanel, setCallStackPanel] = useState(null)
...@@ -58,6 +59,7 @@ export const VmDebugger = ({ vmDebugger: { registerEvent } }) => { ...@@ -58,6 +59,7 @@ export const VmDebugger = ({ vmDebugger: { registerEvent } }) => {
<StoragePanel calldata={storagePanel.calldata} header={storagePanel.header} /> <StoragePanel calldata={storagePanel.calldata} header={storagePanel.header} />
<CallstackPanel calldata={callStackPanel} /> <CallstackPanel calldata={callStackPanel} />
<CalldataPanel calldata={calldataPanel} /> <CalldataPanel calldata={calldataPanel} />
<GlobalVariables block={currentBlock} receipt={currentReceipt} tx={currentTransaction} />
<ReturnValuesPanel dropdownName='Return Value' calldata={returnValuesPanel || {}} /> <ReturnValuesPanel dropdownName='Return Value' calldata={returnValuesPanel || {}} />
<FullStoragesChangesPanel calldata={fullStoragesChangesPanel} /> <FullStoragesChangesPanel calldata={fullStoragesChangesPanel} />
</div> </div>
......
...@@ -5,7 +5,7 @@ import { publishToIPFS } from './publishToIPFS' ...@@ -5,7 +5,7 @@ import { publishToIPFS } from './publishToIPFS'
import { publishToSwarm } from './publishOnSwarm' import { publishToSwarm } from './publishOnSwarm'
export const PublishToStorage = (props: RemixUiPublishToStorageProps) => { export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
const { storage, fileProvider, fileManager, contract, resetStorage } = props const { api, storage, contract, resetStorage } = props
const [state, setState] = useState({ const [state, setState] = useState({
modal: { modal: {
title: '', title: '',
...@@ -25,11 +25,11 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => { ...@@ -25,11 +25,11 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
} else { } else {
if (storage === 'swarm') { if (storage === 'swarm') {
try { try {
const result = await publishToSwarm(contract, fileManager) const result = await publishToSwarm(contract, api)
modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded)) modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded))
// triggered each time there's a new verified publish (means hash correspond) // triggered each time there's a new verified publish (means hash correspond)
fileProvider.addExternal('swarm/' + result.item.hash, result.item.content) api.addExternalFile('swarm/' + result.item.hash, result.item.content)
} catch (err) { } catch (err) {
let parseError = err let parseError = err
try { try {
...@@ -39,11 +39,11 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => { ...@@ -39,11 +39,11 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
} }
} else { } else {
try { try {
const result = await publishToIPFS(contract, fileManager) const result = await publishToIPFS(contract, api)
modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded)) modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded))
// triggered each time there's a new verified publish (means hash correspond) // triggered each time there's a new verified publish (means hash correspond)
fileProvider.addExternal('ipfs/' + result.item.hash, result.item.content) api.addExternalFile('ipfs/' + result.item.hash, result.item.content)
} catch (err) { } catch (err) {
modal('IPFS Publish Failed', publishMessageFailed(storage, err)) modal('IPFS Publish Failed', publishMessageFailed(storage, err))
} }
......
...@@ -2,7 +2,7 @@ import swarm from 'swarmgw' ...@@ -2,7 +2,7 @@ import swarm from 'swarmgw'
const swarmgw = swarm() const swarmgw = swarm()
export const publishToSwarm = async (contract, fileManager) => { export const publishToSwarm = async (contract, api) => {
// gather list of files to publish // gather list of files to publish
const sources = [] const sources = []
let metadata let metadata
...@@ -38,16 +38,14 @@ export const publishToSwarm = async (contract, fileManager) => { ...@@ -38,16 +38,14 @@ export const publishToSwarm = async (contract, fileManager) => {
throw new Error('Error while extracting the hash from metadata.json') throw new Error('Error while extracting the hash from metadata.json')
} }
fileManager.fileProviderOf(fileName).get(fileName, (error, content) => { api.readFile(fileName).then((content) => {
if (error) { sources.push({
console.log(error) content: content,
} else { hash: hash,
sources.push({ filename: fileName
content: content, })
hash: hash, }).catch((error) => {
filename: fileName console.log(error)
})
}
}) })
})) }))
// publish the list of sources in order, fail if any failed // publish the list of sources in order, fail if any failed
......
...@@ -6,7 +6,7 @@ const ipfsNodes = [ ...@@ -6,7 +6,7 @@ const ipfsNodes = [
new IpfsClient({ host: '127.0.0.1', port: 5001, protocol: 'http' }) new IpfsClient({ host: '127.0.0.1', port: 5001, protocol: 'http' })
] ]
export const publishToIPFS = async (contract, fileManager) => { export const publishToIPFS = async (contract, api) => {
// gather list of files to publish // gather list of files to publish
const sources = [] const sources = []
let metadata let metadata
...@@ -42,16 +42,14 @@ export const publishToIPFS = async (contract, fileManager) => { ...@@ -42,16 +42,14 @@ export const publishToIPFS = async (contract, fileManager) => {
throw new Error('Error while extracting the hash from metadata.json') throw new Error('Error while extracting the hash from metadata.json')
} }
fileManager.fileProviderOf(fileName).get(fileName, (error, content) => { api.readFile(fileName).then((content) => {
if (error) { sources.push({
console.log(error) content: content,
} else { hash: hash,
sources.push({ filename: fileName
content: content, })
hash: hash, }).catch((error) => {
filename: fileName console.log(error)
})
}
}) })
})) }))
// publish the list of sources in order, fail if any failed // publish the list of sources in order, fail if any failed
......
export interface RemixUiPublishToStorageProps { export interface RemixUiPublishToStorageProps {
api: any,
storage: string, storage: string,
fileProvider: any,
fileManager: any,
contract: any, contract: any,
resetStorage: () => void resetStorage: () => void
} }
...@@ -4,12 +4,9 @@ interface RendererProps { ...@@ -4,12 +4,9 @@ interface RendererProps {
message: any; message: any;
opt?: any, opt?: any,
plugin: any, plugin: any,
editor: any,
config: any,
fileManager: any
} }
export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugin }: RendererProps) => { export const Renderer = ({ message, opt = {}, plugin }: RendererProps) => {
const [messageText, setMessageText] = useState(null) const [messageText, setMessageText] = useState(null)
const [editorOptions, setEditorOptions] = useState({ const [editorOptions, setEditorOptions] = useState({
useSpan: false, useSpan: false,
...@@ -57,7 +54,7 @@ export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugi ...@@ -57,7 +54,7 @@ export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugi
setMessageText(text) setMessageText(text)
setEditorOptions(options) setEditorOptions(options)
setClose(false) setClose(false)
}, [message]) }, [message, opt])
const getPositionDetails = (msg: any) => { const getPositionDetails = (msg: any) => {
const result = { } as Record<string, number | string> const result = { } as Record<string, number | string>
...@@ -77,7 +74,7 @@ export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugi ...@@ -77,7 +74,7 @@ export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugi
} }
const addAnnotation = (file, error) => { const addAnnotation = (file, error) => {
if (file === config.get('currentFile')) { if (file === plugin.getConfiguration('currentFile')) {
plugin.call('editor', 'addAnnotation', error, file) plugin.call('editor', 'addAnnotation', error, file)
} }
} }
...@@ -95,19 +92,19 @@ export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugi ...@@ -95,19 +92,19 @@ export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugi
} }
const _errorClick = (errFile, errLine, errCol) => { const _errorClick = (errFile, errLine, errCol) => {
if (errFile !== config.get('currentFile')) { if (errFile !== plugin.getConfiguration('currentFile')) {
// TODO: refactor with this._components.contextView.jumpTo // TODO: refactor with this._components.contextView.jumpTo
const provider = fileManager.fileProviderOf(errFile) const provider = plugin.fileProviderOf(errFile)
if (provider) { if (provider) {
provider.exists(errFile).then(() => { provider.exists(errFile).then(() => {
fileManager.open(errFile) plugin.open(errFile)
editor.gotoLine(errLine, errCol) plugin.call('editor', 'gotoLine', errLine, errCol)
}).catch(error => { }).catch(error => {
if (error) return console.log(error) if (error) return console.log(error)
}) })
} }
} else { } else {
editor.gotoLine(errLine, errCol) plugin.call('editor', 'gotoLine', errLine, errCol)
} }
} }
......
...@@ -26,8 +26,8 @@ export const resetCompilerMode = () => (dispatch: React.Dispatch<any>) => { ...@@ -26,8 +26,8 @@ export const resetCompilerMode = () => (dispatch: React.Dispatch<any>) => {
}) })
} }
export const listenToEvents = (editor, compileTabLogic) => (dispatch: React.Dispatch<any>) => { export const listenToEvents = (compileTabLogic, api) => (dispatch: React.Dispatch<any>) => {
editor.event.register('sessionSwitched', () => { api.on('editor', 'sessionSwitched', () => {
dispatch(setEditorMode('sessionSwitched')) dispatch(setEditorMode('sessionSwitched'))
}) })
...@@ -39,7 +39,7 @@ export const listenToEvents = (editor, compileTabLogic) => (dispatch: React.Disp ...@@ -39,7 +39,7 @@ export const listenToEvents = (editor, compileTabLogic) => (dispatch: React.Disp
dispatch(setCompilerMode('compilationDuration', speed)) dispatch(setCompilerMode('compilationDuration', speed))
}) })
editor.event.register('contentChanged', () => { api.on('editor', 'contentChanged', () => {
dispatch(setEditorMode('contentChanged')) dispatch(setEditorMode('contentChanged'))
}) })
......
...@@ -18,7 +18,7 @@ declare global { ...@@ -18,7 +18,7 @@ declare global {
const _paq = window._paq = window._paq || [] //eslint-disable-line const _paq = window._paq = window._paq || [] //eslint-disable-line
export const CompilerContainer = (props: CompilerContainerProps) => { export const CompilerContainer = (props: CompilerContainerProps) => {
const { editor, config, queryParams, compileTabLogic, tooltip, modal, compiledFileName, setHardHatCompilation, updateCurrentVersion, isHardHatProject, configurationSettings } = props // eslint-disable-line const { api, compileTabLogic, tooltip, modal, compiledFileName, updateCurrentVersion, configurationSettings } = props // eslint-disable-line
const [state, setState] = useState({ const [state, setState] = useState({
hideWarnings: false, hideWarnings: false,
autoCompile: false, autoCompile: false,
...@@ -56,26 +56,26 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -56,26 +56,26 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
_updateVersionSelector(selectedVersion) _updateVersionSelector(selectedVersion)
} }
}) })
const currentFileName = config.get('currentFile') const currentFileName = api.getConfiguration('currentFile')
currentFile(currentFileName) currentFile(currentFileName)
listenToEvents(editor, compileTabLogic)(dispatch) listenToEvents(compileTabLogic, api)(dispatch)
}, []) }, [])
useEffect(() => { useEffect(() => {
if (compileTabLogic && compileTabLogic.compiler) { if (compileTabLogic && compileTabLogic.compiler) {
setState(prevState => { setState(prevState => {
const params = queryParams.get() const params = api.getParameters()
const optimize = params.optimize === 'false' ? false : params.optimize === 'true' ? true : null const optimize = params.optimize === 'false' ? false : params.optimize === 'true' ? true : null
const runs = params.runs const runs = params.runs
const evmVersion = params.evmVersion const evmVersion = params.evmVersion
return { return {
...prevState, ...prevState,
hideWarnings: config.get('hideWarnings') || false, hideWarnings: api.getConfiguration('hideWarnings') || false,
autoCompile: config.get('autoCompile') || false, autoCompile: api.getConfiguration('autoCompile') || false,
includeNightlies: config.get('includeNightlies') || false, includeNightlies: api.getConfiguration('includeNightlies') || false,
optimise: (optimize !== null) && (optimize !== undefined) ? optimize : config.get('optimise') || false, optimise: (optimize !== null) && (optimize !== undefined) ? optimize : api.getConfiguration('optimise') || false,
runs: (runs !== null) && (runs !== 'null') && (runs !== undefined) && (runs !== 'undefined') ? runs : 200, runs: (runs !== null) && (runs !== 'null') && (runs !== undefined) && (runs !== 'undefined') ? runs : 200,
evmVersion: (evmVersion !== null) && (evmVersion !== 'null') && (evmVersion !== undefined) && (evmVersion !== 'undefined') ? evmVersion : 'default' evmVersion: (evmVersion !== null) && (evmVersion !== 'null') && (evmVersion !== undefined) && (evmVersion !== 'undefined') ? evmVersion : 'default'
} }
...@@ -152,7 +152,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -152,7 +152,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
allVersions = [...allVersions, ...versions] allVersions = [...allVersions, ...versions]
selectedVersion = state.defaultVersion selectedVersion = state.defaultVersion
if (queryParams.get().version) selectedVersion = queryParams.get().version if (api.getParameters().version) selectedVersion = api.getParameters().version
// Check if version is a URL and corresponding filename starts with 'soljson' // Check if version is a URL and corresponding filename starts with 'soljson'
if (selectedVersion.startsWith('https://')) { if (selectedVersion.startsWith('https://')) {
const urlArr = selectedVersion.split('/') const urlArr = selectedVersion.split('/')
...@@ -197,7 +197,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -197,7 +197,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
// Load solc compiler version according to pragma in contract file // Load solc compiler version according to pragma in contract file
const _setCompilerVersionFromPragma = (filename: string) => { const _setCompilerVersionFromPragma = (filename: string) => {
if (!state.allversions) return if (!state.allversions) return
compileTabLogic.fileManager.readFile(filename).then(data => { api.readFile(filename).then(data => {
const pragmaArr = data.match(/(pragma solidity (.+?);)/g) const pragmaArr = data.match(/(pragma solidity (.+?);)/g)
if (pragmaArr && pragmaArr.length === 1) { if (pragmaArr && pragmaArr.length === 1) {
const pragmaStr = pragmaArr[0].replace('pragma solidity', '').trim() const pragmaStr = pragmaArr[0].replace('pragma solidity', '').trim()
...@@ -228,7 +228,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -228,7 +228,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
} }
const isSolFileSelected = (currentFile = '') => { const isSolFileSelected = (currentFile = '') => {
if (!currentFile) currentFile = config.get('currentFile') if (!currentFile) currentFile = api.getConfiguration('currentFile')
if (!currentFile) return false if (!currentFile) return false
const extention = currentFile.substr(currentFile.length - 3, currentFile.length) const extention = currentFile.substr(currentFile.length - 3, currentFile.length)
return extention.toLowerCase() === 'sol' || extention.toLowerCase() === 'yul' return extention.toLowerCase() === 'sol' || extention.toLowerCase() === 'yul'
...@@ -297,7 +297,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -297,7 +297,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
} }
const compile = () => { const compile = () => {
const currentFile = config.get('currentFile') const currentFile = api.getConfiguration('currentFile')
if (!isSolFileSelected()) return if (!isSolFileSelected()) return
...@@ -321,7 +321,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -321,7 +321,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
}) })
} }
updateCurrentVersion(selectedVersion) updateCurrentVersion(selectedVersion)
queryParams.update({ version: selectedVersion }) api.setParameters({ version: selectedVersion })
let url let url
if (customUrl !== '') { if (customUrl !== '') {
...@@ -331,7 +331,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -331,7 +331,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
}) })
updateCurrentVersion(selectedVersion) updateCurrentVersion(selectedVersion)
url = customUrl url = customUrl
queryParams.update({ version: selectedVersion }) api.setParameters({ version: selectedVersion })
} else if (selectedVersion === 'builtin') { } else if (selectedVersion === 'builtin') {
let location: string | Location = window.document.location let location: string | Location = window.document.location
let path = location.pathname let path = location.pathname
...@@ -406,7 +406,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -406,7 +406,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const handleAutoCompile = (e) => { const handleAutoCompile = (e) => {
const checked = e.target.checked const checked = e.target.checked
config.set('autoCompile', checked) api.setConfiguration('autoCompile', checked)
setState(prevState => { setState(prevState => {
return { ...prevState, autoCompile: checked } return { ...prevState, autoCompile: checked }
}) })
...@@ -415,7 +415,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -415,7 +415,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const handleOptimizeChange = (value) => { const handleOptimizeChange = (value) => {
const checked = !!value const checked = !!value
config.set('optimise', checked) api.setConfiguration('optimise', checked)
compileTabLogic.setOptimize(checked) compileTabLogic.setOptimize(checked)
if (compileTabLogic.optimize) { if (compileTabLogic.optimize) {
compileTabLogic.setRuns(parseInt(state.runs)) compileTabLogic.setRuns(parseInt(state.runs))
...@@ -441,7 +441,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -441,7 +441,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const handleHideWarningsChange = (e) => { const handleHideWarningsChange = (e) => {
const checked = e.target.checked const checked = e.target.checked
config.set('hideWarnings', checked) api.setConfiguration('hideWarnings', checked)
state.autoCompile && compile() state.autoCompile && compile()
setState(prevState => { setState(prevState => {
return { ...prevState, hideWarnings: checked } return { ...prevState, hideWarnings: checked }
...@@ -452,7 +452,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -452,7 +452,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const checked = e.target.checked const checked = e.target.checked
if (!checked) handleLoadVersion(state.defaultVersion) if (!checked) handleLoadVersion(state.defaultVersion)
config.set('includeNightlies', checked) api.setConfiguration('includeNightlies', checked)
setState(prevState => { setState(prevState => {
return { ...prevState, includeNightlies: checked } return { ...prevState, includeNightlies: checked }
}) })
...@@ -483,7 +483,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -483,7 +483,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const checked = event.target.checked const checked = event.target.checked
sethhCompilation(checked) sethhCompilation(checked)
setHardHatCompilation(checked) api.setHardHatCompilation(checked)
} }
/* /*
...@@ -574,7 +574,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { ...@@ -574,7 +574,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
</div> </div>
</div> </div>
{ {
isHardHatProject && api.isHardHatProject &&
<div className="mt-3 remixui_compilerConfig custom-control custom-checkbox"> <div className="mt-3 remixui_compilerConfig custom-control custom-checkbox">
<input className="remixui_autocompile custom-control-input" onChange={updatehhCompilation} id="enableHardhat" type="checkbox" title="Enable Hardhat Compilation" checked={hhCompilation} /> <input className="remixui_autocompile custom-control-input" onChange={updatehhCompilation} id="enableHardhat" type="checkbox" title="Enable Hardhat Compilation" checked={hhCompilation} />
<label className="form-check-label custom-control-label" htmlFor="enableHardhat">Enable Hardhat Compilation</label> <label className="form-check-label custom-control-label" htmlFor="enableHardhat">Enable Hardhat Compilation</label>
......
...@@ -7,7 +7,7 @@ import { CopyToClipboard } from '@remix-ui/clipboard' // eslint-disable-line ...@@ -7,7 +7,7 @@ import { CopyToClipboard } from '@remix-ui/clipboard' // eslint-disable-line
import './css/style.css' import './css/style.css'
export const ContractSelection = (props: ContractSelectionProps) => { export const ContractSelection = (props: ContractSelectionProps) => {
const { contractMap, fileProvider, fileManager, contractsDetails, modal } = props const { api, contractMap, contractsDetails, modal } = props
const [contractList, setContractList] = useState([]) const [contractList, setContractList] = useState([])
const [selectedContract, setSelectedContract] = useState('') const [selectedContract, setSelectedContract] = useState('')
const [storage, setStorage] = useState(null) const [storage, setStorage] = useState(null)
...@@ -203,10 +203,6 @@ export const ContractSelection = (props: ContractSelectionProps) => { ...@@ -203,10 +203,6 @@ export const ContractSelection = (props: ContractSelectionProps) => {
</select> </select>
</div> </div>
<article className="mt-2 pb-0"> <article className="mt-2 pb-0">
<button id="publishOnSwarm" className="btn btn-secondary btn-block" title="Publish on Swarm" onClick={() => { handlePublishToStorage('swarm') }}>
<span>Publish on Swarm</span>
<img id="swarmLogo" className="remixui_storageLogo ml-2" src="assets/img/swarm.webp" />
</button>
<button id="publishOnIpfs" className="btn btn-secondary btn-block" title="Publish on Ipfs" onClick={() => { handlePublishToStorage('ipfs') }}> <button id="publishOnIpfs" className="btn btn-secondary btn-block" title="Publish on Ipfs" onClick={() => { handlePublishToStorage('ipfs') }}>
<span>Publish on Ipfs</span> <span>Publish on Ipfs</span>
<img id="ipfsLogo" className="remixui_storageLogo ml-2" src="assets/img/ipfs.webp" /> <img id="ipfsLogo" className="remixui_storageLogo ml-2" src="assets/img/ipfs.webp" />
...@@ -238,7 +234,7 @@ export const ContractSelection = (props: ContractSelectionProps) => { ...@@ -238,7 +234,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
<span className="mt-2 mx-3 w-100 alert alert-warning" role="alert">No Contract Compiled Yet</span> <span className="mt-2 mx-3 w-100 alert alert-warning" role="alert">No Contract Compiled Yet</span>
</article></section> </article></section>
} }
<PublishToStorage storage={storage} fileManager={fileManager} fileProvider={fileProvider} contract={contractsDetails[selectedContract]} resetStorage={resetStorage} /> <PublishToStorage api={api} storage={storage} contract={contractsDetails[selectedContract]} resetStorage={resetStorage} />
</> </>
) )
} }
......
...@@ -18,46 +18,46 @@ export class CompileTab extends Plugin { ...@@ -18,46 +18,46 @@ export class CompileTab extends Plugin {
public compilerImport public compilerImport
public event public event
constructor (public queryParams, public fileManager, public editor, public config, public fileProvider, public contentImport) { constructor (public api, public contentImport) {
super(profile) super(profile)
this.event = new EventEmitter() this.event = new EventEmitter()
this.compiler = new Compiler((url, cb) => this.call('contentImport', 'resolveAndSave', url).then((result) => cb(null, result)).catch((error) => cb(error.message))) this.compiler = new Compiler((url, cb) => this.call('contentImport', 'resolveAndSave', url).then((result) => cb(null, result)).catch((error) => cb(error.message)))
} }
init () { init () {
this.optimize = this.queryParams.get().optimize this.optimize = this.api.getParameters().optimize
this.optimize = this.optimize === 'true' this.optimize = this.optimize === 'true'
this.queryParams.update({ optimize: this.optimize }) this.api.setParameters({ optimize: this.optimize })
this.compiler.set('optimize', this.optimize) this.compiler.set('optimize', this.optimize)
this.runs = this.queryParams.get().runs this.runs = this.api.getParameters().runs
this.runs = this.runs && this.runs !== 'undefined' ? this.runs : 200 this.runs = this.runs && this.runs !== 'undefined' ? this.runs : 200
this.queryParams.update({ runs: this.runs }) this.api.setParameters({ runs: this.runs })
this.compiler.set('runs', this.runs) this.compiler.set('runs', this.runs)
this.evmVersion = this.queryParams.get().evmVersion this.evmVersion = this.api.getParameters().evmVersion
if (this.evmVersion === 'undefined' || this.evmVersion === 'null' || !this.evmVersion) { if (this.evmVersion === 'undefined' || this.evmVersion === 'null' || !this.evmVersion) {
this.evmVersion = null this.evmVersion = null
} }
this.queryParams.update({ evmVersion: this.evmVersion }) this.api.setParameters({ evmVersion: this.evmVersion })
this.compiler.set('evmVersion', this.evmVersion) this.compiler.set('evmVersion', this.evmVersion)
} }
setOptimize (newOptimizeValue) { setOptimize (newOptimizeValue) {
this.optimize = newOptimizeValue this.optimize = newOptimizeValue
this.queryParams.update({ optimize: this.optimize }) this.api.setParameters({ optimize: this.optimize })
this.compiler.set('optimize', this.optimize) this.compiler.set('optimize', this.optimize)
} }
setRuns (runs) { setRuns (runs) {
this.runs = runs this.runs = runs
this.queryParams.update({ runs: this.runs }) this.api.setParameters({ runs: this.runs })
this.compiler.set('runs', this.runs) this.compiler.set('runs', this.runs)
} }
setEvmVersion (newEvmVersion) { setEvmVersion (newEvmVersion) {
this.evmVersion = newEvmVersion this.evmVersion = newEvmVersion
this.queryParams.update({ evmVersion: this.evmVersion }) this.api.setParameters({ evmVersion: this.evmVersion })
this.compiler.set('evmVersion', this.evmVersion) this.compiler.set('evmVersion', this.evmVersion)
} }
...@@ -79,7 +79,7 @@ export class CompileTab extends Plugin { ...@@ -79,7 +79,7 @@ export class CompileTab extends Plugin {
*/ */
compileFile (target) { compileFile (target) {
if (!target) throw new Error('No target provided for compiliation') if (!target) throw new Error('No target provided for compiliation')
const provider = this.fileManager.fileProviderOf(target) const provider = this.api.fileProviderOf(target)
if (!provider) throw new Error(`cannot compile ${target}. Does not belong to any explorer`) if (!provider) throw new Error(`cannot compile ${target}. Does not belong to any explorer`)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
provider.get(target, (error, content) => { provider.get(target, (error, content) => {
...@@ -93,14 +93,14 @@ export class CompileTab extends Plugin { ...@@ -93,14 +93,14 @@ export class CompileTab extends Plugin {
} }
async isHardhatProject () { async isHardhatProject () {
if (this.fileManager.mode === 'localhost') { if (this.api.getFileManagerMode() === 'localhost') {
return await this.fileManager.exists('hardhat.config.js') return await this.api.fileExists('hardhat.config.js')
} else return false } else return false
} }
runCompiler (hhCompilation) { runCompiler (hhCompilation) {
try { try {
if (this.fileManager.mode === 'localhost' && hhCompilation) { if (this.api.getFileManagerMode() === 'localhost' && hhCompilation) {
const { currentVersion, optimize, runs } = this.compiler.state const { currentVersion, optimize, runs } = this.compiler.state
if (currentVersion) { if (currentVersion) {
const fileContent = `module.exports = { const fileContent = `module.exports = {
...@@ -114,7 +114,7 @@ export class CompileTab extends Plugin { ...@@ -114,7 +114,7 @@ export class CompileTab extends Plugin {
} }
` `
const configFilePath = 'remix-compiler.config.js' const configFilePath = 'remix-compiler.config.js'
this.fileManager.setFileContent(configFilePath, fileContent) this.api.writeFile(configFilePath, fileContent)
this.call('hardhat', 'compile', configFilePath).then((result) => { this.call('hardhat', 'compile', configFilePath).then((result) => {
this.call('terminal', 'log', { type: 'info', value: result }) this.call('terminal', 'log', { type: 'info', value: result })
}).catch((error) => { }).catch((error) => {
...@@ -122,9 +122,9 @@ export class CompileTab extends Plugin { ...@@ -122,9 +122,9 @@ export class CompileTab extends Plugin {
}) })
} }
} }
this.fileManager.saveCurrentFile() this.api.saveCurrentFile()
this.event.emit('removeAnnotations') this.event.emit('removeAnnotations')
var currentFile = this.config.get('currentFile') var currentFile = this.api.getConfiguration('currentFile')
return this.compileFile(currentFile) return this.compileFile(currentFile)
} catch (err) { } catch (err) {
console.error(err) console.error(err)
......
...@@ -9,7 +9,7 @@ import { Renderer } from '@remix-ui/renderer' // eslint-disable-line ...@@ -9,7 +9,7 @@ import { Renderer } from '@remix-ui/renderer' // eslint-disable-line
import './css/style.css' import './css/style.css'
export const SolidityCompiler = (props: SolidityCompilerProps) => { export const SolidityCompiler = (props: SolidityCompilerProps) => {
const { plugin, plugin: { editor, config, queryParams, compileTabLogic, currentFile, fileProvider, fileManager, contractsDetails, contractMap, compileErrors, isHardHatProject, setHardHatCompilation, configurationSettings } } = props const { plugin, plugin: { compileTabLogic, contractsDetails, contractMap, compileErrors, configurationSettings } } = props
const [state, setState] = useState({ const [state, setState] = useState({
contractsDetails: {}, contractsDetails: {},
eventHandlers: {}, eventHandlers: {},
...@@ -75,22 +75,23 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => { ...@@ -75,22 +75,23 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
</div> </div>
) )
const currentFile = plugin.getConfiguration('currentFile')
return ( return (
<> <>
<div id="compileTabView"> <div id="compileTabView">
<CompilerContainer editor={editor} config={config} queryParams={queryParams} compileTabLogic={compileTabLogic} tooltip={toast} modal={modal} compiledFileName={currentFile} setHardHatCompilation={setHardHatCompilation.bind(plugin)} updateCurrentVersion={updateCurrentVersion} isHardHatProject={isHardHatProject} configurationSettings={configurationSettings} /> <CompilerContainer api={plugin} compileTabLogic={compileTabLogic} tooltip={toast} modal={modal} compiledFileName={currentFile} updateCurrentVersion={updateCurrentVersion} configurationSettings={configurationSettings} />
<ContractSelection contractMap={contractMap} fileProvider={fileProvider} fileManager={fileManager} contractsDetails={contractsDetails} modal={modal} /> <ContractSelection api={plugin} contractMap={contractMap} contractsDetails={contractsDetails} modal={modal} />
<div className="remixui_errorBlobs p-4" data-id="compiledErrors"> <div className="remixui_errorBlobs p-4" data-id="compiledErrors">
<span data-id={`compilationFinishedWith_${currentVersion}`}></span> <span data-id={`compilationFinishedWith_${currentVersion}`}></span>
{ compileErrors.error && <Renderer message={compileErrors.error.formattedMessage || compileErrors.error} plugin={plugin} opt={{ type: compileErrors.error.severity || 'error', errorType: compileErrors.error.type }} config={config} editor={editor} fileManager={fileManager} /> } { compileErrors.error && <Renderer message={compileErrors.error.formattedMessage || compileErrors.error} plugin={plugin} opt={{ type: compileErrors.error.severity || 'error', errorType: compileErrors.error.type }} /> }
{ compileErrors.error && (compileErrors.error.mode === 'panic') && modal('Error', panicMessage(compileErrors.error.formattedMessage), 'Close', null) } { compileErrors.error && (compileErrors.error.mode === 'panic') && modal('Error', panicMessage(compileErrors.error.formattedMessage), 'Close', null) }
{ compileErrors.errors && compileErrors.errors.length && compileErrors.errors.map((err, index) => { { compileErrors.errors && compileErrors.errors.length && compileErrors.errors.map((err, index) => {
if (config.get('hideWarnings')) { if (plugin.getConfiguration('hideWarnings')) {
if (err.severity !== 'warning') { if (err.severity !== 'warning') {
return <Renderer key={index} message={err.formattedMessage} plugin={plugin} opt={{ type: err.severity, errorType: err.type }} config={config} editor={editor} fileManager={fileManager} /> return <Renderer key={index} message={err.formattedMessage} plugin={plugin} opt={{ type: err.severity, errorType: err.type }} />
} }
} else { } else {
return <Renderer key={index} message={err.formattedMessage} plugin={plugin} opt={{ type: err.severity, errorType: err.type }} config={config} editor={editor} fileManager={fileManager} /> return <Renderer key={index} message={err.formattedMessage} plugin={plugin} opt={{ type: err.severity, errorType: err.type }} />
} }
}) } }) }
</div> </div>
......
...@@ -4,43 +4,32 @@ export interface SolidityCompilerProps { ...@@ -4,43 +4,32 @@ export interface SolidityCompilerProps {
file: string file: string
} | Record<string, any> } | Record<string, any>
compileErrors: any, compileErrors: any,
isHardHatProject: boolean,
queryParams: any,
compileTabLogic: any, compileTabLogic: any,
currentFile: string,
contractsDetails: Record<string, any>, contractsDetails: Record<string, any>,
editor: any,
config: any,
fileProvider: any,
fileManager: any,
contentImport: any, contentImport: any,
call: (...args) => void call: (...args) => void
on: (...args) => void, on: (...args) => void,
setHardHatCompilation: (value: boolean) => void,
setSelectedVersion: (value: string) => void, setSelectedVersion: (value: string) => void,
configurationSettings: ConfigurationSettings configurationSettings: ConfigurationSettings,
getConfiguration: (value: string) => string,
setConfiguration: (name: string, value: string) => void
}, },
} }
export interface CompilerContainerProps { export interface CompilerContainerProps {
editor: any, api: any,
config: any,
queryParams: any,
compileTabLogic: any, compileTabLogic: any,
tooltip: (message: string | JSX.Element) => void, tooltip: (message: string | JSX.Element) => void,
modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void, modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void,
compiledFileName: string, compiledFileName: string,
setHardHatCompilation: (value: boolean) => void,
updateCurrentVersion: any, updateCurrentVersion: any,
isHardHatProject: boolean,
configurationSettings: ConfigurationSettings configurationSettings: ConfigurationSettings
} }
export interface ContractSelectionProps { export interface ContractSelectionProps {
api: any,
contractMap: { contractMap: {
file: string file: string
} | Record<string, any>, } | Record<string, any>,
fileManager: any,
fileProvider: any,
modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void, modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void,
contractsDetails: Record<string, any> contractsDetails: Record<string, any>
} }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
word-break: break-all; word-break: break-all;
} }
.label_key { .label_key {
min-width: 15%; min-width: max-content;
max-width: 80%; max-width: 80%;
word-break: break-word; word-break: break-word;
} }
......
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