Merge branch 'master' into intl

pull/5370/head
drafish 2 years ago
commit 9d39e56f71
  1. 4
      .prettierignore
  2. 3
      .prettierrc
  3. 6
      apps/remix-ide-e2e/src/tests/defaultLayout.test.ts
  4. 2
      apps/remix-ide-e2e/src/tests/fileExplorer.test.ts
  5. 136
      apps/remix-ide-e2e/src/tests/recorder.test.ts
  6. 21
      apps/remix-ide/bin/remix-ide
  7. 45
      apps/remix-ide/embark/README.md
  8. 66
      apps/remix-ide/embark/index.js
  9. 16
      apps/remix-ide/embark/package.json
  10. 5
      apps/remix-ide/src/app.js
  11. 2
      apps/remix-ide/src/app/panels/file-panel.js
  12. 5
      apps/remix-ide/src/app/tabs/locales/en-US.js
  13. 3
      apps/remix-ide/src/app/tabs/locales/zh-CN.js
  14. 55
      apps/remix-ide/src/app/tabs/runTab/model/recorder.js
  15. 2
      apps/remix-ide/src/walkthroughService.js
  16. 8
      libs/remix-lib/src/execution/forkAt.ts
  17. 2
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  18. 2
      libs/remix-ui/run-tab/src/lib/actions/index.ts
  19. 7
      libs/remix-ui/run-tab/src/lib/actions/recorder.ts
  20. 4
      libs/remix-ui/run-tab/src/lib/components/account.tsx
  21. 8
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  22. 2
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  23. 6
      libs/remix-ui/run-tab/src/lib/components/environment.tsx
  24. 2
      libs/remix-ui/run-tab/src/lib/components/gasPrice.tsx
  25. 48
      libs/remix-ui/run-tab/src/lib/components/recorderCardUI.tsx
  26. 2
      libs/remix-ui/run-tab/src/lib/components/value.tsx
  27. 7
      libs/remix-ui/run-tab/src/lib/reducers/runTab.ts
  28. 2
      libs/remix-ui/run-tab/src/lib/types/index.ts
  29. 2
      libs/remix-ui/run-tab/src/lib/types/recorder.d.ts
  30. 6
      libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
  31. 2
      libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx
  32. 2
      libs/remix-ui/terminal/src/lib/reducers/terminalReducer.ts
  33. 3
      package.json
  34. 65
      tslint.json
  35. 116
      yarn.lock

@ -1,4 +0,0 @@
# Add files here to ignore them from prettier formatting
/dist
/coverage

@ -1,3 +0,0 @@
{
"singleQuote": true
}

@ -17,7 +17,7 @@ module.exports = {
'Loads Side Panel': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORERS')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORER')
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemscripts"]')
@ -40,12 +40,12 @@ module.exports = {
'Toggles Side Panel': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORERS')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORER')
.clickLaunchIcon('filePanel')
.assert.hidden('div[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('filePanel')
.assert.visible('div[data-id="remixIdeSidePanel"]')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORERS')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORER')
},
'Toggles Terminal': function (browser: NightwatchBrowser) {

@ -18,7 +18,7 @@ module.exports = {
'Should create a new file `5_New_contract.sol` in file explorer': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('filePanel')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORERS')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORER')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]') // focus on root directory
.click('*[data-id="fileExplorerNewFilecreateNewFile"]')
.pause(1000)

