Merge branch 'master' into gridView

pull/5370/head
Liana Husikyan 5 months ago committed by GitHub
commit 6df349f4e5
  1. 1
      README.md
  2. 7
      apps/circuit-compiler/src/app/services/circomPluginClient.ts
  3. 44
      apps/remix-ide-e2e/src/tests/file_explorer_context_menu.test.ts
  4. 159
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  5. 3
      apps/remix-ide/src/app/tabs/locales/en/udapp.json
  6. 2
      apps/remix-ide/webpack.config.js
  7. 10
      libs/remix-ui/run-tab/src/lib/actions/account.ts
  8. 4
      libs/remix-ui/run-tab/src/lib/actions/deploy.ts
  9. 9
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  10. 10
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  11. 6
      libs/remix-ui/run-tab/src/lib/components/environment.tsx
  12. 2
      libs/remix-ui/run-tab/src/lib/components/gasLimit.tsx
  13. 6
      libs/remix-ui/run-tab/src/lib/components/instanceContainerUI.tsx
  14. 6
      libs/remix-ui/run-tab/src/lib/components/recorderCardUI.tsx
  15. 31
      libs/remix-ui/run-tab/src/lib/components/universalDappUI.tsx
  16. 21
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  17. 14
      libs/remix-ui/run-tab/src/lib/types/index.ts
  18. 2
      libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
  19. 6
      libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx
  20. 2
      libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts
  21. 2
      libs/remix-ui/static-analyser/src/lib/Button/StaticAnalyserButton.tsx
  22. 2
      libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx

