Unverified Commit 23222d30 authored by David Zagi's avatar David Zagi Committed by GitHub

Merge branch 'master' into remixd_terminal

parents 8c6afc23 811ce192
......@@ -22,6 +22,9 @@ function verifyContracts (browser: NightwatchBrowser, compiledContractNames: str
if (opts.version) {
browser
.click('*[data-id="compilation-details"]')
.waitForElementVisible('*[data-id="remixui_treeviewitem_metadata"]')
.pause(2000)
.click('*[data-id="remixui_treeviewitem_metadata"]')
.waitForElementVisible('*[data-id="treeViewDivtreeViewItemcompiler"]')
.pause(2000)
.click('*[data-id="treeViewDivtreeViewItemcompiler"]')
......
......@@ -49,7 +49,7 @@ module.exports = {
'Debug Ballot / delegate': function (browser: NightwatchBrowser) {
browser.pause(500)
.click('*[data-id="txLoggerDebugButton0xf88bc0ac0761f78d8c883b32550c68dadcdb095595c30e1a1b7c583e5e958dcb"]')
.debugTransaction(1)
.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
.click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
.pause(2000)
......
......@@ -45,7 +45,7 @@ module.exports = {
'Debug Ballot / delegate': function (browser: NightwatchBrowser) {
browser.pause(500)
.click('*[data-id="txLoggerDebugButton0xf88bc0ac0761f78d8c883b32550c68dadcdb095595c30e1a1b7c583e5e958dcb"]')
.debugTransaction(1)
.pause(2000)
.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
.click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
......
......@@ -423,7 +423,7 @@ const localVariable_step717_ABIEncoder = { // eslint-disable-line
const jsGetTrace = `(async () => {
try {
const result = await remix.call('debugger', 'getTrace', '0xa38bff6f06e7c4fc91df1db6aa31a69ab5d5882faa953b1e7a88bfa523268ed7')
const result = await remix.call('debugger', 'getTrace', '0x9341be49e911afe99bf1abc67cbcf36739d2e6470a08a69511c205a0737d7332')
console.log('result ', result)
} catch (e) {
console.log(e.message)
......@@ -432,7 +432,7 @@ const jsGetTrace = `(async () => {
const jsDebug = `(async () => {
try {
const result = await remix.call('debugger', 'debug', '0xa38bff6f06e7c4fc91df1db6aa31a69ab5d5882faa953b1e7a88bfa523268ed7')
const result = await remix.call('debugger', 'debug', '0x9341be49e911afe99bf1abc67cbcf36739d2e6470a08a69511c205a0737d7332')
console.log('result ', result)
} catch (e) {
console.log(e.message)
......
......@@ -420,6 +420,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
fn: null
}
)
} else {
startWalkthroughService()
}
// CONTENT VIEWS & DEFAULT PLUGINS
......@@ -515,6 +517,4 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
if (params.embed) framingService.embed()
framingService.start(params)
startWalkthroughService()
}
This diff is collapsed.
......@@ -136,23 +136,25 @@ export class RemixdHandle extends WebsocketPlugin {
}
function remixdDialog () {
const commandText = 'remixd -s path-to-the-shared-folder --remix-ide remix-ide-instance-URL'
const commandText = 'remixd -s <path-to-the-shared-folder> -u <remix-ide-instance-URL>'
return yo`
<div class=${css.dialog}>
<div class=${css.dialogParagraph}>
Access your local file system from Remix IDE using <a target="_blank" href="https://www.npmjs.com/package/@remix-project/remixd">Remixd NPM package</a>.<br/><br/>
Remixd needs to be running in the background to load the files in localhost workspace. For more info, please check the <a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/remixd.html">Remixd tutorial</a>.
</div>
<div class=${css.dialogParagraph}>If you are just looking for the remixd command, here it is:
<div class=${css.dialogParagraph}>
If you are just looking for the remixd command, here it is:
<br><br><b>${commandText}</b>
<span class="">${copyToClipboard(() => commandText)}</span>
</div>
<div class=${css.dialogParagraph}>When connected, a session will be started between <em>${window.location.origin}</em> and your local file system at <i>ws://127.0.0.1:65520</i>
and the shared folder will be in the File Explorers workspace named "localhost".
<br/>Note, if the shared folder is a Hardhat project, an additional Hardhat websocket plugin will be listening at <i>ws://127.0.0.1:65522</i>
<div class=${css.dialogParagraph}>
When connected, a session will be started between <em>${window.location.origin}</em> and your local file system at <i>ws://127.0.0.1:65520</i>.
The shared folder will be in the "File Explorers" workspace named "localhost".
<br/>Read more about other <a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/remixd.html#ports-usage">Remixd ports usage</a>
</div>
<div class=${css.dialogParagraph}>Please make sure your system is secured enough and ports 65520, 65522 are not opened nor forwarded.
This feature is still in Alpha, so we recommend to keep a copy of the shared folder.
<div class=${css.dialogParagraph}>
This feature is still in Alpha. We recommend to keep a backup of the shared folder.
</div>
<div class=${css.dialogParagraph}>
<h6 class="text-danger">
......
......@@ -24,7 +24,6 @@ const profile = {
documentation: 'https://remix-ide.readthedocs.io/en/latest/solidity_editor.html',
version: packageJson.version,
methods: ['getCompilationResult', 'compile', 'compileWithParameters', 'setCompilerConfig', 'compileFile']
}
// EditorApi:
......
import * as packageJson from '../../../../../../package.json'
import { Plugin } from '@remixproject/engine'
const EventEmitter = require('events')
var Compiler = require('@remix-project/remix-solidity').Compiler
const profile = {
name: 'solidity-logic',
displayName: 'Solidity compiler logic',
description: 'Compile solidity contracts - Logic',
methods: ['getCompilerState'],
version: packageJson.version
}
class CompileTab extends Plugin {
constructor (queryParams, fileManager, editor, config, fileProvider, contentImport) {
super(profile)
this.event = new EventEmitter()
this.queryParams = queryParams
this.compilerImport = contentImport
this.compiler = new Compiler((url, cb) => this.compilerImport.resolveAndSave(url).then((result) => cb(null, result)).catch((error) => cb(error.message)))
this.fileManager = fileManager
this.editor = editor
this.config = config
this.fileProvider = fileProvider
}
init () {
this.optimize = this.queryParams.get().optimize
this.optimize = this.optimize === 'true'
this.queryParams.update({ optimize: this.optimize })
this.compiler.set('optimize', this.optimize)
this.runs = this.queryParams.get().runs
this.runs = this.runs || 200
this.queryParams.update({ runs: this.runs })
this.compiler.set('runs', this.runs)
this.evmVersion = this.queryParams.get().evmVersion
if (this.evmVersion === 'undefined' || this.evmVersion === 'null' || !this.evmVersion) {
this.evmVersion = null
}
this.queryParams.update({ evmVersion: this.evmVersion })
this.compiler.set('evmVersion', this.evmVersion)
}
setOptimize (newOptimizeValue) {
this.optimize = newOptimizeValue
this.queryParams.update({ optimize: this.optimize })
this.compiler.set('optimize', this.optimize)
}
setRuns (runs) {
this.runs = runs
this.queryParams.update({ runs: this.runs })
this.compiler.set('runs', this.runs)
}
setEvmVersion (newEvmVersion) {
this.evmVersion = newEvmVersion
this.queryParams.update({ evmVersion: this.evmVersion })
this.compiler.set('evmVersion', this.evmVersion)
}
/**
* Set the compiler to using Solidity or Yul (default to Solidity)
* @params lang {'Solidity' | 'Yul'} ...
*/
setLanguage (lang) {
this.compiler.set('language', lang)
}
getCompilerState () {
return this.compiler.state
}
/**
* Compile a specific file of the file manager
* @param {string} target the path to the file to compile
*/
compileFile (target) {
if (!target) throw new Error('No target provided for compiliation')
const provider = this.fileManager.fileProviderOf(target)
if (!provider) throw new Error(`cannot compile ${target}. Does not belong to any explorer`)
return new Promise((resolve, reject) => {
provider.get(target, (error, content) => {
if (error) return reject(error)
const sources = { [target]: { content } }
this.event.emit('startingCompilation')
// setTimeout fix the animation on chrome... (animation triggered by 'staringCompilation')
setTimeout(() => { this.compiler.compile(sources, target); resolve() }, 100)
})
})
}
async isHardhatProject () {
if (this.fileManager.mode === 'localhost') {
return await this.fileManager.exists('hardhat.config.js')
} else return false
}
runCompiler (hhCompilation) {
try {
if (this.fileManager.mode === 'localhost' && hhCompilation) {
const { currentVersion, optimize, runs } = this.compiler.state
if (currentVersion) {
const fileContent = `module.exports = {
solidity: '${currentVersion.substring(0, currentVersion.indexOf('+commit'))}',
settings: {
optimizer: {
enabled: ${optimize},
runs: ${runs}
}
}
}
`
const configFilePath = 'remix-compiler.config.js'
this.fileManager.setFileContent(configFilePath, fileContent)
this.call('hardhat', 'compile', configFilePath).then((result) => {
this.call('terminal', 'log', { type: 'info', value: result })
}).catch((error) => {
this.call('terminal', 'log', { type: 'error', value: error })
})
}
}
this.fileManager.saveCurrentFile()
this.event.emit('removeAnnotations')
var currentFile = this.config.get('currentFile')
return this.compileFile(currentFile)
} catch (err) {
console.error(err)
}
}
}
module.exports = CompileTab
'use strict'
var solcTranslate = require('solc/translate')
var remixLib = require('@remix-project/remix-lib')
var txHelper = remixLib.execution.txHelper
module.exports = (contractName, contract, compiledSource) => {
return getDetails(contractName, contract, compiledSource)
}
var getDetails = function (contractName, contract, source) {
var detail = {}
detail.name = contractName
detail.metadata = contract.metadata
if (contract.evm.bytecode.object) {
detail.bytecode = contract.evm.bytecode.object
}
detail.abi = contract.abi
if (contract.evm.bytecode.object) {
detail.bytecode = contract.evm.bytecode
detail.web3Deploy = gethDeploy(contractName.toLowerCase(), contract.abi, contract.evm.bytecode.object)
detail.metadataHash = retrieveMetadataHash(contract.evm.bytecode.object)
if (detail.metadataHash) {
detail.swarmLocation = 'bzzr://' + detail.metadataHash
}
}
detail.functionHashes = {}
for (var fun in contract.evm.methodIdentifiers) {
detail.functionHashes[contract.evm.methodIdentifiers[fun]] = fun
}
detail.gasEstimates = formatGasEstimates(contract.evm.gasEstimates)
detail.devdoc = contract.devdoc
detail.userdoc = contract.userdoc
if (contract.evm.deployedBytecode && contract.evm.deployedBytecode.object.length > 0) {
detail['Runtime Bytecode'] = contract.evm.deployedBytecode
}
if (source && contract.assembly !== null) {
detail.Assembly = solcTranslate.prettyPrintLegacyAssemblyJSON(contract.evm.legacyAssembly, source.content)
}
return detail
}
var retrieveMetadataHash = function (bytecode) {
var match = /a165627a7a72305820([0-9a-f]{64})0029$/.exec(bytecode)
if (!match) {
match = /a265627a7a72305820([0-9a-f]{64})6c6578706572696d656e74616cf50037$/.exec(bytecode)
}
if (match) {
return match[1]
}
}
var gethDeploy = function (contractName, jsonInterface, bytecode) {
var code = ''
var funABI = txHelper.getConstructorInterface(jsonInterface)
funABI.inputs.forEach(function (inp) {
code += 'var ' + inp.name + ' = /* var of type ' + inp.type + ' here */ ;\n'
})
contractName = contractName.replace(/[:./]/g, '_')
code += 'var ' + contractName + 'Contract = new web3.eth.Contract(' + JSON.stringify(jsonInterface).replace('\n', '') + ');' +
'\nvar ' + contractName + ' = ' + contractName + 'Contract.deploy({' +
"\n data: '0x" + bytecode + "', " +
'\n arguments: ['
funABI.inputs.forEach(function (inp) {
code += '\n ' + inp.name + ','
})
code += '\n ]' +
'\n}).send({' +
'\n from: web3.eth.accounts[0], ' +
"\n gas: '4700000'" +
'\n }, function (e, contract){' +
'\n console.log(e, contract);' +
"\n if (typeof contract.address !== 'undefined') {" +
"\n console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);" +
'\n }' +
'\n })'
return code
}
var formatGasEstimates = function (data) {
if (!data) return {}
if (data.creation === undefined && data.external === undefined && data.internal === undefined) return {}
var gasToText = function (g) {
return g === null ? 'unknown' : g
}
var ret = {}
var fun
if ('creation' in data) {
ret.Creation = data.creation
}
if ('external' in data) {
ret.External = {}
for (fun in data.external) {
ret.External[fun] = gasToText(data.external[fun])
}
}
if ('internal' in data) {
ret.Internal = {}
for (fun in data.internal) {
ret.Internal[fun] = gasToText(data.internal[fun])
}
}
return ret
}
......@@ -65,7 +65,7 @@ export default class HardhatProvider extends Plugin {
if (error) {
this.blocked = true
modalDialogCustom.alert('Hardhat Provider', `Error while connecting to the hardhat provider: ${error.message}`)
await this.call('udapp', 'setEnvironmentMode', { context: 'vm', fork: 'berlin' })
await this.call('udapp', 'setEnvironmentMode', { context: 'vm', fork: 'london' })
this.provider = null
setTimeout(_ => { this.blocked = false }, 1000) // we wait 1 second for letting remix to switch to vm
return reject(error)
......
......@@ -361,7 +361,7 @@ class ContractDropdownUI {
return continueTxExecution(null)
}
const amount = this.blockchain.fromWei(tx.value, true, 'ether')
const content = confirmDialog(tx, amount, gasEstimation, null, this.blockchain.determineGasFees(tx), this.blockchain.determineGasPrice.bind(this.blockchain))
const content = confirmDialog(tx, network, amount, gasEstimation, this.blockchain.determineGasFees(tx), this.blockchain.determineGasPrice.bind(this.blockchain))
modalDialog('Confirm transaction', content,
{
......@@ -370,10 +370,9 @@ class ContractDropdownUI {
this.blockchain.config.setUnpersistedProperty('doNotShowTransactionConfirmationAgain', content.querySelector('input#confirmsetting').checked)
// TODO: check if this is check is still valid given the refactor
if (!content.gasPriceStatus) {
cancelCb('Given gas price is not correct')
cancelCb('Given transaction fee is not correct')
} else {
var gasPrice = this.blockchain.toWei(content.querySelector('#gasprice').value, 'gwei')
continueTxExecution(gasPrice)
continueTxExecution(content.txFee)
}
}
}, {
......
......@@ -104,7 +104,7 @@ class RecorderUI extends Plugin {
return continueTxExecution(null)
}
const amount = this.blockchain.fromWei(tx.value, true, 'ether')
const content = confirmDialog(tx, amount, gasEstimation, null, this.blockchain.determineGasFees(tx), this.blockchain.determineGasPrice.bind(this.blockchain))
const content = confirmDialog(tx, network, amount, gasEstimation, this.blockchain.determineGasFees(tx), this.blockchain.determineGasPrice.bind(this.blockchain))
modalDialog('Confirm transaction', content,
{
......@@ -113,10 +113,9 @@ class RecorderUI extends Plugin {
this.config.setUnpersistedProperty('doNotShowTransactionConfirmationAgain', content.querySelector('input#confirmsetting').checked)
// TODO: check if this is check is still valid given the refactor
if (!content.gasPriceStatus) {
cancelCb('Given gas price is not correct')
cancelCb('Given transaction fee is not correct')
} else {
var gasPrice = this.blockchain.toWei(content.querySelector('#gasprice').value, 'gwei')
continueTxExecution(gasPrice)
continueTxExecution(content.txFee)
}
}
}, {
......
......@@ -98,14 +98,14 @@ class SettingsUI {
</label>
<div class="${css.environment}">
<select id="selectExEnvOptions" data-id="settingsSelectEnvOptions" class="form-control ${css.select} custom-select">
<option id="vm-mode-berlin" data-id="settingsVMBerlinMode"
title="Execution environment does not connect to any node, everything is local and in memory only."
value="vm-berlin" name="executionContext" fork="berlin" > JavaScript VM (Berlin)
</option>
<option id="vm-mode-london" data-id="settingsVMLondonMode"
title="Execution environment does not connect to any node, everything is local and in memory only."
value="vm-london" name="executionContext" fork="london"> JavaScript VM (London)
</option>
<option id="vm-mode-berlin" data-id="settingsVMBerlinMode"
title="Execution environment does not connect to any node, everything is local and in memory only."
value="vm-berlin" name="executionContext" fork="berlin" > JavaScript VM (Berlin)
</option>
<option id="injected-mode" data-id="settingsInjectedMode"
title="Execution environment has been provided by Metamask or similar provider."
value="injected" name="executionContext"> Injected Web3
......
......@@ -14,20 +14,47 @@ var css = csjs`
}
`
// TODO: self is not actually used and can be removed
function confirmDialog (tx, amount, gasEstimation, self, newGasPriceCb, initialParamsCb) {
var onGasPriceChange = function () {
function confirmDialog (tx, network, amount, gasEstimation, newGasPriceCb, initialParamsCb) {
const onGasPriceChange = function () {
var gasPrice = el.querySelector('#gasprice').value
newGasPriceCb(gasPrice, (txFeeText, priceStatus) => {
el.querySelector('#txfee').innerHTML = txFeeText
el.gasPriceStatus = priceStatus
el.txFee = { gasPrice }
})
}
var el = yo`
const onMaxFeeChange = function () {
var maxFee = el.querySelector('#maxfee').value
var confirmBtn = document.querySelector('#modal-footer-ok')
var maxPriorityFee = el.querySelector('#maxpriorityfee').value
if (parseInt(network.lastBlock.baseFeePerGas, 16) > parseInt(maxFee)) {
el.querySelector('#txfee').innerHTML = 'Transaction is invalid. Max fee should not be less than Base fee'
el.gasPriceStatus = false
confirmBtn.hidden = true
return
} else {
el.gasPriceStatus = true
confirmBtn.hidden = false
}
newGasPriceCb(maxFee, (txFeeText, priceStatus) => {
el.querySelector('#txfee').innerHTML = txFeeText
if (priceStatus) {
confirmBtn.hidden = false
} else {
confirmBtn.hidden = true
}
el.gasPriceStatus = priceStatus
el.txFee = { maxFee, maxPriorityFee, baseFeePerGas: network.lastBlock.baseFeePerGas }
})
}
const el = yo`
<div>
<div>You are about to create a transaction on the Main Network. Confirm the details to send the info to your provider.
<br>The provider for many users is MetaMask. The provider will ask you to sign the transaction before it is sent to the Main Network.</div>
<div class="text-dark">You are about to create a transaction on ${network.name} Network. Confirm the details to send the info to your provider.
<br>The provider for many users is MetaMask. The provider will ask you to sign the transaction before it is sent to ${network.name} Network.
</div>
<div class="mt-3 ${css.txInfoBox}">
<div>
<span class="text-dark mr-2">From:</span>
......@@ -37,7 +64,11 @@ function confirmDialog (tx, amount, gasEstimation, self, newGasPriceCb, initialP
<span class="text-dark mr-2">To:</span>
<span>${tx.to ? tx.to : '(Contract Creation)'}</span>
</div>
<div>
<div class="d-flex align-items-center">
<span class="text-dark mr-2">Data:</span>
<pre class="${css.wrapword} mb-0">${tx.data && tx.data.length > 50 ? tx.data.substring(0, 49) + '...' : tx.data} ${copyToClipboard(() => { return tx.data })}</pre>
</div>
<div class="mb-3">
<span class="text-dark mr-2">Amount:</span>
<span>${amount} Ether</span>
</div>
......@@ -49,18 +80,32 @@ function confirmDialog (tx, amount, gasEstimation, self, newGasPriceCb, initialP
<span class="text-dark mr-2">Gas limit:</span>
<span>${tx.gas}</span>
</div>
<div>
${
network.lastBlock.baseFeePerGas ? yo`
<div class="align-items-center my-1" title="Represents the part of the tx fee that goes to the miner.">
<div class='d-flex'>
<span class="text-dark mr-2 text-nowrap">Max Priority fee:</span>
<input class="form-control mr-1 text-right" style='height: 1.2rem; width: 6rem;' value="0" id='maxpriorityfee' />
<span title="visit https://ethgasstation.info for current gas price info.">Gwei</span>
</div>
</div>
<div class="align-items-center my-1" title="Represents the maximum amount of fee that you will pay for this transaction. The minimun needs to be set to base fee.">
<div class='d-flex'>
<span class="text-dark mr-2 text-nowrap">Max fee (Not less than base fee - ${parseInt(network.lastBlock.baseFeePerGas, 16)} Gwei):</span>
<input class="form-control mr-1 text-right" style='height: 1.2rem; width: 6rem;' id='maxfee' oninput=${onMaxFeeChange} />
<span>Gwei</span>
<span class="text-dark ml-2"></span>
</div>
</div>`
: yo`<div class="d-flex align-items-center my-1">
<span class="text-dark mr-2 text-nowrap">Gas price:</span>
<input class="form-control mr-1 text-right" style='width: 40px; height: 28px;' id='gasprice' oninput=${onGasPriceChange} />
<span>Gwei (visit <a target='_blank' href='https://ethgasstation.info'>ethgasstation.info</a> for current gas price info.)</span>
</div>`
}
<div class="mb-3">
<span class="text-dark mr-2">Max transaction fee:</span>
<span id='txfee'></span>
</div>
<div class="d-flex align-items-center my-1">
<span class="text-dark mr-2">Gas price:</span>
<input class="form-control mr-1" style='width: 40px; height: 28px;'id='gasprice' oninput=${onGasPriceChange} />
<span>Gwei (visit <a target='_blank' href='https://ethgasstation.info'>ethgasstation.info</a> for current gas price info.)</span>
</div>
<div class="d-flex align-items-center">
<span class="text-dark mr-2 mb-3">Data:</span>
<pre class=${css.wrapword}>${tx.data && tx.data.length > 50 ? tx.data.substring(0, 49) + '...' : tx.data} ${copyToClipboard(() => { return tx.data })}</pre>
<span class="text-warning" id='txfee'></span>
</div>
</div>
<div class="d-flex py-1 align-items-center custom-control custom-checkbox ${css.checkbox}">
......@@ -74,10 +119,14 @@ function confirmDialog (tx, amount, gasEstimation, self, newGasPriceCb, initialP
if (txFeeText) {
el.querySelector('#txfee').innerHTML = txFeeText
}
if (gasPriceValue) {
if (el.querySelector('#gasprice') && gasPriceValue) {
el.querySelector('#gasprice').value = gasPriceValue
onGasPriceChange()
}
if (el.querySelector('#maxfee') && network && network.lastBlock && network.lastBlock.baseFeePerGas) {
el.querySelector('#maxfee').value = parseInt(network.lastBlock.baseFeePerGas, 16)
onMaxFeeChange()
}
if (gasPriceStatus !== undefined) {
el.gasPriceStatus = gasPriceStatus
}
......
......@@ -216,7 +216,7 @@ export class LandingPage extends ViewPlugin {
const invertNum = (themeQuality === 'dark') ? 1 : 0
if (this.solEnv.getElementsByTagName('img')[0]) this.solEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
if (this.debuggerEnv.getElementsByTagName('img')[0]) this.debuggerEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
if (this.optimismEnv.getElementsByTagName('img')[0]) this.optimismEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
if (this.solhintEnv.getElementsByTagName('img')[0]) this.solhintEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
if (this.learnEthEnv.getElementsByTagName('img')[0]) this.learnEthEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
if (this.sourcifyEnv.getElementsByTagName('img')[0]) this.sourcifyEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
......@@ -277,10 +277,10 @@ export class LandingPage extends ViewPlugin {
this.verticalIcons.select('solidity')
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'solidity'])
}
const startDebugger = async () => {
await this.appManager.activatePlugin('debugger')
this.verticalIcons.select('debugger')
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'debugger'])
const startOptimism = async () => {
await this.appManager.activatePlugin('optimism-compiler')
this.verticalIcons.select('optimism-compiler')
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'optimism-compiler'])
}
const startSolhint = async () => {
await this.appManager.activatePlugin(['solidity', 'solhint'])
......@@ -385,8 +385,8 @@ export class LandingPage extends ViewPlugin {
// main
this.solEnv = createLargeButton('assets/img/solidityLogo.webp', 'solidityLogo', 'Solidity', startSolidity)
// Featured
this.debuggerEnv = createLargeButton('assets/img/debuggerLogo.webp', 'debuggerLogo', 'Debugger', startDebugger)
this.solhintEnv = createLargeButton('assets/img/solhintLogo.png', 'solhintLogo', 'solhint linter', startSolhint)
this.optimismEnv = createLargeButton('assets/img/optimismLogo.webp', 'optimismLogo', 'Optimism', startOptimism)
this.solhintEnv = createLargeButton('assets/img/solhintLogo.png', 'solhintLogo', 'Solhint linter', startSolhint)
this.learnEthEnv = createLargeButton('assets/img/learnEthLogo.webp', 'learnEthLogo', 'LearnEth', startLearnEth)
this.sourcifyEnv = createLargeButton('assets/img/sourcifyLogo.webp', 'sourcifyLogo', 'Sourcify', startSourceVerify)
this.moreEnv = createLargeButton('assets/img/moreLogo.webp', 'moreLogo', 'More', startPluginManager)
......@@ -395,7 +395,7 @@ export class LandingPage extends ViewPlugin {
const themeQuality = globalRegistry.get('themeModule').api.currentTheme().quality
const invertNum = (themeQuality === 'dark') ? 1 : 0
this.solEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
this.debuggerEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
this.optimismEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
this.solhintEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
this.learnEthEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
this.sourcifyEnv.getElementsByTagName('img')[0].style.filter = `invert(${invertNum})`
......@@ -505,10 +505,10 @@ export class LandingPage extends ViewPlugin {
<h4>Featured Plugins</h4>
<div class="d-flex flex-row pt-2">
${this.solEnv}
${this.optimismEnv}
${this.learnEthEnv}
${this.solhintEnv}
${this.sourcifyEnv}
${this.debuggerEnv}
${this.sourcifyEnv}
${this.moreEnv}
</div>
</div>
......
......@@ -51,7 +51,7 @@ const confirmationCb = function (network, tx, gasEstimation, continueTxExecution
return continueTxExecution(null)
}
var amount = Web3.utils.fromWei(typeConversion.toInt(tx.value), 'ether')
var content = confirmDialog(tx, amount, gasEstimation, self.udappUI,
var content = confirmDialog(tx, network, amount, gasEstimation,
(gasPrice, cb) => {
let txFeeText, priceStatus
// TODO: this try catch feels like an anti pattern, can/should be
......@@ -93,10 +93,9 @@ const confirmationCb = function (network, tx, gasEstimation, continueTxExecution
)
// TODO: check if this is check is still valid given the refactor
if (!content.gasPriceStatus) {
cancelCb('Given gas price is not correct')
cancelCb('Given transaction fee is not correct')
} else {
var gasPrice = Web3.utils.toWei(content.querySelector('#gasprice').value, 'gwei')
continueTxExecution(gasPrice)
continueTxExecution(content.txFee)
}
}
},
......
......@@ -109,7 +109,7 @@ ace.define("ace/theme/remixDark",["require","exports","module","ace/lib/dom"], f
}\
.ace-remixDark .ace_type {\
color:#75ceef;\
}]\
}\
.ace-remixDark .ace_visibility (\
color:#f7d777;\
)\
......
......@@ -20,9 +20,10 @@ export class ExecutionContext {
constructor () {
this.event = new EventManager()
this.executionContext = null
this.lastBlock = null
this.blockGasLimitDefault = 4300000
this.blockGasLimit = this.blockGasLimitDefault
this.currentFork = 'berlin'
this.currentFork = 'london'
this.mainNetGenesisHash = '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'
this.customNetWorks = {}
this.blocks = {}
......@@ -86,10 +87,10 @@ export class ExecutionContext {
web3.eth.getBlock(0, (error, block) => {
if (error) console.log('cant query first block')
if (block && block.hash !== this.mainNetGenesisHash) name = 'Custom'
callback(err, { id, name })
callback(err, { id, name, lastBlock: this.lastBlock, currentFork: this.currentFork })
})
} else {
callback(err, { id, name })
callback(err, { id, name, lastBlock: this.lastBlock, currentFork: this.currentFork })
}
})
}
......@@ -176,10 +177,11 @@ export class ExecutionContext {
const block = await web3.eth.getBlock('latest')
// we can't use the blockGasLimit cause the next blocks could have a lower limit : https://github.com/ethereum/remix/issues/506
this.blockGasLimit = (block && block.gasLimit) ? Math.floor(block.gasLimit - (5 * block.gasLimit) / 1024) : this.blockGasLimitDefault
this.lastBlock = block
try {
this.currentFork = execution.forkAt(await web3.eth.net.getId(), block.number)
} catch (e) {
this.currentFork = 'berlin'
this.currentFork = 'london'
console.log(`unable to detect fork, defaulting to ${this.currentFork}..`)
console.error(e)
}
......
{
"name": "@remix-project/remix-analyzer",
"version": "0.5.12",
"version": "0.5.13",
"description": "Tool to perform static analysis on Solidity smart contracts",
"main": "index.js",
"types": ".index.d.ts",
......@@ -19,14 +19,14 @@
}
],
"dependencies": {
"@ethereumjs/block": "^3.3.0",
"@ethereumjs/tx": "^3.2.1",
"@ethereumjs/vm": "^5.4.1",
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-astwalker": "^0.0.26",
"@remix-project/remix-lib": "^0.5.3",
"@remix-project/remix-lib": "^0.5.4",
"async": "^2.6.2",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.1.4",
"ethers": "^5.4.2",
"string-similarity": "^4.0.4",
"web3": "1.2.4"
},
......@@ -51,5 +51,5 @@
"typescript": "^3.7.5"
},
"typings": "index.d.ts",
"gitHead": "5e91f3010a7198f1b2d90cc7796bda750c58f1ea"
"gitHead": "664824605fa84648c79770631da371d4f81e0052"
}
\ No newline at end of file
{
"name": "@remix-project/remix-astwalker",
"version": "0.0.33",
"version": "0.0.34",
"description": "Tool to walk through Solidity AST",
"main": "index.js",
"scripts": {
......@@ -34,14 +34,14 @@
]
},
"dependencies": {
"@ethereumjs/block": "^3.3.0",
"@ethereumjs/tx": "^3.2.1",
"@ethereumjs/vm": "^5.4.1",
"@remix-project/remix-lib": "^0.5.3",
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-lib": "^0.5.4",
"@types/tape": "^4.2.33",
"async": "^2.6.2",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.1.4",
"ethers": "^5.4.2",
"nyc": "^13.3.0",
"string-similarity": "^4.0.4",
"tape": "^4.10.1",
......@@ -53,5 +53,5 @@
"tap-spec": "^5.0.0"
},
"typings": "index.d.ts",
"gitHead": "5e91f3010a7198f1b2d90cc7796bda750c58f1ea"
"gitHead": "664824605fa84648c79770631da371d4f81e0052"
}
\ No newline at end of file
{
"name": "@remix-project/remix-debug",
"version": "0.5.3",
"version": "0.5.4",
"description": "Tool to debug Ethereum transactions",
"contributors": [
{
......@@ -18,17 +18,17 @@
],
"main": "src/index.js",
"dependencies": {
"@ethereumjs/block": "^3.3.0",
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/common": "^2.2.0",
"@ethereumjs/tx": "^3.2.1",
"@ethereumjs/vm": "^5.4.1",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-astwalker": "^0.0.26",
"@remix-project/remix-lib": "^0.5.3",
"@remix-project/remix-lib": "^0.5.4",
"async": "^2.6.2",
"commander": "^2.19.0",
"deep-equal": "^1.0.1",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.1.4",
"ethers": "^5.4.2",
"string-similarity": "^4.0.4",
"web3": "^1.2.4"
},
......@@ -61,5 +61,5 @@
},
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-debug#readme",
"typings": "src/index.d.ts",
"gitHead": "5e91f3010a7198f1b2d90cc7796bda750c58f1ea"
"gitHead": "664824605fa84648c79770631da371d4f81e0052"
}
\ No newline at end of file
......@@ -46,7 +46,7 @@ type Opcode = {
* information about the opcode.
*/
export function parseCode (raw) {
const common = new Common({ chain: 'mainnet', hardfork: 'berlin' })
const common = new Common({ chain: 'mainnet', hardfork: 'london' })
const opcodes = getOpcodesForHF(common)
const code = []
......
......@@ -40,7 +40,7 @@ export class TraceManager {
const networkId = await this.web3.eth.net.getId()
this.fork = execution.forkAt(networkId, tx.blockNumber)
} catch (e) {
this.fork = 'berlin'
this.fork = 'london'
console.log(`unable to detect fork, defaulting to ${this.fork}..`)
console.error(e)
}
......
......@@ -11,7 +11,7 @@ export function sendTx (vm, from, to, value, data, cb?) {
return new Promise ((resolve, reject) => {
var tx = new Tx({
nonce: new BN(from.nonce++),
gasPrice: new BN(1),
// gasPrice: new BN(1),
gasLimit: new BN(3000000, 10),
to: to,
value: new BN(value, 10),
......
......@@ -9,7 +9,7 @@ var remixLib = require('@remix-project/remix-lib')
function sendTx (vm, from, to, value, data, cb) {
var tx = new Tx({
nonce: new BN(from.nonce++),
gasPrice: new BN(1),
// gasPrice: new BN(1),
gasLimit: new BN(3000000, 10),
to: to,
value: new BN(value, 10),
......
{
"name": "@remix-project/remix-lib",
"version": "0.5.3",
"version": "0.5.4",
"description": "Library to various Remix tools",
"contributors": [
{
......@@ -14,9 +14,9 @@
],
"main": "src/index.js",
"dependencies": {
"@ethereumjs/block": "^3.3.0",
"@ethereumjs/tx": "^3.2.1",
"@ethereumjs/vm": "^5.4.1",
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"async": "^2.1.2",
"ethereumjs-util": "^7.0.10",
"ethers": "^4.0.40",
......@@ -53,5 +53,5 @@
},
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-lib#readme",
"typings": "src/index.d.ts",
"gitHead": "5e91f3010a7198f1b2d90cc7796bda750c58f1ea"
"gitHead": "664824605fa84648c79770631da371d4f81e0052"
}
\ No newline at end of file
......@@ -17,7 +17,7 @@ export function forkAt (networkId, blockNumber) {
}
return currentForkName
}
return 'berlin'
return 'london'
}
// see https://github.com/ethereum/go-ethereum/blob/master/params/config.go
......@@ -46,6 +46,10 @@ const forks = {
{
number: 12244000,
name: 'berlin'
},
{
number: 12965000,
name: 'london'
}
],
3: [
......
......@@ -72,7 +72,7 @@ export class TxRunnerVM {
}
}
const EIP1559 = this.commonContext.hardfork() !== 'berlin'
const EIP1559 = this.commonContext.hardfork() !== 'berlin' // berlin is the only pre eip1559 fork that we handle.
let tx
if (!EIP1559) {
tx = Transaction.fromTxData({
......
......@@ -15,8 +15,18 @@ export class TxRunnerWeb3 {
this._api = api
}
_executeTx (tx, gasPrice, api, promptCb, callback) {
if (gasPrice) tx.gasPrice = this.getWeb3().utils.toHex(gasPrice)
_executeTx (tx, txFee, api, promptCb, callback) {
if (txFee) {
if (txFee.baseFeePerGas) {
tx.maxPriorityFee = this.getWeb3().utils.toHex(this.getWeb3().utils.toWei(txFee.maxPriorityFee, 'gwei'))
tx.maxFee = this.getWeb3().utils.toHex(this.getWeb3().utils.toWei(txFee.maxFee, 'gwei'))
tx.type = 2
} else {
tx.gasPrice = this.getWeb3().utils.toHex(this.getWeb3().utils.toWei(txFee.gasPrice, 'gwei'))
tx.type = 1
}
}
if (api.personalMode()) {
promptCb(
(value) => {
......@@ -100,8 +110,8 @@ export class TxRunnerWeb3 {
return
}
confirmCb(network, tx, tx['gas'], (gasPrice) => {
return this._executeTx(tx, gasPrice, this._api, promptCb, callback)
confirmCb(network, tx, tx['gas'], (txFee) => {
return this._executeTx(tx, txFee, this._api, promptCb, callback)
}, (error) => {
callback(error)
})
......
{
"name": "@remix-project/remix-simulator",
"version": "0.2.3",
"version": "0.2.4",
"description": "Ethereum IDE and tools for the web",
"contributors": [
{
......@@ -14,11 +14,11 @@
],
"main": "src/index.js",
"dependencies": {
"@ethereumjs/block": "^3.3.0",
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/common": "^2.2.0",
"@ethereumjs/tx": "^3.2.1",
"@ethereumjs/vm": "^5.4.1",
"@remix-project/remix-lib": "^0.5.3",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-lib": "^0.5.4",
"ansi-gray": "^0.1.1",
"async": "^3.1.0",
"body-parser": "^1.18.2",
......@@ -26,7 +26,7 @@
"commander": "^2.19.0",
"cors": "^2.8.5",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.1.4",
"ethers": "^5.4.2",
"express": "^4.16.3",
"express-ws": "^4.0.0",
"merge": "^1.2.0",
......@@ -66,5 +66,5 @@
},
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-simulator#readme",
"typings": "src/index.d.ts",
"gitHead": "5e91f3010a7198f1b2d90cc7796bda750c58f1ea"
"gitHead": "664824605fa84648c79770631da371d4f81e0052"
}
\ No newline at end of file
......@@ -99,7 +99,7 @@ export class VMContext {
constructor (fork?) {
this.blockGasLimitDefault = 4300000
this.blockGasLimit = this.blockGasLimitDefault
this.currentFork = fork || 'berlin'
this.currentFork = fork || 'london'
this.currentVm = this.createVm(this.currentFork)
this.blocks = {}
this.latestBlockNumber = 0
......
{
"name": "@remix-project/remix-solidity",
"version": "0.4.3",
"version": "0.4.4",
"description": "Tool to load and run Solidity compiler",
"main": "index.js",
"types": "./index.d.ts",
......@@ -15,14 +15,14 @@
}
],
"dependencies": {
"@ethereumjs/block": "^3.3.0",
"@ethereumjs/tx": "^3.2.1",
"@ethereumjs/vm": "^5.4.1",
"@remix-project/remix-lib": "^0.5.3",
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-lib": "^0.5.4",
"async": "^2.6.2",
"eslint-scope": "^5.0.0",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.1.4",
"ethers": "^5.4.2",
"solc": "^0.7.4",
"string-similarity": "^4.0.4",
"web3": "1.2.4",
......@@ -59,5 +59,5 @@
},
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-solidity#readme",
"typings": "index.d.ts",
"gitHead": "5e91f3010a7198f1b2d90cc7796bda750c58f1ea"
"gitHead": "664824605fa84648c79770631da371d4f81e0052"
}
\ No newline at end of file
{
"name": "@remix-project/remix-tests",
"version": "0.2.3",
"version": "0.2.4",
"description": "Tool to test Solidity smart contracts",
"main": "src/index.js",
"types": "./src/index.d.ts",
......@@ -35,13 +35,13 @@
},
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-tests#readme",
"dependencies": {
"@ethereumjs/block": "^3.3.0",
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/common": "^2.2.0",
"@ethereumjs/tx": "^3.2.1",
"@ethereumjs/vm": "^5.4.1",
"@remix-project/remix-lib": "^0.5.3",
"@remix-project/remix-simulator": "^0.2.3",
"@remix-project/remix-solidity": "^0.4.3",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-lib": "^0.5.4",
"@remix-project/remix-simulator": "^0.2.4",
"@remix-project/remix-solidity": "^0.4.4",
"ansi-gray": "^0.1.1",
"async": "^2.6.0",
"axios": ">=0.21.1",
......@@ -50,7 +50,7 @@
"colors": "^1.1.2",
"commander": "^2.13.0",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.1.4",
"ethers": "^5.4.2",
"express-ws": "^4.0.0",
"merge": "^1.2.0",
"signale": "^1.4.0",
......@@ -77,5 +77,5 @@
"typescript": "^3.3.1"
},
"typings": "src/index.d.ts",
"gitHead": "5e91f3010a7198f1b2d90cc7796bda750c58f1ea"
"gitHead": "664824605fa84648c79770631da371d4f81e0052"
}
\ No newline at end of file
......@@ -16,6 +16,24 @@ export const ModalDialog = (props: ModalDialogProps) => {
modal.current.focus()
}, [props.hide])
useEffect(() => {
function handleBlur (e) {
if (!e.currentTarget.contains(e.relatedTarget)) {
e.stopPropagation()
if (document.activeElement !== this) {
handleHide()
}
}
}
if (modal.current) {
modal.current.addEventListener('blur', handleBlur)
return () => {
modal.current.removeEventListener('blur', handleBlur)
}
}
}, [modal.current])
const modalKeyEvent = (keyCode) => {
if (keyCode === 27) { // Esc
if (props.cancelFn) props.cancelFn()
......@@ -40,13 +58,6 @@ export const ModalDialog = (props: ModalDialogProps) => {
handleHide()
}
const handleBlur = (e) => {
if (!e.currentTarget.contains(e.relatedTarget)) {
e.stopPropagation()
handleHide()
}
}
return (
<div
data-id={`${props.id}ModalDialogContainer-react`}
......@@ -58,7 +69,6 @@ export const ModalDialog = (props: ModalDialogProps) => {
>
<div className="modal-dialog" role="document">
<div
onBlur={handleBlur}
ref={modal}
tabIndex={-1}
className={'modal-content remixModalContent ' + (props.modalClass ? props.modalClass : '')}
......
......@@ -44,7 +44,7 @@ export const listenToEvents = (editor, compileTabLogic) => (dispatch: React.Disp
})
compileTabLogic.compiler.event.register('loadingCompiler', () => {
dispatch(setCompilerMode('compilationDuration'))
dispatch(setCompilerMode('loadingCompiler'))
})
compileTabLogic.compiler.event.register('compilerLoaded', () => {
......
......@@ -8,6 +8,14 @@ import { resetEditorMode, listenToEvents } from './actions/compiler'
import './css/style.css'
declare global {
interface Window {
_paq: any
}
}
const _paq = window._paq = window._paq || [] //eslint-disable-line
export const CompilerContainer = (props: CompilerContainerProps) => {
const { editor, config, queryParams, compileTabLogic, tooltip, modal, compiledFileName, setHardHatCompilation, updateCurrentVersion, isHardHatProject, configurationSettings } = props // eslint-disable-line
const [state, setState] = useState({
......@@ -27,8 +35,8 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
language: '',
evmVersion: ''
})
const [disableCompileButton, setDisableCompileButton] = useState<boolean>(false)
const compileIcon = useRef(null)
const warningIcon = useRef(null)
const promptMessageInput = useRef(null)
const [hhCompilation, sethhCompilation] = useState(false)
const [compilerContainer, dispatch] = useReducer(compilerReducer, compilerInitialState)
......@@ -75,6 +83,9 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
}, [compileTabLogic])
useEffect(() => {
const isDisabled = !compiledFileName || (compiledFileName && !isSolFileSelected(compiledFileName))
setDisableCompileButton(isDisabled)
setState(prevState => {
return { ...prevState, compiledFileName }
})
......@@ -235,14 +246,8 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
}
const compilationDuration = (speed: number) => {
if (!warningIcon.current) return
if (speed > 1000) {
const msg = `Last compilation took ${speed}ms. We suggest to turn off autocompilation.`
warningIcon.current.setAttribute('title', msg)
warningIcon.current.style.visibility = 'visible'
} else {
warningIcon.current.style.visibility = 'hidden'
console.log(`Last compilation took ${speed}ms. We suggest to turn off autocompilation.`)
}
}
......@@ -256,8 +261,8 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
if (!compileIcon.current) return
compileIcon.current.setAttribute('title', 'compiler is loading, please wait a few moments.')
compileIcon.current.classList.add('remixui_spinningIcon')
warningIcon.current.style.visibility = 'hidden'
_updateLanguageSelector()
setDisableCompileButton(true)
}
const compilerLoaded = () => {
......@@ -265,6 +270,9 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
compileIcon.current.setAttribute('title', '')
compileIcon.current.classList.remove('remixui_spinningIcon')
if (state.autoCompile) compile()
const isDisabled = !compiledFileName || (compiledFileName && !isSolFileSelected(compiledFileName))
setDisableCompileButton(isDisabled)
}
const compilationFinished = () => {
......@@ -272,6 +280,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
compileIcon.current.setAttribute('title', 'idle')
compileIcon.current.classList.remove('remixui_spinningIcon')
compileIcon.current.classList.remove('remixui_bouncingIcon')
_paq.push(['trackEvent', 'compiler', 'compiled_with_version', _retrieveVersion()])
}
const scheduleCompilation = () => {
......@@ -292,7 +301,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
if (!isSolFileSelected()) return
_setCompilerVersionFromPragma(currentFile)
compileTabLogic.runCompiler()
compileTabLogic.runCompiler(hhCompilation)
}
const _retrieveVersion = (version?) => {
......@@ -440,6 +449,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const handleNightliesChange = (e) => {
const checked = e.target.checked
if (!checked) handleLoadVersion(state.defaultVersion)
config.set('includeNightlies', checked)
setState(prevState => {
return { ...prevState, includeNightlies: checked }
......@@ -522,6 +532,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
<label className="remixui_compilerLabel form-check-label" htmlFor="evmVersionSelector">EVM Version</label>
<select value={state.evmVersion} onChange={(e) => handleEvmVersionChange(e.target.value)} className="custom-select" id="evmVersionSelector">
<option data-id={state.evmVersion === 'default' ? 'selected' : ''} value="default">compiler default</option>
<option data-id={state.evmVersion === 'berlin' ? 'selected' : ''} value="berlin">berlin</option>
<option data-id={state.evmVersion === 'muirGlacier' ? 'selected' : ''} value="muirGlacier">muirGlacier</option>
<option data-id={state.evmVersion === 'istanbul' ? 'selected' : ''} value="istanbul">istanbul</option>
<option data-id={state.evmVersion === 'petersburg' ? 'selected' : ''} value="petersburg">petersburg</option>
......@@ -564,13 +575,15 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
isHardHatProject && <div className="mt-2 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} />
<label className="form-check-label custom-control-label" htmlFor="enableHardhat">Enable Hardhat Compilation</label>
<a href="https://remix-ide.readthedocs.io/en/latest/hardhat.html#enable-hardhat-compilation" target="_blank">
<i className="ml-2 fas fa-info" title="Know how to use Hardhat Compilation"></i>
</a>
</div>
}
<button id="compileBtn" data-id="compilerContainerCompileBtn" className="btn btn-primary btn-block remixui_disabled mt-3" title="Compile" onClick={compile} disabled={!state.compiledFileName || (state.compiledFileName && !isSolFileSelected(state.compiledFileName))}>
<button id="compileBtn" data-id="compilerContainerCompileBtn" className="btn btn-primary btn-block remixui_disabled mt-3" title="Compile" onClick={compile} disabled={disableCompileButton}>
<span>
<i ref={warningIcon} title="Compilation Slow" style={{ visibility: 'hidden' }} className="remixui_warnCompilationSlow fas fa-exclamation-triangle" aria-hidden="true"></i>
{ warningIcon.current && warningIcon.current.style.visibility === 'hidden' && <i ref={compileIcon} className="fas fa-sync remixui_icon" aria-hidden="true"></i> }
Compile { state.compiledFileName || '<no file selected>' }
{ <i ref={compileIcon} className="fas fa-sync remixui_icon" aria-hidden="true"></i> }
Compile { typeof state.compiledFileName === 'string' ? helper.extractNameFromKey(state.compiledFileName) || '<no file selected>' : '<no file selected>' }
</span>
</button>
</header>
......
......@@ -162,17 +162,25 @@ export const ContractSelection = (props: ContractSelectionProps) => {
}
const contractProperties = contractsDetails[selectedContract] || {}
const log = <div className="remixui_detailsJSON">
{
Object.keys(contractProperties).map((propertyName, index) => {
const copyDetails = <span className="remixui_copyDetails"><CopyToClipboard content={contractProperties[propertyName]} direction='top' /></span>
const questionMark = <span className="remixui_questionMark"><i title={ help[propertyName] } className="fas fa-question-circle" aria-hidden="true"></i></span>
return (<div className="remixui_log" key={index}>
<div className="remixui_key">{ propertyName } { copyDetails } { questionMark }</div>
{ insertValue(contractProperties, propertyName) }
</div>)
})
}
<TreeView>
{
Object.keys(contractProperties).map((propertyName, index) => {
const copyDetails = <span className="remixui_copyDetails"><CopyToClipboard content={contractProperties[propertyName]} direction='top' /></span>
const questionMark = <span className="remixui_questionMark"><i title={ help[propertyName] } className="fas fa-question-circle" aria-hidden="true"></i></span>
return (
<div className="remixui_log" key={index}>
<TreeViewItem
label={
<div data-id={`remixui_treeviewitem_${propertyName}`} className="remixui_key">{ propertyName } { copyDetails } { questionMark }</div>
}>
{ insertValue(contractProperties, propertyName) }
</TreeViewItem>
</div>
)
})
}
</TreeView>
</div>
modal(selectedContract, log, 'Close', null)
......
'use strict'
import * as remixLib from '@remix-project/remix-lib'
const txHelper = remixLib.execution.txHelper
export class CompilerAbstract {
public languageversion: string
public data: Record<string, any>
public source: Record<string, any>
constructor (languageversion, data, source) {
this.languageversion = languageversion
this.data = data
this.source = source // source code
}
getContracts () {
return this.data.contracts
}
getContract (name) {
return txHelper.getContract(name, this.data.contracts)
}
visitContracts (calllback) {
return txHelper.visitContracts(this.data.contracts, calllback)
}
getData () {
return this.data
}
getAsts () {
return this.data.sources // ast
}
getSourceName (fileIndex) {
if (this.data && this.data.sources) {
return Object.keys(this.data.sources)[fileIndex]
} else if (Object.keys(this.source.sources).length === 1) {
// if we don't have ast, we return the only one filename present.
const sourcesArray = Object.keys(this.source.sources)
return sourcesArray[0]
}
return null
}
getSourceCode () {
return this.source
}
}
'use strict'
import { canUseWorker, urlFromVersion } from './compiler-utils'
import { Compiler } from '@remix-project/remix-solidity'
import { CompilerAbstract } from './compiler-abstract'
export const compile = async (compilationTargets, settings, contentResolverCallback) => {
return new Promise((resolve) => {
const compiler = new Compiler(contentResolverCallback)
compiler.set('evmVersion', settings.evmVersion)
compiler.set('optimize', settings.optimize)
compiler.set('language', settings.language)
compiler.set('runs', settings.runs)
compiler.loadVersion(canUseWorker(settings.version), urlFromVersion(settings.version))
compiler.event.register('compilationFinished', (success, compilationData, source) => {
resolve(new CompilerAbstract(settings.version, compilationData, source))
})
compiler.event.register('compilerLoaded', () => compiler.compile(compilationTargets, ''))
})
}
const semver = require('semver')
const minixhr = require('minixhr')
/* global Worker */
export const baseURLBin = 'https://binaries.soliditylang.org/bin'
export const baseURLWasm = 'https://binaries.soliditylang.org/wasm'
export const pathToURL = {}
/**
* Retrieves the URL of the given compiler version
* @param version is the version of compiler with or without 'soljson-v' prefix and .js postfix
*/
export function urlFromVersion (version) {
if (!version.startsWith('soljson-v')) version = 'soljson-v' + version
if (!version.endsWith('.js')) version = version + '.js'
return `${pathToURL[version]}/${version}`
}
/**
* Checks if the worker can be used to load a compiler.
* checks a compiler whitelist, browser support and OS.
*/
export function canUseWorker (selectedVersion) {
const version = semver.coerce(selectedVersion)
const isNightly = selectedVersion.includes('nightly')
return browserSupportWorker() && (
// All compiler versions (including nightlies) after 0.6.3 are wasm compiled
semver.gt(version, '0.6.3') ||
// Only releases are wasm compiled starting with 0.3.6
(semver.gte(version, '0.3.6') && !isNightly)
)
}
function browserSupportWorker () {
return document.location.protocol !== 'file:' && Worker !== undefined
}
// returns a promise for minixhr
export function promisedMiniXhr (url) {
return new Promise((resolve) => {
minixhr(url, (json, event) => {
resolve({ json, event })
})
})
}
export * from './compileTabLogic'
export * from './compiler-abstract'
export * from './compiler-helpers'
export * from './compiler-utils'
export * from './contract-parser'
import React, { useEffect, useState, useReducer } from 'react'
import React, { useEffect, useState, useReducer, CSSProperties } from 'react'
import Button from './Button/StaticAnalyserButton' // eslint-disable-line
import remixLib from '@remix-project/remix-lib'
import _ from 'lodash'
......@@ -89,6 +89,23 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
dispatch({ type: '', payload: {} })
// Show 'Enable Slither Analysis' checkbox
if (currentWorkspace && currentWorkspace.isLocalhost === true) setShowSlither('visible')
else {
setShowSlither('hidden')
setSlitherEnabled(false)
}
})
props.analysisModule.on('manager', 'pluginDeactivated', (plugin) => {
// Hide 'Enable Slither Analysis' checkbox
if (plugin.name === 'remixd') {
// Reset warning state
setWarningState([])
// Reset badge
props.event.trigger('staticAnaysisWarning', [])
// Reset state
dispatch({ type: '', payload: {} })
setShowSlither('hidden')
setSlitherEnabled(false)
}
})
return () => { }
}, [props])
......@@ -245,8 +262,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
showWarnings(warningMessage, 'warningModuleName')
props.event.trigger('staticAnaysisWarning', [warningCount])
}
}).catch((error) => {
console.log('Error found:', error) // This should be removed once testing done
}).catch(() => {
props.analysisModule.call('terminal', 'log', { type: 'error', value: '[Slither Analysis]: Error occured! See remixd console for details.' })
showWarnings(warningMessage, 'warningModuleName')
})
......@@ -398,7 +414,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
/>
<Button buttonText="Run" onClick={() => run(state.data, state.source, state.file)} disabled={(state.data === null || categoryIndex.length === 0) && !slitherEnabled }/>
</div>
<div className="d-flex" id="enableSlitherAnalysis">
<div className="d-flex" id="enableSlitherAnalysis" style={{ visibility: showSlither } as CSSProperties }>
<RemixUiCheckbox
id="enableSlither"
inputType="checkbox"
......@@ -406,8 +422,10 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
checked={slitherEnabled}
label="Enable Slither Analysis"
onChange={() => {}}
visibility = {showSlither}
/>
<a href="https://remix-ide.readthedocs.io/en/latest/slither.html#enable-slither-analysis" target="_blank">
<i className="ml-3 fas fa-info" title="Know how to use Slither Analysis"></i>
</a>
</div>
</div>
<div id="staticanalysismodules" className="list-group list-group-flush">
......
{
"name": "@remix-project/remix-url-resolver",
"version": "0.0.24",
"version": "0.0.25",
"description": "Solidity import url resolver engine",
"main": "index.js",
"types": "./index.d.ts",
......@@ -42,5 +42,5 @@
"typescript": "^3.1.6"
},
"typings": "index.d.ts",
"gitHead": "5e91f3010a7198f1b2d90cc7796bda750c58f1ea"
"gitHead": "664824605fa84648c79770631da371d4f81e0052"
}
\ No newline at end of file
{
"name": "@remix-project/remixd",
"version": "0.4.2",
"version": "0.5.0",
"description": "remix server: allow accessing file system from remix.ethereum.org and start a dev environment (see help section)",
"main": "index.js",
"types": "./index.d.ts",
......
......@@ -120,9 +120,9 @@ export class SlitherClient extends PluginClient {
allowPaths = allowPathString
remaps = remapString.trim()
}
const allowPathsOption: string = allowPaths ? `--allow-paths ${allowPaths}` : ''
const optimizeOption: string = optimize ? ' --optimize ' : ''
const evmOption: string = evmVersion ? ` --evm-version ${evmVersion}` : ''
const allowPathsOption: string = allowPaths ? `--allow-paths ${allowPaths} ` : ''
const optimizeOption: string = optimize ? '--optimize ' : ''
const evmOption: string = evmVersion ? `--evm-version ${evmVersion}` : ''
const solcArgs: string = optimizeOption || evmOption || allowPathsOption ? `--solc-args '${allowPathsOption}${optimizeOption}${evmOption}'` : ''
const solcRemaps = remaps ? `--solc-remaps "${remaps}"` : ''
......
This diff is collapsed.
{
"name": "remix-project",
"version": "0.15.0-dev",
"version": "0.16.0-dev",
"license": "MIT",
"description": "Ethereum Remix Monorepo",
"keywords": [
......@@ -130,10 +130,10 @@
},
"dependencies": {
"@erebos/bzz-node": "^0.13.0",
"@ethereumjs/block": "^3.3.0",
"@ethereumjs/common": "^2.3.1",
"@ethereumjs/tx": "^3.2.1",
"@ethereumjs/vm": "^5.4.1",
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/common": "^2.4.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remixproject/engine": "^0.3.17",
"@remixproject/engine-web": "^0.3.17",
"@remixproject/plugin": "^0.3.17",
......@@ -153,7 +153,7 @@
"deep-equal": "^1.0.1",
"document-register-element": "1.13.1",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.1.4",
"ethers": "^5.4.2",
"express-ws": "^4.0.0",
"file-saver": "^2.0.5",
"form-data": "^4.0.0",
......
# Release process
This document includes:
- how to release the remixd
- how to publish remix libs to NPM
- how to update remix.ethereum.org
- how to update remix-alpha.ethereum.org
- how to update remix-beta.ethereum.org
- how to release remix IDE
## RemixD release
- update new version number in remixd libs/remixd/package.json
- nx build remixd
- cd into ./dist/libs/remixd
- npm publish
- create bump PR to master.
## Remix libs release
(remove dist and login to npm)
- git fetch origin master
- git checkout origin/master
- git checkout -b bumpLibsVersion
......@@ -76,4 +85,4 @@ This is not strictly speaking a release. Updating the remix site is done through
## remix-alpha.ethereum.org update
remix-alpha.ethereum.org is automaticaly updated every time commits are pushed to master
\ No newline at end of file
remix-alpha.ethereum.org is automaticaly updated every time commits are pushed to master
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