@ -42,7 +42,7 @@ module.exports = {
.createContract(['12'])
.clickInstance(0)
.clickFunction('set - transact (not payable)', { types: 'uint256 _p', values: '34' })
.click('i.savetransaction')
.click('.savetransaction')
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]')
.execute(function () {
const modalOk = document.querySelector('[data-id="udappNotify-modal-footer-ok-react"]') as any
@ -77,7 +77,7 @@ module.exports = {
.selectContract('t2est')
.pause(1000)
.createContract([])
.click('i.savetransaction')
.click('.savetransaction')
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]')
.execute(function () {
const modalOk = document.querySelector('[data-id="udappNotify-modal-footer-ok-react"]') as any
@ -95,6 +95,50 @@ module.exports = {
status: 'true Transaction mined and execution succeed',
'decoded input': { 'uint256 _po': '10' }
})
},
'Run with live "mode"': function (browser: NightwatchBrowser) {
let addressRef: string
browser.addFile('scenario_live_mode.json', { content: JSON.stringify(liveModeScenario, null, '\t') })
.addFile('scenario_live_mode_storage.sol', { content: testStorageForLiveMode })
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]')
.openFile('scenario_live_mode.json')
.clickLaunchIcon('udapp')
.click('*[data-id="deployAndRunClearInstances"]')
.click('*[data-id="runtabLivemodeInput"]')
.click('.runtransaction')
.pause(1000)
.clickInstance(0)
.getAddressAtPosition(0, (address) => {
addressRef = address
})
.clickFunction('retrieve - call')
.perform((done) => {
browser.verifyCallReturnValue(addressRef, ['', '0:uint256: 350'])
.perform(() => done())
})
// change the init state and recompile the same contract.
.openFile('scenario_live_mode_storage.sol')
.setEditorValue(testStorageForLiveMode.replace('number = 350', 'number = 300'))
.pause(5000)
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]')
.openFile('scenario_live_mode.json')
.clickLaunchIcon('udapp')
.click('*[data-id="deployAndRunClearInstances"]')
.click('.runtransaction')
.pause(5000)
.clickInstance(0)
.getAddressAtPosition(0, (address) => {
addressRef = address
})
.clickFunction('retrieve - call')
.perform((done) => {
browser.verifyCallReturnValue(addressRef, ['', '0:uint256: 300'])
.perform(() => done())
})
.end()
}
}
@ -364,3 +408,91 @@ const scenario = {
]
}
}
const liveModeScenario = {
"accounts": {
"account{0}": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4"
},
"linkReferences": {},
"transactions": [
{
"timestamp": 1656329164297,
"record": {
"value": "0",
"parameters": [],
"abi": "0x8b8c9c14c8e1442e90dd6ff82bb9889ccfe5a54d88ef30776f11047ecce5fedb",
"contractName": "Storage",
"bytecode": "608060405234801561001057600080fd5b5060c88061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610604e577c010000000000000000000000000000000000000000000000000000000060003504632e64cec1811460535780636057361d146068575b600080fd5b60005460405190815260200160405180910390f35b60786073366004607a565b600055565b005b600060208284031215608b57600080fd5b503591905056fea264697066735822122091f1bc250ccda7caf2b0d9f67b0314d92233fdb5952b72cece72bd2a5d43cfc264736f6c63430008070033",
"linkReferences": {},
"name": "",
"inputs": "()",
"type": "constructor",
"from": "account{0}"
}
}
],
"abis": {
"0x8b8c9c14c8e1442e90dd6ff82bb9889ccfe5a54d88ef30776f11047ecce5fedb": [
{
"inputs": [
{
"internalType": "uint256",
"name": "num",
"type": "uint256"
}
],
"name": "store",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "retrieve",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
]
}
}
const testStorageForLiveMode = `// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/**
* @title Storage
* @dev Store & retrieve value in a variable
* @custom:dev-run-script ./scripts/deploy_with_ethers.ts
*/
contract Storage {
uint256 number;
constructor () {
number = 350;
}
/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}`

@ -1,21 +0,0 @@
#!/usr/bin/env node
var path = require('path')
var httpServer = require('http-server')
var remixd = require('remixd')
var server = httpServer.createServer({
root: path.join(__dirname, '/../')
})
var folder = process.argv.length > 2 ? process.argv[2] : process.cwd()
server.listen(8080, '127.0.0.1', function () {})
var router = new remixd.Router(65520, remixd.services.sharedFolder, { remixIdeUrl: 'http://localhost:8080' }, (webSocket) => {
remixd.services.sharedFolder.setWebSocket(webSocket)
remixd.services.sharedFolder.setupNotifications(folder)
remixd.services.sharedFolder.sharedFolder(folder, false)
})
router.start()
console.log('\x1b[33m%s\x1b[0m', 'Starting Remix IDE at http://localhost:8080 and sharing ' + folder)

@ -1,45 +0,0 @@
# embark-remix
An Embark plugin that allows Remix to connect to a local DApp via [`remixd`](https://github.com/ethereum/remixd). This plugin serves a local copy of Remix IDE from the machine running the plugin or alternatively allows connection from the public [Remix IDE](https://remix.ethereum.org). The URL of the Remix IDE can be specified in the Embark plugin options, specified below.
## Options
To configure options for the `embark-remix` plugin, modify the `plugins` property of `embark.json` in the DApp.
### How to use default options
To pass no options to the plugin and use the defaults, simply use an empty object:
```
"plugins": {
"embark-remix": {}
}
```
This will provide the default options to the plugin (shown below).
### Available options
The available options for this plugin are below. Default options are shown below. This is equivalent to passing an empty object `{}`.
```
"plugins": {
"embark-remix": {
"readOnly": false,
"remixIde": {
"protocol": "http",
"host": "localhost",
"port": 8088
}
}
}
```
`readOnly` does not let Remix update the contents on the local filesystem.
- Default: `false`
`remixIde` specifies the URL that the Remix IDE will be served from. If this is a `localhost` URL, the plugin creates a server that is responsible for listening on this URL.
- Default: `(see above)`
If it is preferred to connect to the public Remix IDE at https://remix.ethereum.org, set the `remixIde` config to:
```
"remixIde": {
"protocol": "https",
"host": "remix.ethereum.org",
"port": false
}
```

@ -1,66 +0,0 @@
const httpServer = require('http-server')
const remixd = require('remixd')
const path = require('path')
const merge = require('merge')
const colors = require('colors')
const DEFAULT_OPTIONS = {
protocol: 'http',
host: 'localhost',
port: '8088'
}
module.exports = (embark) => {
// plugin options
const readOnly = embark.pluginConfig.readOnly || false
const { protocol, host, port } = merge.recursive(DEFAULT_OPTIONS, embark.pluginConfig.remixIde)
// globals
const remixIdeUrl = `${protocol}://${host}` + `${port ? `:${port}` : ''}`
const sharedFolder = path.join(__dirname, '../../')
const sharedFolderService = remixd.services.sharedFolder
let server
// setup HTTP server
if (['localhost', '127.0.0.1', '0.0.0.0'].includes(host)) {
server = httpServer.createServer({
root: path.join(__dirname, '../../node_modules/remix-ide')
})
server.listen(port, '127.0.0.1', function () {
embark.logger.info('Remix IDE (via embark-remix plugin) available at ' + colors.underline(remixIdeUrl))
})
} else {
embark.logger.info('embark-remix is set to connect to a Remix IDE at ' + colors.underline(remixIdeUrl))
}
// setup Embark service check
embark.registerServiceCheck('Remix IDE', (cb) => {
return cb({ name: `Remix IDE ${host}:${port}`, status: 'on' })
})
// setup remixd shared folder service
const sharedFolderRouter = new remixd.Router(65520, sharedFolderService, { remixIdeUrl }, (webSocket) => {
sharedFolderService.setWebSocket(webSocket)
sharedFolderService.setupNotifications(sharedFolder)
sharedFolderService.sharedFolder(sharedFolder, readOnly)
})
const killRemixD = sharedFolderRouter.start()
const kill = () => {
if (server) server.close()
embark.logger.info(colors.red('embark-remix stopped'))
process.exit()
}
if (process.platform === 'win32') {
require('readline').createInterface({
input: process.stdin,
output: process.stdout
}).on('SIGINT', function () {
process.emit('SIGINT')
})
}
process.on('SIGINT', kill) // catch ctrl-c
process.on('SIGTERM', kill) // catch kill
process.on('exit', killRemixD)
}

@ -1,16 +0,0 @@
{
"name": "embark-remix",
"version": "0.0.2",
"description": "load remix IDE from embark environment",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
"dependencies": {
"remix-ide": "latest",
"remixd": "latest",
"http-server": "latest"
}
}

@ -326,7 +326,8 @@ class AppComponent {
filePanel.slitherHandle,
linkLibraries,
deployLibraries,
openZeppelinProxy
openZeppelinProxy,
run.recorder
])
this.layout.panels = {
@ -360,7 +361,7 @@ class AppComponent {
await this.appManager.activatePlugin(['settings', 'config'])
await this.appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'contextualListener', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport', 'gistHandler'])
await this.appManager.activatePlugin(['settings'])
await this.appManager.activatePlugin(['walkthrough','storage', 'search','compileAndRun'])
await this.appManager.activatePlugin(['walkthrough','storage', 'search','compileAndRun', 'recorder'])
this.appManager.on(
'filePanel',

@ -29,7 +29,7 @@ const { SlitherHandle } = require('../files/slither-handle.js')
const profile = {
name: 'filePanel',
displayName: 'File explorers',
displayName: 'File explorer',
intlId: 'filePanel.displayName',
methods: ['createNewFile', 'uploadFile', 'getCurrentWorkspace', 'getWorkspaces', 'createWorkspace', 'setWorkspace', 'registerContextMenuItem', 'renameWorkspace', 'deleteWorkspace'],
events: ['setWorkspace', 'workspaceRenamed', 'workspaceDeleted', 'workspaceCreated'],

@ -15,7 +15,7 @@ export default {
'settings.themes': 'Themes',
'settings.locales': 'Lanaguage',
'filePanel.displayName': 'File explorers',
'filePanel.displayName': 'File explorer',
'filePanel.workspace': 'Workspaces',
'filePanel.create': 'Create',
'filePanel.workspace.create': 'Create Workspace',
@ -89,7 +89,7 @@ export default {
'udapp.signature': 'signature',
'udapp.signedMessage': 'Signed Message',
'udapp.environment': 'Environment',
'udapp.setupEnvironmentDocs': 'check out docs to setup Environment',
'udapp.environmentDocs': 'Click for docs about Environment',
'udapp.deploy': 'Deploy',
'udapp.publishTo': 'Publish to',
'udapp.or': 'or',
@ -100,7 +100,6 @@ export default {
'udapp.deployAndRunClearInstances': 'Clear instances list and reset recorder',
'udapp.deployAndRunNoInstanceText': 'Currently you have no contract instances to interact with.',
'udapp.transactionsRecorded': 'Transactions recorded',
'udapp.transactionsRecordedText': 'All transactions (deployed contracts and function executions) can be saved and replayed inanother environment. e.g Transactions created in Javascript VM can be replayed in the Injected Web3.',
'search.displayName': 'Search in files',
'search.replace': 'Replace',

@ -89,7 +89,7 @@ export default {
'udapp.signature': '签名',
'udapp.signedMessage': '已签名的消息',
'udapp.environment': '环境',
'udapp.setupEnvironmentDocs': '查看环境设置文档',
'udapp.environmentDocs': '点击查看环境文档',
'udapp.deploy': '部署',
'udapp.publishTo': '发布到',
'udapp.or': '或',
@ -100,7 +100,6 @@ export default {
'udapp.deployAndRunClearInstances': '清空合约实例并重置交易记录',
'udapp.deployAndRunNoInstanceText': '当前您没有可交互的合约实例.',
'udapp.transactionsRecorded': '已记录交易',
'udapp.transactionsRecordedText': '可以记录一个环境中的所有交易 (包括合约部署和函数调用)并在另一个环境中重放。 例如在Javascript虚拟机环境中记录的交易可以在注入的Web3环境中重放。',
'search.displayName': '全文搜索',
'search.replace': '替换',

@ -1,16 +1,28 @@
var async = require('async')
var ethutil = require('ethereumjs-util')
var remixLib = require('@remix-project/remix-lib')
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../.././../../package.json'
var EventManager = remixLib.EventManager
var format = remixLib.execution.txFormat
var txHelper = remixLib.execution.txHelper
const helper = require('../../../../lib/helper')
const _paq = window._paq = window._paq || [] //eslint-disable-line
const profile = {
name: 'recorder',
displayName: 'Recorder',
description: '',
version: packageJson.version,
methods: [ ]
}
/**
* Record transaction as long as the user create them.
*/
class Recorder {
class Recorder extends Plugin {
constructor (blockchain) {
super(profile)
this.event = new EventManager()
this.blockchain = blockchain
this.data = { _listen: true, _replay: false, journal: [], _createdContracts: {}, _createdContractsReverse: {}, _usedAccounts: {}, _abis: {}, _contractABIReferences: {}, _linkReferences: {} }
@ -169,16 +181,30 @@ class Recorder {
/**
* run the list of records
*
* @param {Object} records
* @param {Object} accounts
* @param {Object} options
* @param {Object} abis
* @param {Object} linkReferences
* @param {Function} confirmationCb
* @param {Function} continueCb
* @param {Function} promptCb
* @param {Function} alertCb
* @param {Function} logCallBack
* @param {Function} liveMode
* @param {Function} newContractFn
*
*/
run (records, accounts, options, abis, linkReferences, confirmationCb, continueCb, promptCb, alertCb, logCallBack, newContractFn) {
run (records, accounts, options, abis, linkReferences, confirmationCb, continueCb, promptCb, alertCb, logCallBack, liveMode, newContractFn) {
this.setListen(false)
logCallBack(`Running ${records.length} transaction(s) ...`)
async.eachOfSeries(records, (tx, index, cb) => {
const liveMsg = liveMode ? ' in live mode' : ''
logCallBack(`Running ${records.length} transaction(s)${liveMsg} ...`)
async.eachOfSeries(records, async (tx, index, cb) => {
if (liveMode && tx.record.type === 'constructor') {
// resolve the bytecode using the contract name, this ensure getting the last compiled one.
const data = await this.call('compilerArtefacts', 'getArtefactsByContractName', tx.record.contractName)
tx.record.bytecode = data.artefact.evm.bytecode.object
}
var record = this.resolveAddress(tx.record, accounts, options)
var abi = abis[tx.record.abi]
if (!abi) {
@ -257,8 +283,10 @@ class Recorder {
}, () => { this.setListen(true) })
}
runScenario (json, continueCb, promptCb, alertCb, confirmationCb, logCallBack, cb) {
runScenario (liveMode, json, continueCb, promptCb, alertCb, confirmationCb, logCallBack, cb) {
_paq.push(['trackEvent', 'run', 'recorder', 'start'])
if (!json) {
_paq.push(['trackEvent', 'run', 'recorder', 'wrong-json'])
return cb('a json content must be provided')
}
if (typeof json === 'string') {
@ -269,12 +297,17 @@ class Recorder {
}
}
let txArray
let accounts
let options
let abis
let linkReferences
try {
var txArray = json.transactions || []
var accounts = json.accounts || []
var options = json.options || {}
var abis = json.abis || {}
var linkReferences = json.linkReferences || {}
txArray = json.transactions || []
accounts = json.accounts || []
options = json.options || {}
abis = json.abis || {}
linkReferences = json.linkReferences || {}
} catch (e) {
return cb('Invalid Scenario File. Please try again')
}
@ -283,7 +316,7 @@ class Recorder {
return
}
this.run(txArray, accounts, options, abis, linkReferences, confirmationCb, continueCb, promptCb, alertCb, logCallBack, (abi, address, contractName) => {
this.run(txArray, accounts, options, abis, linkReferences, confirmationCb, continueCb, promptCb, alertCb, logCallBack, liveMode, (abi, address, contractName) => {
cb(null, abi, address, contractName)
})
}

@ -33,7 +33,7 @@ export class WalkthroughService extends Plugin {
{
element: document.querySelector('#verticalIconsKindsolidity'),
title: 'Solidity Compiler',
intro: 'Having selected a .sol file in the File Explorers (the icon above), compile it with the Solidity Compiler.',
intro: 'Having selected a .sol file in the File Explorer (the icon above), compile it with the Solidity Compiler.',
tooltipClass: 'bg-light text-dark',
position: 'right'
},

@ -50,6 +50,14 @@ const forks = {
{
number: 12965000,
name: 'london'
},
{
number: 13773000,
name: 'arrowGlacier'
},
{
number: 15050000,
name: 'grayGlacier'
}
],
3: [

@ -334,7 +334,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
return { ...prevState, opt: { ...prevState.opt, debugWithGeneratedSources: checked } }
})
}} 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 (Solidity {'>='} v0.7.2)</label>
</div>
{ state.isLocalNodeUsed && <div className="mt-2 mb-2 debuggerConfig custom-control custom-checkbox">
<input className="custom-control-input" id="debugWithLocalNodeInput" onChange={({ target: { checked } }) => {

@ -54,7 +54,7 @@ export const getExecutionContext = () => getContext(plugin)
export const executeTransactions = (instanceIndex: number, lookupOnly: boolean, funcABI: FuncABI, inputsValues: string, contractName: string, contractABI, contract, address, logMsg:string, mainnetPrompt: MainnetPrompt, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, funcIndex?: number) => runTransactions(plugin, dispatch, instanceIndex, lookupOnly, funcABI, inputsValues, contractName, contractABI, contract, address, logMsg, mainnetPrompt, gasEstimationPrompt, passphrasePrompt, funcIndex)
export const loadFromAddress = (contract: ContractData, address: string) => loadAddress(plugin, dispatch, contract, address)
export const storeNewScenario = async (prompt: (msg: string, defaultValue: string) => JSX.Element) => storeScenario(plugin, dispatch, prompt)
export const runScenario = (gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => runCurrentScenario(plugin, dispatch, gasEstimationPrompt, passphrasePrompt, confirmDialogContent)
export const runScenario = (liveMode: boolean, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => runCurrentScenario(liveMode, plugin, dispatch, gasEstimationPrompt, passphrasePrompt, confirmDialogContent)
export const setScenarioPath = (path: string) => updateScenarioPath(dispatch, path)
export const getFuncABIValues = (funcABI: FuncABI) => getFuncABIInputs(plugin, funcABI)
export const setNetworkName = (networkName: string) => setNetworkNameFromProvider(dispatch, networkName)

@ -36,12 +36,13 @@ export const storeScenario = async (plugin: RunTab, dispatch: React.Dispatch<any
)
}
const runScenario = (plugin: RunTab, dispatch: React.Dispatch<any>, file: string, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => {
const runScenario = (liveMode: boolean, plugin: RunTab, dispatch: React.Dispatch<any>, file: string, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => {
if (!file) return dispatch(displayNotification('Alert', 'Unable to run scenerio, no specified scenario file', 'OK', null))
plugin.fileManager.readFile(file).then((json) => {
// TODO: there is still a UI dependency to remove here, it's still too coupled at this point to remove easily
plugin.recorder.runScenario(
liveMode,
json,
(error, continueTxExecution, cancelCb) => {
continueHandler(dispatch, gasEstimationPrompt, error, continueTxExecution, cancelCb)
@ -64,9 +65,9 @@ const runScenario = (plugin: RunTab, dispatch: React.Dispatch<any>, file: string
}).catch((error) => dispatch(displayNotification('Alert', error, 'OK', null)))
}
export const runCurrentScenario = (plugin: RunTab, dispatch: React.Dispatch<any>, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => {
export const runCurrentScenario = (liveMode: boolean, plugin: RunTab, dispatch: React.Dispatch<any>, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => {
const file = plugin.config.get('currentFile')
if (!file) return dispatch(displayNotification('Alert', 'A scenario file has to be selected', 'Ok', null))
runScenario(plugin, dispatch, file, gasEstimationPrompt, passphrasePrompt, confirmDialogContent)
runScenario(liveMode, plugin, dispatch, file, gasEstimationPrompt, passphrasePrompt, confirmDialogContent)
}

@ -163,8 +163,8 @@ export function AccountUI (props: AccountProps) {
accounts.map((value, index) => <option value={value} key={index}>{ loadedAccounts[value] }</option>)
}
</select>
<div style={{ marginLeft: -5 }}><CopyToClipboard content={selectedAccount} direction='top' /></div>
<i id="remixRunSignMsg" data-id="settingsRemixRunSignMsg" className="mx-1 fas fa-edit udapp_icon" aria-hidden="true" onClick={signMessage} title="Sign a message using this account key"></i>
<div style={{ marginLeft: -5 }}><CopyToClipboard tip='Copy account to clipboard' content={selectedAccount} direction='top' /></div>
<i id="remixRunSignMsg" data-id="settingsRemixRunSignMsg" className="mx-1 fas fa-edit udapp_icon" aria-hidden="true" onClick={signMessage} title="Sign a message using this account"></i>
</div>
</div>
)

@ -121,12 +121,12 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
if (enable) {
setAtAddressOptions({
disabled: false,
title: 'Interact with the given contract.'
title: 'Interact with the deployed contract - requires the .abi file or compiled .sol file to be selected in the editor (with the same compiler configuration)'
})
} else {
setAtAddressOptions({
disabled: true,
title: loadedAddress ? 'Compile *.sol file or select *.abi file.' : '⚠ Compile *.sol file or select *.abi file & then enter the address of deployed contract.'
title: loadedAddress ? 'Compile a *.sol file or select a *.abi file.' : 'To interact with a deployed contract, enter its address and compile its source *.sol file (with the same compiler settings) or select its .abi file in the editor. '
})
}
}
@ -135,12 +135,12 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
if (enable) {
setContractOptions({
disabled: false,
title: 'Select contract for Deploy or At Address.'
title: 'Select a compiled contract to deploy or to use with At Address.'
})
} else {
setContractOptions({
disabled: true,
title: loadType === 'sol' ? 'Select and compile *.sol file to deploy or access a contract.' : '⚠ Selected *.abi file allows accessing contracts, select and compile *.sol file to deploy and access one.'
title: loadType === 'sol' ? 'Select and compile *.sol file to deploy or access a contract.' : 'When there is a compiled .sol file, the choice of contracts to deploy or to use with AtAddress is made here.'
})
}
}

@ -292,7 +292,7 @@ export function ContractGUI (props: ContractGUIProps) {
})}
</div>
<div className="udapp_group udapp_multiArg">
<CopyToClipboard tip='Encode values of input fields & copy to clipboard' icon='fa-clipboard' direction={'left'} getContent={() => getContentOnCTC(multiFields.current)} />
<CopyToClipboard tip='Encode values of input fields & copy to clipboard' icon='fa-clipboard' direction={'bottom'} getContent={() => getContentOnCTC(multiFields.current)} />
<button onClick={() => handleMultiValsSubmit(multiFields.current)} title={buttonOptions.title} data-id={buttonOptions.dataId} className={`udapp_instanceButton ${buttonOptions.classList}`}>{ buttonOptions.content }</button>
</div>
</div>

@ -32,11 +32,11 @@ export function EnvironmentUI (props: EnvironmentProps) {
)
}
</select>
<a href="https://remix-ide.readthedocs.io/en/latest/run.html#run-setup" target="_blank" rel="noreferrer">
<a href="https://remix-ide.readthedocs.io/en/latest/run.html#environment" target="_blank" rel="noreferrer">
<i
className="udapp_infoDeployAction ml-2 fas fa-info"
title={intl.formatMessage({id: 'udapp.setupEnvironmentDocs', defaultMessage: "check out docs to setup Environment"})}>
</i>
title={intl.formatMessage({id: 'udapp.environmentDocs', defaultMessage: "Click for docs about Environment"})}
></i>
</a>
</div>
</div>

@ -11,7 +11,7 @@ export function GasPriceUI (props: GasPriceProps) {
return (
<div className="udapp_crow">
<label className="udapp_settingsLabel"><FormattedMessage id='udapp.gasLimit' defaultMessage='Gas limit' /></label>
<input type="number" className="form-control udapp_gasNval udapp_col2" id="gasLimit" value={props.gasLimit} onChange={handleGasLimit} />
<input type="number" className="form-control udapp_gasNval udapp_col2" title="The default gas limit is 3M. Adjust as needed." id="gasLimit" value={props.gasLimit} onChange={handleGasLimit} />
</div>
)
}

@ -1,16 +1,19 @@
// eslint-disable-next-line no-use-before-define
import React, {useState} from 'react'
import React, {useRef, useState} from 'react'
import { FormattedMessage } from 'react-intl'
import { RecorderProps } from '../types'
import { OverlayTrigger, Tooltip } from 'react-bootstrap' // eslint-disable-line
export function RecorderUI (props: RecorderProps) {
const inputLive = useRef<HTMLInputElement>()
const [toggleExpander, setToggleExpander] = useState<boolean>(false)
const triggerRecordButton = () => {
props.storeScenario(props.scenarioPrompt)
}
const handleClickRunButton = () => {
props.runCurrentScenario(props.gasEstimationPrompt, props.passphrasePrompt, props.mainnetPrompt)
const liveMode = inputLive.current ? inputLive.current.checked : false
props.runCurrentScenario(liveMode, props.gasEstimationPrompt, props.passphrasePrompt, props.mainnetPrompt)
}
const toggleClass = () => {
@ -25,6 +28,14 @@ export function RecorderUI (props: RecorderProps) {
<FormattedMessage id='udapp.transactionsRecorded' defaultMessage='Transactions recorded' />
</label>
<div className="ml-2 mb-2 badge badge-pill badge-primary" title="The number of recorded transactions">{props.count}</div>
<OverlayTrigger placement={'right'} overlay={
<Tooltip className="text-nowrap" id="info-recorder">
<span>Save transactions (deployed contracts and function executions) and replay them in another environment. <br/> e.g Transactions created in Javascript VM can be replayed in the Injected Web3.
</span>
</Tooltip>
}>
<i style={{ fontSize: 'medium' }} className={'ml-2 fal fa-info-circle'} aria-hidden="true"></i>
</OverlayTrigger>
</div>
<div>
<span data-id='udappRecorderTitleExpander' onClick={toggleClass}>
@ -32,19 +43,28 @@ export function RecorderUI (props: RecorderProps) {
</span>
</div>
</div>
<div className={`border-bottom flex-column ${toggleExpander ? "d-flex" : "d-none"}`}>
<div className="p-2 mt-2">
<FormattedMessage
id='udapp.transactionsRecordedText'
defaultMessage='All transactions (deployed contracts and function executions) can be saved and replayed in
another environment. e.g Transactions created in Javascript VM can be replayed in the Injected Web3.'
/>
<div className={`flex-column ${toggleExpander ? "d-flex" : "d-none"}`}>
<div className="mb-1 mt-1 fmt-2 custom-control custom-checkbox mb-1">
<input ref={inputLive} type="checkbox" id="livemode-recorder" className="custom-control-input custom-select" name="input-livemode"/>
<label className="form-check-label custom-control-label" data-id="runtabLivemodeInput" htmlFor="livemode-recorder">Use live mode (Run transactions against latest compiled contracts).</label>
</div>
<div className="mb-2 udapp_transactionActions">
<i className="fas fa-save savetransaction udapp_recorder udapp_icon"
onClick={triggerRecordButton} title="Save Transactions" aria-hidden="true">
</i>
<i className="fas fa-play runtransaction udapp_runTxs udapp_icon" title="Run Transactions" data-id="runtransaction" aria-hidden="true" onClick={handleClickRunButton}></i>
<div className="mb-1 mt-1 udapp_transactionActions">
<OverlayTrigger placement={'right'} overlay={
<Tooltip className="text-nowrap" id="tooltip-save-recorder">
<span>Save {props.count} transaction(s) as scenario file.
</span>
</Tooltip>
}>
<button className="btn btn-sm btn-info savetransaction udapp_recorder" onClick={triggerRecordButton}>Save</button>
</OverlayTrigger>
<OverlayTrigger placement={'right'} overlay={
<Tooltip className="text-nowrap" id="tooltip-run-recorder">
<span>Run transaction(s) from the current scenario file.
</span>
</Tooltip>
}>
<button className="btn btn-sm btn-info runtransaction udapp_runTxs" data-id="runtransaction" onClick={handleClickRunButton}>Run</button>
</OverlayTrigger>
</div>
</div>
</div>

@ -59,7 +59,7 @@ export function ValueUI (props: ValueProps) {
className="form-control udapp_gasNval udapp_col2"
id="value"
data-id="dandrValue"
title="Enter the value and choose the unit"
title="Enter an amount and choose its unit"
onKeyPress={validateInputKey}
onChange={validateValue}
value={props.sendValue}

@ -115,14 +115,14 @@ export const runTabInitialState: RunTabState = {
providerList: [{
id: 'vm-mode-london',
dataId: 'settingsVMLondonMode',
title: 'Execution environment does not connect to any node, everything is local and in memory only.',
title: 'Execution environment is local to Remix. Data is only saved to browser memory and will vanish upon reload.',
value: 'vm-london',
fork: 'london',
content: 'JavaScript VM (London)'
}, {
id: 'vm-mode-berlin',
dataId: 'settingsVMBerlinMode',
title: 'Execution environment does not connect to any node, everything is local and in memory only.',
title: 'Execution environment is local to Remix. Data is only saved to browser memory and will vanish upon reload.',
value: 'vm-berlin',
fork: 'berlin',
content: 'JavaScript VM (Berlin)'
@ -135,8 +135,7 @@ export const runTabInitialState: RunTabState = {
}, {
id: 'web3-mode',
dataId: 'settingsWeb3Mode',
title: `Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse!
If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http.`,
title: `Execution environment connects to an external node. For security, only connect to trusted networks. If Remix is served via https and your node is accessed via http, it might not work. In this case, try cloning the repository and serving it via http.`,
value: 'web3',
content: 'Web3 Provider'
}],

@ -166,7 +166,7 @@ export interface ContractDropdownProps {
export interface RecorderProps {
storeScenario: (prompt: (msg: string, defaultValue: string) => JSX.Element) => void,
runCurrentScenario: (gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => void,
runCurrentScenario: (liveMode: boolean, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => void,
mainnetPrompt: MainnetPrompt,
gasEstimationPrompt: (msg: string) => JSX.Element,
passphrasePrompt: (msg: string) => JSX.Element,

@ -9,7 +9,7 @@ export class Recorder {
getAll: () => void;
clearAll: () => void;
run: (records, accounts, options, abis, linkReferences, confirmationCb, continueCb, promptCb, alertCb, logCallBack, newContractFn) => void
runScenario: (json, continueCb, promptCb, alertCb, confirmationCb, logCallBack, cb) => void
runScenario: (liveMode, json, continueCb, promptCb, alertCb, confirmationCb, logCallBack, cb) => void
}
import { Blockchain } from "./blockchain";

@ -794,7 +794,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
<label className="remixui_compilerLabel form-check-label" htmlFor="compilierLanguageSelector">
<FormattedMessage id='solidity.language' defaultMessage='Language' />
</label>
<select onChange={(e) => handleLanguageChange(e.target.value)} disabled={state.useFileConfiguration} value={state.language} className="custom-select" id="compilierLanguageSelector" title="Available since v0.5.7">
<select onChange={(e) => handleLanguageChange(e.target.value)} disabled={state.useFileConfiguration} value={state.language} className="custom-select" id="compilierLanguageSelector" title="Language specification available from Compiler >= v0.5.7">
<option data-id={state.language === 'Solidity' ? 'selected' : ''} value='Solidity'>Solidity</option>
<option data-id={state.language === 'Yul' ? 'selected' : ''} value='Yul'>Yul</option>
</select>
@ -835,7 +835,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
</div>
<div className={`pt-2 ml-4 ml-2 align-items-start justify-content-between d-flex`}>
{ (!showFilePathInput && state.useFileConfiguration) && <span
title="Click to open the config file."
title="Click to open the config file"
onClick={configFilePath === '' ? () => {} : openFile}
className="py-2 remixui_compilerConfigPath"
>{configFilePath === '' ? 'No file selected.' : configFilePath}</span> }
@ -909,7 +909,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
}>
<a href="https://remix-ide.readthedocs.io/en/latest/running_js_scripts.html#compile-a-contract-and-run-a-script-on-the-fly" target="_blank" ><i className="pl-2 ml-2 mt-3 mb-1 fas fa-info text-dark"></i></a>
</OverlayTrigger>
<CopyToClipboard tip="Copy tag to use in contract NatSpec" getContent={() => '@custom:dev-run-script file_path'} direction='top'>
<CopyToClipboard tip="Click to copy the custom NatSpec tag" getContent={() => '@custom:dev-run-script file_path'} direction='top'>
<button className="btn remixui_copyButton ml-2 mt-3 mb-1 text-dark">
<i className="remixui_copyIcon far fa-copy" aria-hidden="true"></i>
</button>

@ -677,7 +677,7 @@ export const SolidityUnitTesting = (props: Record<string, any>) => { // eslint-d
<button
className="btn border w-50"
data-id="testTabGenerateTestFile"
title="Generate sample test file."
title="Generate a sample test file"
disabled={disableGenerateButton}
onClick={async () => {
await testTabLogic.generateTestFile((err:any) => { if (err) setToasterMsg(err)}) // eslint-disable-line @typescript-eslint/no-explicit-any

@ -154,7 +154,7 @@ export const registerScriptRunnerReducer = (state, action) => {
case INFO:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: 'text-log', provider: action.payload.provider })
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: 'text-success', provider: action.payload.provider })
}
case WARN:
return {

@ -172,6 +172,7 @@
"core-js": "^3.6.5",
"deep-equal": "^1.0.1",
"document-register-element": "1.13.1",
"eslint-config-prettier": "^8.5.0",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.4.2",
"ethjs-util": "^0.1.6",
@ -276,7 +277,6 @@
"csslint": "^1.0.2",
"dotenv": "^8.2.0",
"eslint": "6.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "2.20.2",
"eslint-plugin-jsx-a11y": "6.4.1",
@ -314,7 +314,6 @@
"npm-run-all": "^4.0.2",
"nyc": "^13.3.0",
"onchange": "^3.2.1",
"prettier": "1.19.1",
"request": "^2.83.0",
"rimraf": "^2.6.1",
"selenium-standalone": "^8.0.4",

@ -1,65 +0,0 @@
{
"rulesDirectory": ["node_modules/@nrwl/workspace/src/tslint"],
"linterOptions": {
"exclude": ["**/*"]
},
"rules": {
"arrow-return-shorthand": true,
"callable-types": true,
"class-name": true,
"deprecation": {
"severity": "warn"
},
"forin": true,
"import-blacklist": [true, "rxjs/Rx"],
"interface-over-type-literal": true,
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-arg": true,
"no-bitwise": true,
"no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [true, "ignore-params"],
"no-misused-new": true,
"no-non-null-assertion": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-unnecessary-initializer": true,
"no-unused-expression": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"prefer-const": true,
"radix": true,
"triple-equals": [true, "allow-null-check"],
"unified-signatures": true,
"variable-name": false,
"nx-enforce-module-boundaries": [
true,
{
"enforceBuildableLibDependency": true,
"allow": [],
"depConstraints": [
{ "sourceTag": "*", "onlyDependOnLibsWithTags": ["*"] }
]
}
]
}
}

@ -5542,22 +5542,17 @@ async-settle@^1.0.0:
dependencies:
async-done "^1.2.2"
async@0.9.x:
version "0.9.2"
resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
integrity sha512-l6ToIJIotphWahxxHyzK9bnLR6kM4jJIIgLShZeqLY7iboHoGkdgFl7W2/Ivi4SkMJYGKqW8vSuk0uKUj6qsSw==
async@^2.4.0, async@^2.5.0, async@^2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
version "2.6.4"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221"
integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==
dependencies:
lodash "^4.17.14"
async@^3.1.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.2.tgz#2eb7671034bb2194d45d30e31e24ec7e7f9670cd"
integrity sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==
async@^3.1.0, async@^3.2.3:
version "3.2.4"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
asynckit@^0.4.0:
version "0.4.0"
@ -6589,6 +6584,11 @@ boom@2.x.x:
dependencies:
hoek "2.x.x"
bootstrap@^5.1.3:
version "5.1.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.1.3.tgz#ba081b0c130f810fa70900acbc1c6d3c28fa8f34"
integrity sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==
borc@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/borc/-/borc-2.1.2.tgz#6ce75e7da5ce711b963755117dd1b187f6f8cf19"
@ -6645,6 +6645,13 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"
brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
dependencies:
balanced-match "^1.0.0"
brace@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/brace/-/brace-0.8.0.tgz#e826c6d5054cae5f607ad7b1c81236dd2cf01978"
@ -7424,7 +7431,7 @@ chalk@^3.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^4.0.0, chalk@^4.1.0:
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@ -8019,7 +8026,7 @@ compression@^1.7.4:
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
concat-stream@^1.5.0, concat-stream@^1.5.2:
version "1.6.0"
@ -9500,11 +9507,11 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
ejs@^3.1.5, ejs@^3.1.6:
version "3.1.6"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a"
integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==
version "3.1.8"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.8.tgz#758d32910c78047585c7ef1f92f9ee041c1c190b"
integrity sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==
dependencies:
jake "^10.6.1"
jake "^10.8.5"
electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.857:
version "1.3.866"
@ -9822,12 +9829,10 @@ escodegen@^2.0.0:
optionalDependencies:
source-map "~0.6.1"
eslint-config-prettier@^6.11.0:
version "6.15.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9"
integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==
dependencies:
get-stdin "^6.0.0"
eslint-config-prettier@^8.5.0:
version "8.5.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1"
integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==
eslint-config-standard@^14.1.1:
version "14.1.1"
@ -10280,11 +10285,9 @@ events@^2.0.0:
integrity sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==
eventsource@^1.0.7:
version "1.1.0"
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.0.tgz#00e8ca7c92109e94b0ddf32dac677d841028cfaf"
integrity sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==
dependencies:
original "^1.0.0"
version "1.1.2"
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.2.tgz#bc75ae1c60209e7cb1541231980460343eaea7c2"
integrity sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==
evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
version "1.0.3"
@ -10735,11 +10738,11 @@ file-uri-to-path@2:
integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==
filelist@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b"
integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==
version "1.0.4"
resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==
dependencies:
minimatch "^3.0.4"
minimatch "^5.0.1"
filename-regex@^2.0.0:
version "2.0.1"
@ -11372,11 +11375,6 @@ get-stdin@^5.0.0:
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=
get-stdin@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
@ -13765,13 +13763,13 @@ it-to-stream@^0.1.1:
p-fifo "^1.0.0"
readable-stream "^3.6.0"
jake@^10.6.1:
version "10.8.2"
resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b"
integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==
jake@^10.8.5:
version "10.8.5"
resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46"
integrity sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==
dependencies:
async "0.9.x"
chalk "^2.4.2"
async "^3.2.3"
chalk "^4.0.2"
filelist "^1.0.1"
minimatch "^3.0.4"
@ -15909,7 +15907,7 @@ minimalistic-crypto-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
minimatch@*, minimatch@3.0.4, minimatch@^3.0.4:
minimatch@*, minimatch@3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@ -15923,6 +15921,20 @@ minimatch@^3.0.0, minimatch@^3.0.2:
dependencies:
brace-expansion "^1.0.0"
minimatch@^3.0.4:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies:
brace-expansion "^1.1.7"
minimatch@^5.0.1:
version "5.1.0"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7"
integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==
dependencies:
brace-expansion "^2.0.1"
minimist-options@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
@ -17660,13 +17672,6 @@ ordered-read-streams@^1.0.0:
dependencies:
readable-stream "^2.0.1"
original@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==
dependencies:
url-parse "^1.4.3"
os-browserify@^0.3.0, os-browserify@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
@ -18808,11 +18813,6 @@ preserve@^0.2.0:
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
prettier@1.19.1:
version "1.19.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
pretty-format@^26.6.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93"
@ -23019,7 +23019,7 @@ url-parse-lax@^3.0.0:
dependencies:
prepend-http "^2.0.0"
url-parse@^1.4.3, url-parse@^1.5.3:
url-parse@^1.5.3:
version "1.5.10"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==

Loading…
Cancel
Save