@ -32,7 +32,6 @@
![Remix screenshot](https://github.com/ethereum/remix-project/raw/master/apps/remix-ide/remix-screenshot-400h.png)
**VSCode extension**, see: [Ethereum-Remix](https://marketplace.visualstudio.com/items?itemName=RemixProject.ethereum-remix)
## Remix libraries
Remix libraries are essential for Remix IDE's native plugins. Read more about libraries [here](libs/README.md)

@ -10,6 +10,8 @@ import * as compilerV215 from 'circom_wasm/v2.1.5'
import { extractNameFromKey, extractParentFromKey } from '@remix-ui/helper'
import { CompilationConfig, CompilerReport, PrimeValue, ResolverOutput } from '../types'
// @ts-ignore
const _paq = (window._paq = window._paq || [])
export class CircomPluginClient extends PluginClient {
public internalEvents: EventManager
private _compilationConfig: CompilationConfig = {
@ -162,6 +164,7 @@ export class CircomPluginClient extends PluginClient {
const circuitErrors = circuitApi.report()
this.logCompilerReport(circuitErrors)
_paq.push(['trackEvent', 'circuit-compiler', 'compile', 'Compilation failed'])
throw new Error(circuitErrors)
} else {
this.lastCompiledFile = path
@ -181,6 +184,7 @@ export class CircomPluginClient extends PluginClient {
} else {
this.internalEvents.emit('circuit_compiling_done', [])
}
_paq.push(['trackEvent', 'circuit-compiler', 'compile', 'Compilation successful'])
circuitApi.log().map(log => {
log && this.call('terminal', 'log', { type: 'log', value: log })
})
@ -222,6 +226,7 @@ export class CircomPluginClient extends PluginClient {
const r1csErrors = r1csApi.report()
this.logCompilerReport(r1csErrors)
_paq.push(['trackEvent', 'circuit-compiler', 'generateR1cs', 'R1CS Generation failed'])
throw new Error(r1csErrors)
} else {
this.internalEvents.emit('circuit_generating_r1cs_done')
@ -230,6 +235,7 @@ export class CircomPluginClient extends PluginClient {
// @ts-ignore
await this.call('fileManager', 'writeFile', writePath, r1csProgram, true)
_paq.push(['trackEvent', 'circuit-compiler', 'generateR1cs', 'R1CS Generation successful'])
r1csApi.log().map(log => {
log && this.call('terminal', 'log', { type: 'log', value: log })
})
@ -250,6 +256,7 @@ export class CircomPluginClient extends PluginClient {
const witness = this.compiler ? await this.compiler.generate_witness(dataRead, input) : await generate_witness(dataRead, input)
// @ts-ignore
await this.call('fileManager', 'writeFile', wasmPath.replace('.wasm', '.wtn'), witness, true)
_paq.push(['trackEvent', 'circuit-compiler', 'computeWitness', 'Witness computing successful'])
this.internalEvents.emit('circuit_computing_witness_done')
this.emit('statusChanged', { key: 'succeed', title: 'witness computed successfully', type: 'success' })
}

@ -105,25 +105,25 @@ module.exports = {
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/Copy_README.txt"]', 7000)
},
// folder copy paste tests
'Should copy folder and paste in root with right click and it will contain a copied folder #group1 ': function (browser: NightwatchBrowser) {
browser
.rightClick('li[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementPresent('[data-id="contextMenuItemcopy')
.click('[data-id="contextMenuItemcopy"]')
.rightClick('*[data-id="treeViewLiMenu"]')
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemCopy_contracts"]', 7000)
},
'Should copy folder and paste in contracts with right click and it will contain a copied folder #group1 ': function (browser: NightwatchBrowser) {
browser
.pause(1000)
.waitForElementVisible('li[data-id="treeViewLitreeViewItemscripts"]')
.rightClick('li[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementPresent('[data-id="contextMenuItemcopy')
.click('[data-id="contextMenuItemcopy"]')
.rightClick('*[data-id="treeViewLitreeViewItemcontracts"]')
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/Copy_scripts"]', 7000)
}
}
// folder copy paste tests
'Should copy folder and paste in root with right click and it will contain a copied folder #group1 ': function (browser: NightwatchBrowser) {
browser
.rightClick('li[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementPresent('[data-id="contextMenuItemcopy')
.click('[data-id="contextMenuItemcopy"]')
.rightClick('*[data-id="treeViewLiMenu"]')
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemCopy_contracts"]', 7000)
},
'Should copy folder and paste in contracts with right click and it will contain a copied folder #group1 ': function (browser: NightwatchBrowser) {
browser
.pause(1000)
.waitForElementVisible('li[data-id="treeViewLitreeViewItemscripts"]')
.rightClick('li[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementPresent('[data-id="contextMenuItemcopy')
.click('[data-id="contextMenuItemcopy"]')
.rightClick('*[data-id="treeViewLitreeViewItemcontracts"]')
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/Copy_scripts"]', 7000)
}
}

@ -167,7 +167,7 @@ module.exports = {
},
'Should print hardhat logs #group4': function (browser: NightwatchBrowser) {
browser
.addFile('printHardhatlog.sol', { content: hardhatLog })
.addFile('printHardhatlog.sol', { content: hardhatLog })
.clickLaunchIcon('solidity')
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.waitForElementVisible('[for="autoCompile"]')
@ -266,22 +266,22 @@ module.exports = {
if (Array.isArray(result.value) && result.value.length > 0) {
console.log('Found ' + result.value.length + ' transactions')
browser
.click({
selector: '[data-id="listenNetworkCheckInput"]',
})
.click({
selector: '*[data-id="terminalClearConsole"]',
})
.click({
selector: '*[data-id="compilerContainerCompileAndRunBtn"]',
})
.pause(10000)
.waitForElementNotPresent({
locateStrategy: 'xpath',
selector: "//*[@class='remix_ui_terminal_log' and contains(.,'to:') and contains(.,'from:')]",
timeout: 120000
})
.end()
.click({
selector: '[data-id="listenNetworkCheckInput"]',
})
.click({
selector: '*[data-id="terminalClearConsole"]',
})
.click({
selector: '*[data-id="compilerContainerCompileAndRunBtn"]',
})
.pause(10000)
.waitForElementNotPresent({
locateStrategy: 'xpath',
selector: "//*[@class='remix_ui_terminal_log' and contains(.,'to:') and contains(.,'from:')]",
timeout: 120000
})
.end()
} else {
browser
.assert.fail('No transaction found')
@ -309,7 +309,7 @@ module.exports = {
.switchEnvironment('vm-custom-fork')
.waitForElementVisible('[data-id="vm-custom-fork-modal-footer-ok-react"]')
.execute(() => {
(document.querySelector('*[data-id="vm-custom-forkModalDialogContainer-react"] input[data-id="CustomForkNodeUrl"]') as any).focus()
(document.querySelector('*[data-id="vm-custom-forkModalDialogContainer-react"] input[data-id="CustomForkNodeUrl"]') as any).focus()
}, [], () => { })
.clearValue('*[data-id="CustomForkNodeUrl"]').pause(1000).setValue('*[data-id="CustomForkNodeUrl"]', 'https://go.getblock.io/ee42d0a88f314707be11dd799b122cb9')
.execute(() => {
@ -331,7 +331,7 @@ module.exports = {
.executeScriptInTerminal(`web3.eth.getCode('0x75F509A4eDA030470272DfBAf99A47D587E76709')`) // sepolia contract
.waitForElementContainsText('*[data-id="terminalJournal"]', byteCodeInSepolia, 120000)
.click('*[data-id="terminalClearConsole"]')
},
},
'Should run a free function while being connected to mainnet #group9': function (browser: NightwatchBrowser) {
const script = `
@ -359,10 +359,10 @@ module.exports = {
.switchEnvironment('vm-mainnet-fork')
.clickLaunchIcon('filePanel')
.addFile('test_mainnet.sol', { content: script })
const path = "//*[@class='view-line' and contains(.,'resolveENS') and contains(.,'view')]//span//span[contains(.,'(')]"
const path = "//*[@class='view-line' and contains(.,'resolveENS') and contains(.,'view')]//span//span[contains(.,'(')]"
const pathRunFunction = `//li//*[@aria-label='Run the free function "resolveENS"']`
browser.waitForElementVisible('#editorView')
browser.waitForElementVisible('#editorView')
//.waitForElementPresent(pathRunFunction)
.pause(10000) // the parser need to parse the code
.useXpath()
@ -371,25 +371,25 @@ module.exports = {
.perform(function () {
const actions = this.actions({ async: true });
return actions
.keyDown(this.Keys.SHIFT)
.keyDown(this.Keys.ALT)
.sendKeys('r')
.keyDown(this.Keys.SHIFT)
.keyDown(this.Keys.ALT)
.sendKeys('r')
})
.useCss()
.waitForElementContainsText('*[data-id="terminalJournal"]', '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', 120000)
},
'Should run free function which logs in the terminal #group10': function (browser: NightwatchBrowser) {
const script = `import "hardhat/console.sol";
function runSomething () view {
console.log("test running free function");
}
}
`
browser
.addFile('test.sol', { content: script })
.scrollToLine(3)
const path = "//*[@class='view-line' and contains(.,'runSomething') and contains(.,'view')]//span//span[contains(.,'(')]"
const path = "//*[@class='view-line' and contains(.,'runSomething') and contains(.,'view')]//span//span[contains(.,'(')]"
const pathRunFunction = `//li//*[@aria-label='Run the free function "runSomething"']`
browser.waitForElementVisible('#editorView')
.useXpath()
@ -398,18 +398,15 @@ module.exports = {
.perform(function () {
const actions = this.actions({ async: true });
return actions
.keyDown(this.Keys.SHIFT)
.keyDown(this.Keys.ALT)
.sendKeys('r')
.keyDown(this.Keys.SHIFT)
.keyDown(this.Keys.ALT)
.sendKeys('r')
})
.useCss()
.waitForElementContainsText('*[data-id="terminalJournal"]', 'test running free function', 120000)
}
}
const asyncAwait = `
var p = function () {
return new Promise(function (resolve, reject) {
@ -417,7 +414,7 @@ const asyncAwait = `
resolve("Promise Resolved")
}, 5000)
})
}
}
var run = async () => {
console.log('Waiting Promise')
@ -455,7 +452,7 @@ const resolveExternalUrlAndSave = `
} catch (e) {
console.log(e.message)
}
})()
})()
`
const resolveExternalUrlAndSaveToaPath = `
@ -466,7 +463,7 @@ const resolveExternalUrlAndSaveToaPath = `
} catch (e) {
console.log(e.message)
}
})()
})()
`
const resolveUrl = `
@ -477,7 +474,7 @@ const resolveUrl = `
} catch (e) {
console.log(e.message)
}
})()
})()
`
const deployWithEthersJs = `
@ -485,32 +482,32 @@ const deployWithEthersJs = `
(async () => {
try {
console.log('Running deployWithEthers script...')
const constructorArgs = [] // Put constructor args (if any) here for your contract
// Note that the script needs the ABI which is generated from the compilation artifact.
// Make sure contract is compiled and artifacts are generated
const artifactsPath = 'contracts/artifacts/Owner.json' // Change this for different path
const metadata = JSON.parse(await remix.call('fileManager', 'getFile', artifactsPath))
// 'web3Provider' is a remix global variable object
const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner()
let factory = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer)
let contract = await factory.deploy(...constructorArgs);
console.log('Contract Address: ', contract.address);
// The contract is NOT deployed yet; we must wait until it is mined
await contract.deployed()
console.log('Deployment successful.')
contract.on('OwnerSet', (previousOwner, newOwner) => {
console.log('previousOwner' , previousOwner)
console.log('newOwner' , newOwner)
})
console.log('ok')
} catch (e) {
console.log(e.message)
@ -577,12 +574,12 @@ contract StorageWithLib {
* @dev Store valrue in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
@ -629,11 +626,11 @@ describe("Storage", function () {
deployedLinkReferences: metadata.data.deployedBytecode.linkReferences,
}
const options = {
libraries: {
libraries: {
'Lib': lib.address
}
}
const factory = await ethers.getContractFactoryFromArtifact(artifact, options)
const storage = await factory.deploy();
await storage.deployed()
@ -657,10 +654,10 @@ import "hardhat/console.sol";
contract OwnerTest {
address private owner;
// event for EVM logging
event OwnerSet(address indexed oldOwner, address indexed newOwner);
// modifier to check if caller is owner
modifier isOwner() {
// If the first argument of 'require' evaluates to 'false', execution terminates and all
@ -671,7 +668,7 @@ contract OwnerTest {
require(msg.sender == owner, "Caller is not owner");
_;
}
/**
* @dev Set contract deployer as owner
*/
@ -692,7 +689,7 @@ contract OwnerTest {
}
/**
* @dev Return owner address
* @dev Return owner address
* @return address of owner
*/
function getOwner() external view returns (address) {
@ -705,39 +702,39 @@ const scriptAutoExec = {
contract: `// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;
library lib {
function test () public view returns (uint) {
return 147;
}
}
/**
* @title Storage
* @dev Store & retrieve value inr a variable
* @custom:dev-run-script ./scripts/deploy_storage.js
*/
contract Storage {
uint256 number;
/**
* @dev Store valrue in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
number = num;
}
/**
* @dev Return value
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
function getFromLib() public view returns (uint) {
return lib.test();
}
@ -747,16 +744,16 @@ const scriptAutoExec = {
// Right click on the script name and hit "Run" to execute
const { expect } = require("chai");
const { ethers } = require("hardhat");
(async () => {
try {
// function getContractFactoryFromArtifact(artifact: Artifact, signer?: ethers.Signer): Promise<ethers.ContractFactory>;
// function getContractFactoryFromArtifact(artifact: Artifact, factoryOptions: FactoryOptions): Promise<ethers.ContractFactory>;
const metadataLib = JSON.parse(await remix.call('fileManager', 'readFile', 'contracts/artifacts/lib.json'))
console.log('deploying lib:')
const artifactLib = {
contractName: 'Lib',
sourceName: 'contracts/1_Storage.sol',
@ -767,15 +764,15 @@ const scriptAutoExec = {
deployedLinkReferences: metadataLib.data.deployedBytecode.linkReferences,
}
const optionsLib = {}
const factoryLib = await ethers.getContractFactoryFromArtifact(artifactLib, optionsLib)
const lib = await factoryLib.deploy();
await lib.deployed()
console.log('lib deployed', lib.address)
const metadata = JSON.parse(await remix.call('fileManager', 'readFile', 'contracts/artifacts/Storage.json'))
const artifact = {
contractName: 'Storage',
@ -787,25 +784,25 @@ const scriptAutoExec = {
deployedLinkReferences: metadata.data.deployedBytecode.linkReferences,
}
const options = {
libraries: {
libraries: {
'lib': lib.address
}
}
const factory = await ethers.getContractFactoryFromArtifact(artifact, options)
const storage = await factory.deploy();
await storage.deployed()
const storeValue = await storage.store(333);
// wait until the transaction is mined
await storeValue.wait();
console.log((await storage.getFromLib()).toString())
// expect((await storage.getFromLib()).toString()).to.equal('34');
} catch (e) {
console.error(e.message)
}

@ -82,7 +82,8 @@
"udapp.solScan.iconTooltip": "Click to scan this contract for vulnerabilities using third-party SolidityScan [BETA]",
"udapp.solScan.modalTitle": "Permission to share code",
"udapp.solScan.modalMessage": "To scan the contract for vulnerabilities & possible risks, smart contract code will be shared to third-party SolidityScan (https://solidityscan.com/).\n\n Would you like to continue?",
"udapp.solScan.modalMessage": "To scan the contract for vulnerabilities & possible risks, smart contract code will be shared to third-party SolidityScan. ",
"udapp.solScan.likeToContinue": "Would you like to continue?",
"udapp.solScan.modalOkLabel": "Continue",
"udapp.solScan.modalCancelLabel": "Cancel",
"udapp.solScan.errModalTitle": "Scan error",

@ -170,7 +170,7 @@ class CopyFileAfterBuild {
apply(compiler) {
const onEnd = async () => {
try {
console.log('runnning CopyFileAfterBuild')
console.log('running CopyFileAfterBuild')
// This copy the raw-loader files used by the etherscan plugin to the remix-ide root folder.
// This is needed because by default the etherscan resources are served from the /plugins/etherscan/ folder,
// but the raw-loader try to access the resources from the root folder.

@ -1,7 +1,7 @@
import { shortenAddress } from "@remix-ui/helper"
import { RunTab } from "../types/run-tab"
import { clearInstances, setAccount, setExecEnv } from "./actions"
import { displayNotification, displayPopUp, fetchAccountsListFailed, fetchAccountsListRequest, fetchAccountsListSuccess, setMatchPassphrase, setPassphrase } from "./payload"
import { displayNotification, fetchAccountsListFailed, fetchAccountsListRequest, fetchAccountsListSuccess, setMatchPassphrase, setPassphrase } from "./payload"
import { toChecksumAddress } from '@ethereumjs/util'
export const updateAccountBalances = async (plugin: RunTab, dispatch: React.Dispatch<any>) => {
@ -39,7 +39,7 @@ export const fillAccountsList = async (plugin: RunTab, dispatch: React.Dispatch<
dispatch(fetchAccountsListFailed(e.message))
}
} catch (e) {
dispatch(displayPopUp(`Cannot get account list: ${e}`))
plugin.call('notification', 'toast', `Cannot get account list: ${e}`)
}
}
@ -78,9 +78,9 @@ export const createNewBlockchainAccount = async (plugin: RunTab, dispatch: React
},
async (error, address) => {
if (error) {
return dispatch(displayPopUp('Cannot create an account: ' + error))
return plugin.call('notification', 'toast', 'Cannot create an account: ' + error)
}
dispatch(displayPopUp(`account ${address} created`))
plugin.call('notification', 'toast', `account ${address} created`)
await fillAccountsList(plugin, dispatch)
}
)
@ -89,7 +89,7 @@ export const createNewBlockchainAccount = async (plugin: RunTab, dispatch: React
export const signMessageWithAddress = (plugin: RunTab, dispatch: React.Dispatch<any>, account: string, message: string, modalContent: (hash: string, data: string) => JSX.Element, passphrase?: string) => {
plugin.blockchain.signMessage(message, account, passphrase, (err, msgHash, signedData) => {
if (err) {
return displayPopUp(err)
return plugin.call('notification', 'toast', err)
}
dispatch(displayNotification('Signed Message', modalContent(msgHash, signedData), 'OK', null, () => {}, null))
})

@ -6,7 +6,7 @@ import { SolcInput, SolcOutput } from "@openzeppelin/upgrades-core"
// Used direct path to UpgradeableContract class to fix cyclic dependency error from @openzeppelin/upgrades-core library
import { UpgradeableContract } from '../../../../../../node_modules/@openzeppelin/upgrades-core/dist/standalone'
import { DeployMode, MainnetPrompt } from "../types"
import { displayNotification, displayPopUp, fetchProxyDeploymentsSuccess, setDecodedResponse, updateInstancesBalance } from "./payload"
import { displayNotification, fetchProxyDeploymentsSuccess, setDecodedResponse, updateInstancesBalance } from "./payload"
import { addInstance } from "./actions"
import { addressToString, logBuilder } from "@remix-ui/helper"
import Web3 from "web3"
@ -256,7 +256,7 @@ export const loadAddress = (plugin: RunTab, dispatch: React.Dispatch<any>, contr
const contractData = { name: '<at address>', abi, contract: { file: plugin.REACT_API.contracts.currentFile } } as ContractData
return addInstance(dispatch, { contractData, address, name: '<at address>' })
} else if (loadType === 'instance') {
if (!contract) return dispatch(displayPopUp('No compiled contracts found.'))
if (!contract) return plugin.call('notification', 'toast', 'No compiled contracts found.')
const currentFile = plugin.REACT_API.contracts.currentFile
const compiler = plugin.REACT_API.contracts.contractList[currentFile].find(item => item.alias === contract.name)
const contractData = getSelectedContract(contract.name, compiler.compiler)

@ -416,7 +416,7 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
) : null}
</div>
<div className="udapp_subcontainer">
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap text-left" tooltipId="remixUdappContractNamesTooltip" tooltipText={contractOptions.title}>
<CustomTooltip placement={'auto-end'} tooltipClasses="text-nowrap text-left" tooltipId="remixUdappContractNamesTooltip" tooltipText={contractOptions.title}>
<select
ref={contractsRef}
value={currentContract}
@ -447,7 +447,7 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
</div>
{evmVersion && loadedContractData && (
<CustomTooltip
placement={'right'}
placement={'auto-end'}
tooltipClasses="text-wrap text-left"
tooltipId="info-evm-version-warn"
tooltipText={
@ -483,6 +483,9 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
isValidProxyUpgrade={isValidProxyUpgrade}
modal={props.modal}
disabled={props.selectedAccount === ''}
solcVersion={props.solCompilerVersion}
setSolcVersion={props.setCompilerVersion}
getVersion={props.getCompilerVersion}
/>
<div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input
@ -494,7 +497,7 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
checked={props.ipfsCheckedState}
/>
<CustomTooltip
placement={'right'}
placement={'auto-end'}
tooltipClasses="text-wrap text-left"
tooltipId="remixIpfsUdappTooltip"
tooltipText={

@ -32,7 +32,6 @@ export function ContractGUI(props: ContractGUIProps) {
const initializeFields = useRef<Array<HTMLInputElement | null>>([])
const basicInputRef = useRef<HTMLInputElement>()
const intl = useIntl()
useEffect(() => {
if (props.deployOption && Array.isArray(props.deployOption)) {
if (props.deployOption[0] && props.deployOption[0].title === 'Deploy with Proxy' && props.deployOption[0].active) handleDeployProxySelect(true)
@ -173,6 +172,7 @@ export function ContractGUI(props: ContractGUIProps) {
}
const handleActionClick = async () => {
props.getVersion()
if (deployState.deploy) {
const proxyInitializeString = getMultiValsString(initializeFields.current)
props.clickCallBack(props.initializerOptions.inputs.inputs, proxyInitializeString, ['Deploy with Proxy'])
@ -285,7 +285,7 @@ export function ContractGUI(props: ContractGUIProps) {
<div className="udapp_contractActionsContainerSingle pt-2" style={{ display: toggleContainer ? 'none' : 'flex' }}>
<CustomTooltip
delay={0}
placement={'right'}
placement={'auto-end'}
tooltipClasses="text-wrap"
tooltipId="remixUdappInstanceButtonTooltip"
tooltipText={
@ -299,8 +299,8 @@ export function ContractGUI(props: ContractGUIProps) {
<div className="d-flex p-0 wrapperElement" onClick={handleActionClick} data-id={buttonOptions.dataId} data-title={buttonOptions.title}>
<button
className={`udapp_instanceButton text-nowrap overflow-hidden text-truncate ${props.widthClass} btn btn-sm ${buttonOptions.classList}`}
data-id={buttonOptions.dataId}
data-title={buttonOptions.title}
data-id={`${buttonOptions.dataId}`}
data-title={`${buttonOptions.title}`}
disabled={(toggleUpgradeImp && !proxyAddress) || props.disabled || (props.inputs !== '' && basicInput === '')}
>
{title}
@ -368,7 +368,7 @@ export function ContractGUI(props: ContractGUIProps) {
</label>
</button>
</CopyToClipboard>
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="remixUdappInstanceButtonTooltip" tooltipText={buttonOptions.title}>
<CustomTooltip placement={'auto-end'} tooltipClasses="text-nowrap" tooltipId="remixUdappInstanceButtonTooltip" tooltipText={buttonOptions.title}>
<div onClick={handleExpandMultiClick}>
<button
type="button"

@ -24,12 +24,12 @@ export function EnvironmentUI(props: EnvironmentProps) {
<label id="selectExEnv" className="udapp_settingsLabel">
<FormattedMessage id="udapp.environment" />
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText={<FormattedMessage id="udapp.tooltipText2" />}>
<CustomTooltip placement={'auto-end'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText={<FormattedMessage id="udapp.tooltipText2" />}>
<a href="https://chainlist.org/" target="_blank">
<i className={'ml-2 fas fa-plug'} aria-hidden="true"></i>
</a>
</CustomTooltip>
<CustomTooltip placement={'right'} tooltipClasses="text-wrap" tooltipId="runAndDeployAddresstooltip" tooltipText={<FormattedMessage id="udapp.environmentDocs" />}>
<CustomTooltip placement={'auto-end'} tooltipClasses="text-wrap" tooltipId="runAndDeployAddresstooltip" tooltipText={<FormattedMessage id="udapp.environmentDocs" />}>
<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-circle"></i>
</a>
@ -41,7 +41,7 @@ export function EnvironmentUI(props: EnvironmentProps) {
{isL2(currentProvider && currentProvider.displayName)}
{currentProvider && currentProvider.displayName}
{currentProvider && bridges[currentProvider.displayName] && (
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText={<FormattedMessage id="udapp.tooltipText3" />}>
<CustomTooltip placement={'auto-end'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText={<FormattedMessage id="udapp.tooltipText3" />}>
<i
style={{ fontSize: 'medium' }}
className={'ml-2 fa fa-rocket-launch'}

@ -64,7 +64,7 @@ export function GasLimitUI(props: GasPriceProps) {
<label className="mb-1 w-50 form-check-label custom-control-label" htmlFor="glManualConfig" data-id="glManualConfiguration">
<FormattedMessage id="udapp.gasLimitManual" />
</label>
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="remixGasPriceTooltip" tooltipText={<FormattedMessage id="udapp.tooltipText4" />}>
<CustomTooltip placement={'auto-end'} tooltipClasses="text-nowrap" tooltipId="remixGasPriceTooltip" tooltipText={<FormattedMessage id="udapp.tooltipText4" />}>
<input
type="number"
ref={inputComponent}

@ -44,6 +44,8 @@ export function InstanceContainerUI(props: InstanceContainerProps) {
plugin={props.plugin}
exEnvironment={props.exEnvironment}
editInstance={props.editInstance}
solcVersion={props.solcVersion}
getVersion={props.getVersion}
/>
)
})}
@ -62,7 +64,7 @@ export function InstanceContainerUI(props: InstanceContainerProps) {
</CustomTooltip>
{instanceList.length > 0 ? (
<CustomTooltip
placement="right"
placement={'auto-end'}
tooltipClasses="text-nowrap"
tooltipId="deployAndRunClearInstancesTooltip"
tooltipText={<FormattedMessage id="udapp.deployAndRunClearInstances" />}
@ -92,6 +94,8 @@ export function InstanceContainerUI(props: InstanceContainerProps) {
plugin={props.plugin}
exEnvironment={props.exEnvironment}
editInstance={props.editInstance}
solcVersion={props.solcVersion}
getVersion={props.getVersion}
/>
)
})}

@ -41,7 +41,7 @@ export function RecorderUI(props: RecorderProps) {
<FormattedMessage id="udapp.transactionsRecorded" />
</label>
<CustomTooltip
placement={'right'}
placement={'auto-end'}
tooltipClasses="text-nowrap"
tooltipId="recordedTransactionsCounttooltip"
tooltipText={<FormattedMessage id="udapp.transactionsCountTooltip" />}
@ -51,7 +51,7 @@ export function RecorderUI(props: RecorderProps) {
</div>
</CustomTooltip>
<CustomTooltip
placement={'right'}
placement={'auto-end'}
tooltipClasses="text-nowrap"
tooltipId="recordedTransactionsWalkthroughtooltip"
tooltipText={<FormattedMessage id="udapp.transactionsWalkthroughTooltip" />}
@ -77,7 +77,7 @@ export function RecorderUI(props: RecorderProps) {
<div className="mb-1 mt-1 custom-control custom-checkbox mb-1" id='udappRecorderUseLatest'>
<input ref={inputLive} type="checkbox" id="livemode-recorder" className="custom-control-input custom-select" name="input-livemode" />
<CustomTooltip
placement={'right'}
placement={'auto-end'}
tooltipClasses="text-wrap"
tooltipId="tooltip-livemode-recorder"
tooltipText={

@ -28,8 +28,6 @@ export function UniversalDappUI(props: UdappProps) {
const [evmBC, setEvmBC] = useState(null)
const [instanceBalance, setInstanceBalance] = useState(0)
const getVersion = () => window.location.href.split('=')[5].split('+')[0].split('-')[1]
useEffect(() => {
if (!props.instance.abi) {
const abi = txHelper.sortAbiFunction(props.instance.contractData.abi)
@ -295,7 +293,6 @@ export function UniversalDappUI(props: UdappProps) {
}
await props.plugin.call('notification', 'modal', modal)
}
})
}
}
@ -305,7 +302,11 @@ export function UniversalDappUI(props: UdappProps) {
const modal: AppModal = {
id: 'SolidityScanPermissionHandler',
title: <FormattedMessage id="udapp.solScan.modalTitle" />,
message: <FormattedMessage id="udapp.solScan.modalMessage" />,
message: <div className='d-flex flex-column'>
<span><FormattedMessage id="udapp.solScan.modalMessage" />
<a href={'https://solidityscan.com'} target="_blank" >Learn more</a></span><br/>
<FormattedMessage id="udapp.solScan.likeToContinue" />
</div>,
okLabel: <FormattedMessage id="udapp.solScan.modalOkLabel" />,
okFn: handleScanContinue,
cancelLabel: <FormattedMessage id="udapp.solScan.modalCancelLabel" />
@ -407,7 +408,7 @@ export function UniversalDappUI(props: UdappProps) {
</CustomTooltip>
)}
<CustomTooltip placement="top" tooltipClasses="text-nowrap" tooltipId="udapp_udappSolScanTooltip" tooltipText={<FormattedMessage id="udapp.solScan.iconTooltip" />}>
<i className="fas fa-qrcode p-0" onClick={askPermissionToScan}></i>
<i className="fas fa-qrcode p-0" style={{ padding: "0.15rem" }} onClick={askPermissionToScan}></i>
</CustomTooltip>
</div>
</div>
@ -435,6 +436,7 @@ export function UniversalDappUI(props: UdappProps) {
return (
<div key={index}>
<ContractGUI
getVersion={props.getVersion}
funcABI={funcABI}
clickCallBack={(valArray: {name: string; type: string}[], inputsValues: string) => {
runTransaction(lookupOnly, funcABI, valArray, inputsValues, index)
@ -469,10 +471,21 @@ export function UniversalDappUI(props: UdappProps) {
<div className="py-2 border-top d-flex justify-content-start flex-grow-1">
<FormattedMessage id="udapp.lowLevelInteractions" />
</div>
<CustomTooltip placement={'bottom-end'} tooltipClasses="text-wrap" tooltipId="receiveEthDocstoolTip" tooltipText={<FormattedMessage id="udapp.tooltipText8" />}>
<a href={`https://solidity.readthedocs.io/en/${getVersion()}/contracts.html#receive-ether-function`} target="_blank" rel="noreferrer">
<i aria-hidden="true" className="fas fa-info my-2 mr-1"></i>
</a>
<CustomTooltip
placement={'bottom-end'}
tooltipClasses="text-wrap"
tooltipId="receiveEthDocstoolTip"
tooltipText={<FormattedMessage id="udapp.tooltipText8" />}
>
{ // receive method added to solidity v0.6.x. use this as diff.
props.solcVersion.canReceive === false ? (
<a href={`https://solidity.readthedocs.io/en/v${props.solcVersion.version}/contracts.html`} target="_blank" rel="noreferrer">
<i aria-hidden="true" className="fas fa-info my-2 mr-1"></i>
</a>
) :<a href={`https://solidity.readthedocs.io/en/v${props.solcVersion.version}/contracts.html#receive-ether-function`} target="_blank" rel="noreferrer">
<i aria-hidden="true" className="fas fa-info my-2 mr-1"></i>
</a>
}
</CustomTooltip>
</div>
<div className="d-flex flex-column align-items-start">

@ -80,6 +80,22 @@ export function RunTabUI(props: RunTabProps) {
const [runTab, dispatch] = useReducer(runTabReducer, initialState)
const REACT_API = { runTab }
const currentfile = plugin.config.get('currentFile')
const [solcVersion, setSolcVersion] = useState<{version: string, canReceive: boolean}>({ version: '', canReceive: true })
const getVersion = () => {
let version = '0.8.25'
try {
version = window.location.href.split('=')[5].split('+')[0].split('-')[1].slice(1) ?? '0.8.25'
if (parseFloat(version) < 0.6) {
setSolcVersion({ version: version, canReceive: false })
} else {
setSolcVersion({ version: version, canReceive: true })
}
} catch (e) {
setSolcVersion({ version, canReceive: true })
console.log(e)
}
}
useEffect(() => {
if (!props.initialState) {
@ -306,6 +322,9 @@ export function RunTabUI(props: RunTabProps) {
isValidProxyAddress={isValidProxyAddress}
isValidProxyUpgrade={isValidProxyUpgrade}
proxy={runTab.proxy}
solCompilerVersion={solcVersion}
setCompilerVersion={setSolcVersion}
getCompilerVersion={getVersion}
/>
<RecorderUI
plugin={plugin}
@ -330,6 +349,8 @@ export function RunTabUI(props: RunTabProps) {
mainnetPrompt={mainnetPrompt}
runTransactions={executeTransactions}
sendValue={runTab.sendValue}
solcVersion={solcVersion}
getVersion={getVersion}
getFuncABIInputs={getFuncABIValues}
exEnvironment={runTab.selectExEnv}
editInstance={(instance) => {

@ -279,6 +279,11 @@ export interface ContractDropdownProps {
isValidProxyAddress?: (address: string) => Promise<boolean>,
isValidProxyUpgrade?: (proxyAddress: string, contractName: string, solcInput: SolcInput, solcOuput: SolcOutput, solcVersion: string) => Promise<LayoutCompatibilityReport | { ok: boolean, pass: boolean, warning: boolean }>,
proxy: { deployments: { address: string, date: string, contractName: string }[] }
solCompilerVersion: { version: string, canReceive: boolean }
setCompilerVersion: React.Dispatch<React.SetStateAction<{
version: string;
canReceive: boolean;}>>
getCompilerVersion: () => void
}
export interface RecorderProps {
@ -343,6 +348,8 @@ export interface InstanceContainerProps {
exEnvironment: string
editInstance: (instance) => void
plugin: RunTab
solcVersion: { version: string, canReceive: boolean }
getVersion: any
}
export interface Modal {
@ -397,6 +404,11 @@ export interface ContractGUIProps {
isValidProxyAddress?: (address: string) => Promise<boolean>,
isValidProxyUpgrade?: (proxyAddress: string) => Promise<LayoutCompatibilityReport | { ok: boolean, pass: boolean, warning: boolean }>,
modal?: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void, okBtnClass?: string, cancelBtnClass?: string) => void
solcVersion?: { version: string, canReceive: boolean }
setSolcVersion?: React.Dispatch<React.SetStateAction<{
version: string;
canReceive: boolean;}>>
getVersion: () => void
}
export interface MainnetProps {
network: Network,
@ -452,6 +464,8 @@ export interface UdappProps {
exEnvironment: string
editInstance: (instance) => void
plugin: RunTab
solcVersion: { version: string, canReceive: boolean }
getVersion: () => string
}
export interface DeployButtonProps {

@ -1127,7 +1127,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
disabled={(configFilePath === '' && state.useFileConfiguration) || disableCompileButton}
>
<CustomTooltip
placement="right"
placement={'auto-end'}
tooltipId="overlay-tooltip-compile-run"
tooltipText={
<div className="text-left">

@ -272,7 +272,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
}}
>
<CustomTooltip
placement="right"
placement={'auto-end'}
tooltipId="publishOnIpfsTooltip"
tooltipClasses="text-nowrap"
tooltipText={`${intl.formatMessage({
@ -295,7 +295,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
}}
>
<CustomTooltip
placement="right"
placement={'auto-end'}
tooltipId="publishOnSwarmTooltip"
tooltipClasses="text-nowrap"
tooltipText={`${intl.formatMessage({
@ -320,7 +320,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
}}
>
<CustomTooltip
placement="right"
placement={'auto-end'}
tooltipId="CompilationDetailsTooltip"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="solidity.displayContractDetails" />}

@ -104,7 +104,7 @@ export class CompileTabLogic {
* @param {string} target the path to the file to compile
*/
compileFile (target) {
if (!target) throw new Error('No target provided for compiliation')
if (!target) throw new Error('No target provided for compilation')
return new Promise((resolve, reject) => {
this.api.readFile(target).then(async(content) => {
const sources = { [target]: { content } }

@ -27,7 +27,7 @@ const StaticAnalyserButton = ({ onClick, buttonText, disabled, title, classList
)
const buttonWithTooltip = () => (
<CustomTooltip placement="right" tooltipId="ssaRunButtonTooltip" tooltipClasses="text-nowrap" tooltipText={title}>
<CustomTooltip placement={'auto-end'} tooltipId="ssaRunButtonTooltip" tooltipClasses="text-nowrap" tooltipText={title}>
<div id="staticAnalysisWrapper" className={`${newclassList} p-0`}>
<button id="staticAnalysisRunBtn" className={newclassList} disabled={disabled} onClick={onClick} style={{ pointerEvents: 'none', color: 'white' }}>
<span className="pl-3 pr-4">{buttonText}</span>

@ -118,7 +118,7 @@ const Icon = ({ iconRecord, verticalIconPlugin, contextMenuAction, theme }: Icon
>
<img
data-id={iconRecord.active ? `selected` : ''}
className={`${theme === 'dark' ? 'invert' : ''} ${theme} remixui_image ${iconRecord.active ? `selected-${theme}` : ''}`}
className={`${theme === 'dark' ? 'invert' : ''} ${theme} remixui_image ${iconRecord.active || iconRecord.pinned ? `selected-${theme}` : ''}`}
src={icon}
alt={name}
/>

Loading…
Cancel
Save