Merge branch 'master' into popuppanelfix

pull/5371/head
Aniket 2 weeks ago committed by GitHub
commit e3fc88385d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      apps/remix-ide-e2e/src/tests/circom.test.ts
  2. 2
      apps/remix-ide-e2e/src/tests/matomo.test.ts
  3. 4
      apps/remix-ide/src/app/components/preload.tsx
  4. 8
      apps/remix-ide/src/app/tabs/compile-tab.js
  5. 10
      apps/remix-ide/src/app/tabs/locales/ru/home.json
  6. 7
      apps/remix-ide/src/app/udapp/run-tab.tsx
  7. 3
      libs/remix-ui/plugin-manager/src/lib/components/ActivePluginCard.tsx
  8. 3
      libs/remix-ui/plugin-manager/src/lib/components/InactivePluginCard.tsx
  9. 265
      libs/remix-ui/run-tab/src/lib/actions/evmmap.ts
  10. 5
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  11. 21
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  12. 4
      libs/remix-ui/run-tab/src/lib/components/environment.tsx
  13. 2
      libs/remix-ui/run-tab/src/lib/components/instanceContainerUI.tsx
  14. 4
      libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx
  15. 4
      libs/remix-ui/run-tab/src/lib/components/universalDappUI.tsx
  16. 76
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  17. 21
      libs/remix-ui/run-tab/src/lib/types/index.ts
  18. 2
      libs/remix-ui/settings/src/lib/remix-ui-settings.tsx
  19. 2
      libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx

@ -196,7 +196,7 @@ module.exports = {
.waitForElementPresent('[data-id="verticalIconsKindcircuit-compiler"]') .waitForElementPresent('[data-id="verticalIconsKindcircuit-compiler"]')
.waitForElementVisible('[data-id="verticalIconsKindcircuit-compiler"]') .waitForElementVisible('[data-id="verticalIconsKindcircuit-compiler"]')
.click('[data-id="play-editor"]') .click('[data-id="play-editor"]')
.pause(7000) .pause(10000)
.journalLastChildIncludes('newZkey') .journalLastChildIncludes('newZkey')
.pause(25000) .pause(25000)
.journalLastChildIncludes('setup done.') .journalLastChildIncludes('setup done.')

@ -439,7 +439,7 @@ module.exports = {
return (window as any)._paq return (window as any)._paq
}, [], (res) => { }, [], (res) => {
const expectedEvents = [ const expectedEvents = [
["trackEvent", "Preload", "start"], ["trackEvent", "App", "Preload", "start"],
["trackEvent", "Storage", "activate", "indexedDB"], ["trackEvent", "Storage", "activate", "indexedDB"],
["trackEvent", "App", "load"], ["trackEvent", "App", "load"],
]; ];

@ -10,7 +10,7 @@ import './styles/preload.css'
import isElectron from 'is-electron' import isElectron from 'is-electron'
const _paq = (window._paq = window._paq || []) const _paq = (window._paq = window._paq || [])
_paq.push(['trackEvent', 'Preload', 'start']) _paq.push(['trackEvent', 'App', 'Preload', 'start'])
export const Preload = (props: any) => { export const Preload = (props: any) => {
const [tip, setTip] = useState<string>('') const [tip, setTip] = useState<string>('')
@ -40,7 +40,7 @@ export const Preload = (props: any) => {
}) })
}) })
.catch((err) => { .catch((err) => {
_paq.push(['trackEvent', 'Preload', 'error', err && err.message]) _paq.push(['trackEvent', 'App', 'PreloadError', err && err.message])
console.error('Error loading Remix:', err) console.error('Error loading Remix:', err)
setError(true) setError(true)
}) })

@ -99,13 +99,17 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
* This function is used by remix-plugin compiler API. * This function is used by remix-plugin compiler API.
* @param {object} settings {evmVersion, optimize, runs, version, language} * @param {object} settings {evmVersion, optimize, runs, version, language}
*/ */
setCompilerConfig (settings) { async setCompilerConfig (settings) {
super.setCompilerConfig(settings) super.setCompilerConfig(settings)
this.renderComponent() this.renderComponent()
// @todo(#2875) should use loading compiler return value to check whether the compiler is loaded instead of "setInterval" // @todo(#2875) should use loading compiler return value to check whether the compiler is loaded instead of "setInterval"
const value = JSON.stringify(settings, null, '\t') const value = JSON.stringify(settings, null, '\t')
let pluginInfo
pluginInfo = await this.call('udapp', 'showPluginDetails')
this.call('notification', 'toast', compilerConfigChangedToastMsg(this.currentRequest.from, value)) if (this.currentRequest.from === 'udapp') {
this.call('notification', 'toast', compilerConfigChangedToastMsg((pluginInfo ? pluginInfo.displayName : this.currentRequest.from ), value))
}
} }
compile (fileName) { compile (fileName) {

@ -1,4 +1,5 @@
{ {
"home.home": "Главная",
"home.scamAlert": "Предупреждение о мошенничестве", "home.scamAlert": "Предупреждение о мошенничестве",
"home.scamAlertText": "Единственный URL, который использует Remix, - это remix.ethereum.org", "home.scamAlertText": "Единственный URL, который использует Remix, - это remix.ethereum.org",
"home.scamAlertText2": "Остерегайтесь видеороликов, рекламирующих \"ботов-передовиков ликвидности\"", "home.scamAlertText2": "Остерегайтесь видеороликов, рекламирующих \"ботов-передовиков ликвидности\"",
@ -6,6 +7,9 @@
"home.learnMore": "Узнать больше", "home.learnMore": "Узнать больше",
"home.here": "здесь", "home.here": "здесь",
"home.featured": "Рекомендуемые", "home.featured": "Рекомендуемые",
"home.learnEthPromoTitle": "LearnEth: Учебники внутри Remix",
"home.learnEthPromoButton": "Начать обучение",
"home.learnEthPromoText": "Ознакомьтесь с уроками по Remix, Solidity и другим проектам Web3. Отлично подходит для всех уровней навыков.",
"home.jumpIntoWeb3": "Перейти в WEB3", "home.jumpIntoWeb3": "Перейти в WEB3",
"home.jumpIntoWeb3More": "Подробнее", "home.jumpIntoWeb3More": "Подробнее",
"home.jumpIntoWeb3Text": "Remix IDE является частью проекта Remix, широкий выбор инструментов которого, может быть использован для всего путешествия по разработке контракта пользователями любого уровня знаний. Узнайте больше на сайте проекта Remix.", "home.jumpIntoWeb3Text": "Remix IDE является частью проекта Remix, широкий выбор инструментов которого, может быть использован для всего путешествия по разработке контракта пользователями любого уровня знаний. Узнайте больше на сайте проекта Remix.",
@ -36,6 +40,7 @@
"home.ozerc1155TemplateDesc": "Создайте ERC1155 токен, импортируя библиотеку OpenZeppelin.", "home.ozerc1155TemplateDesc": "Создайте ERC1155 токен, импортируя библиотеку OpenZeppelin.",
"home.gnosisSafeMultisigTemplateDesc": "Создайте кошельки с мульти-подписью с использованием этого шаблона.", "home.gnosisSafeMultisigTemplateDesc": "Создайте кошельки с мульти-подписью с использованием этого шаблона.",
"home.zeroxErc20TemplateDesc": "Создайте токен ERC20, импортируя контракт с 0xProject.", "home.zeroxErc20TemplateDesc": "Создайте токен ERC20, импортируя контракт с 0xProject.",
"home.learnEthPluginDesc": "Узнайте о Remix, Solidity и других проектах Web3.",
"home.learn": "Обучение", "home.learn": "Обучение",
"home.learnEth1": "Основы Remix", "home.learnEth1": "Основы Remix",
"home.learnEth1Desc": "Введение в интерфейс Remix-а и основные операции.", "home.learnEth1Desc": "Введение в интерфейс Remix-а и основные операции.",
@ -65,5 +70,8 @@
"home.resources": "Источники", "home.resources": "Источники",
"home.connectToLocalhost": "Подключиться к локальному хосту", "home.connectToLocalhost": "Подключиться к локальному хосту",
"home.seeAllTutorials": "Посмотреть все уроки", "home.seeAllTutorials": "Посмотреть все уроки",
"home.maintainedByRemix": "Поддерживается Remix" "home.maintainedByRemix": "Поддерживается Remix",
"home.gitCloneTooltip": "Клонировать репозиторий Github в новую рабочую область",
"home.gistTooltip": "Открыть репозиторий Gist",
"home.newFileTooltip": "Добавить новый файл в рабочую область"
} }

@ -35,7 +35,8 @@ const profile = {
'setEnvironmentMode', 'setEnvironmentMode',
'clearAllInstances', 'clearAllInstances',
'addInstance', 'addInstance',
'resolveContractAndAddInstance' 'resolveContractAndAddInstance',
'showPluginDetails'
] ]
} }
@ -87,6 +88,10 @@ export class RunTab extends ViewPlugin {
}) })
} }
showPluginDetails() {
return profile
}
async setEnvironmentMode(env) { async setEnvironmentMode(env) {
const canCall = await this.askUserPermission('setEnvironmentMode', 'change the environment used') const canCall = await this.askUserPermission('setEnvironmentMode', 'change the environment used')
if (canCall) { if (canCall) {

@ -3,6 +3,8 @@ import React from 'react'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import '../remix-ui-plugin-manager.css' import '../remix-ui-plugin-manager.css'
import { CustomTooltip } from '@remix-ui/helper' import { CustomTooltip } from '@remix-ui/helper'
const _paq = (window._paq = window._paq || [])
interface PluginCardProps { interface PluginCardProps {
profile: any profile: any
buttonText: string buttonText: string
@ -85,6 +87,7 @@ function ActivePluginCard({ profile, buttonText, deactivatePlugin }: PluginCardP
> >
<button <button
onClick={() => { onClick={() => {
_paq.push(['trackEvent', 'pluginManager', 'deactivateBtn', 'deactivate btn ' + profile.name])
deactivatePlugin(profile.name) deactivatePlugin(profile.name)
}} }}
className="btn btn-secondary btn-sm" className="btn btn-secondary btn-sm"

@ -5,6 +5,8 @@ import { FormattedMessage, useIntl } from 'react-intl'
import '../remix-ui-plugin-manager.css' import '../remix-ui-plugin-manager.css'
import { CustomTooltip } from '@remix-ui/helper' import { CustomTooltip } from '@remix-ui/helper'
import { onLineContext } from '@remix-ui/app' import { onLineContext } from '@remix-ui/app'
const _paq = (window._paq = window._paq || [])
interface PluginCardProps { interface PluginCardProps {
profile: any profile: any
buttonText: string buttonText: string
@ -103,6 +105,7 @@ function InactivePluginCard({ profile, buttonText, activatePlugin }: PluginCardP
{!canBeActivated ? <button className="btn btn-secondary btn-sm">{intl.formatMessage({ id: 'pluginManager.UnavailableOffline' })}</button> : ( {!canBeActivated ? <button className="btn btn-secondary btn-sm">{intl.formatMessage({ id: 'pluginManager.UnavailableOffline' })}</button> : (
<button <button
onClick={() => { onClick={() => {
_paq.push(['trackEvent', 'pluginManager', 'activateBtn', 'activate btn' + profile.name])
activatePlugin(profile.name) activatePlugin(profile.name)
}} }}
className="btn btn-success btn-sm" className="btn btn-success btn-sm"

@ -0,0 +1,265 @@
export type ChainInfo = {
id: number | string
name: string
}
export type ChainCompatibleInfo = {
chain: ChainInfo
minCompilerVersion: string
evmVersion: HardFork
}
export type HardFork =
| 'cancun'
| 'shanghai'
| 'paris'
| 'london'
| 'berlin'
| 'istanbul'
| 'petersburg'
| 'constantinople'
| 'byzantium'
| 'spuriousDragon'
| 'tangerineWhistle'
| 'homestead'
export const evmMap: Map<HardFork, { chainId: ChainInfo[], minCompilerVersion: string }> = new Map([
['cancun', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" },
{ id: 5, name: "Goerli" },
{ id: 10, name: "Optimism" },
{ id: 56, name: "BNB Smart Chain Mainnet" },
{ id: 100, name: "Gnosis Chain" },
{ id: 137, name: "Polygon Mainnet" },
{ id: 250, name: "Fantom Opera" },
{ id: 300, name: "zkSync Era Mainnet" },
{ id: 42161, name: "Arbitrum One" },
{ id: 42170, name: "Arbitrum Nova" },
{ id: 43114, name: "Avalanche C-Chain" },
{ id: 44787, name: "Celo Alfajores Testnet" },
{ id: 59144, name: "Linea Mainnet" },
{ id: 59141, name: "Linea Testnet" },
{ id: 421614, name: "Arbitrum Sepolia" },
{ id: 534352, name: "Scroll" },
{ id: 11155111, name: "Sepolia" }
],
minCompilerVersion: "0.8.24+commit.e11b9ed9",
evmVersion: 'cancun'
}],
['shanghai', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" },
{ id: 5, name: "Goerli" },
{ id: 10, name: "Optimism" },
{ id: 30, name: "Rootstock Mainnet" },
{ id: 56, name: "BNB Smart Chain Mainnet" },
{ id: 100, name: "Gnosis Chain" },
{ id: 137, name: "Polygon Mainnet" },
{ id: 250, name: "Fantom Opera" },
{ id: 300, name: "zkSync Era Mainnet" },
{ id: 302, name: "zkSync Era Testnet" },
{ id: 314, name: "Filecoin - Mainnet" },
{ id: 324, name: "zkSync Era Mainnet" },
{ id: 369, name: "PulseChain" },
{ id: 388, name: "HALO Mainnet" },
{ id: 1101, name: "Polygon zkEVM" },
{ id: 1088, name: "Metis Andromeda Mainnet" },
{ id: 1284, name: "Moonbeam" },
{ id: 2000, name: "Dogechain Mainnet" },
{ id: 42161, name: "Arbitrum One" },
{ id: 42170, name: "Arbitrum Nova" },
{ id: 44787, name: "Celo Alfajores Testnet" },
{ id: 59144, name: "Linea Mainnet" },
{ id: 59141, name: "Linea Testnet" },
{ id: 59902, name: "Metis Sepolia Testnet" },
{ id: 421614, name: "Arbitrum Sepolia" },
{ id: 534352, name: "Scroll" },
{ id: 11155111, name: "Sepolia" },
{ id: 11155420, name: "Optimism Sepolia Testnet" },
{ id: 1666600000, name: "Harmony Mainnet Shard 0" }
],
minCompilerVersion: "0.8.20+commit.a1b79de6",
evmVersion: 'shanghai'
}],
['paris', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" },
{ id: 5, name: "Goerli" },
{ id: 10, name: "Optimism" },
{ id: 30, name: "Rootstock Mainnet" },
{ id: 56, name: "BNB Smart Chain Mainnet" },
{ id: 100, name: "Gnosis Chain" },
{ id: 137, name: "Polygon Mainnet" },
{ id: 250, name: "Fantom Opera" },
{ id: 300, name: "zkSync Era Mainnet" },
{ id: 302, name: "zkSync Era Testnet" },
{ id: 314, name: "Filecoin - Mainnet" },
{ id: 324, name: "zkSync Era Mainnet" },
{ id: 369, name: "PulseChain" },
{ id: 388, name: "HALO Mainnet" },
{ id: 1088, name: "Metis Andromeda Mainnet" },
{ id: 1101, name: "Polygon zkEVM" },
{ id: 1284, name: "Moonbeam" },
{ id: 2000, name: "Dogechain Mainnet" },
{ id: 42220, name: "Celo Mainnet" },
{ id: 42161, name: "Arbitrum One" },
{ id: 42170, name: "Arbitrum Nova" },
{ id: 44787, name: "Celo Alfajores Testnet" },
{ id: 59144, name: "Linea Mainnet" },
{ id: 59141, name: "Linea Testnet" },
{ id: 59902, name: "Metis Sepolia Testnet" },
{ id: 421614, name: "Arbitrum Sepolia" },
{ id: 534352, name: "Scroll" },
{ id: 11155111, name: "Sepolia" },
{ id: 11155420, name: "Optimism Sepolia Testnet" },
{ id: 1666600000, name: "Harmony Mainnet Shard 0" }
],
minCompilerVersion: "0.8.18+commit.87f61d96",
evmVersion: 'paris'
}],
['london', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" },
{ id: 5, name: "Goerli" },
{ id: 10, name: "Optimism" },
{ id: 25, name: "Cronos Mainnet" },
{ id: 30, name: "Rootstock Mainnet" },
{ id: 56, name: "BNB Smart Chain Mainnet" },
{ id: 137, name: "Polygon Mainnet" },
{ id: 250, name: "Fantom Opera" },
{ id: 1280, name: "HALO Mainnet" },
{ id: 42161, name: "Arbitrum One" },
{ id: 42170, name: "Arbitrum Nova" },
{ id: 42220, name: "Celo Mainnet" },
{ id: 59144, name: "Linea Mainnet" },
{ id: 59141, name: "Linea Testnet" },
{ id: 11155111, name: "Sepolia" },
],
minCompilerVersion: "0.8.7+commit.e28d00a7",
evmVersion: 'london'
}],
['berlin', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" },
{ id: 5, name: "Goerli" },
{ id: 10, name: "Optimism" },
{ id: 25, name: "Cronos Mainnet" },
{ id: 30, name: "Rootstock Mainnet" },
{ id: 56, name: "BNB Smart Chain Mainnet" },
{ id: 137, name: "Polygon Mainnet" },
{ id: 250, name: "Fantom Opera" },
{ id: 1280, name: "HALO Mainnet" },
{ id: 42161, name: "Arbitrum One" },
{ id: 42170, name: "Arbitrum Nova" },
{ id: 42220, name: "Celo Mainnet" },
{ id: 59144, name: "Linea Mainnet" },
{ id: 59141, name: "Linea Testnet" },
{ id: 11155111, name: "Sepolia" }
],
minCompilerVersion: "0.8.5+commit.a4f2e591",
evmVersion: 'berlin'
}],
['istanbul', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" },
{ id: 5, name: "Goerli" },
{ id: 10, name: "Optimism" },
{ id: 25, name: "Cronos Mainnet" },
{ id: 30, name: "Rootstock Mainnet" },
{ id: 56, name: "BNB Smart Chain Mainnet" },
{ id: 137, name: "Polygon Mainnet" },
{ id: 250, name: "Fantom Opera" },
{ id: 1280, name: "HALO Mainnet" },
{ id: 42161, name: "Arbitrum One" },
{ id: 42170, name: "Arbitrum Nova" },
{ id: 42220, name: "Celo Mainnet" },
{ id: 59144, name: "Linea Mainnet" },
{ id: 59141, name: "Linea Testnet" },
{ id: 11155111, name: "Sepolia" }
],
minCompilerVersion: "0.5.14+commit.01f1aaa4",
evmVersion: 'istanbul'
}],
['petersburg', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" },
{ id: 5, name: "Goerli" },
{ id: 11155111, name: "Sepolia" }
],
minCompilerVersion: "0.5.5+commit.47a71e8f",
evmVersion: 'petersburg'
}],
['constantinople', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" },
{ id: 5, name: "Goerli" },
{ id: 11155111, name: "Sepolia" }
],
minCompilerVersion: "0.5.5+commit.47a71e8f",
evmVersion: 'constantinople'
}],
['byzantium', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" }
],
minCompilerVersion: "0.4.21+commit.dfe3193c",
evmVersion: 'byzantium'
}],
['spuriousDragon', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" }
],
minCompilerVersion: "0.4.9+commit.364da425",
evmVersion: 'spuriousDragon'
}],
['tangerineWhistle', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" }
],
minCompilerVersion: "0.4.0+commit.acd334c9",
evmVersion: 'tangerineWhistle'
}],
['homestead', {
chainId: [
{ id: 1, name: "Ethereum Mainnet" },
{ id: 5, name: "Goerli" },
{ id: 11155111, name: "Sepolia" }
],
minCompilerVersion: "0.1.2+commit.d0d36e3",
evmVersion: 'homestead'
}],
])
export function getCompatibleChains(fork: HardFork): ChainInfo[] {
const forkData = evmMap.get(fork)
return forkData ? forkData.chainId : []
}
export function isChainCompatible(fork: HardFork, chainId: number): boolean {
const compatibleChains = getCompatibleChains(fork)
return compatibleChains.some(chain => chain.id === chainId)
}
export function isChainCompatibleWithAnyFork(chainId: number, forks: HardFork[]): boolean {
return forks.some(fork => isChainCompatible(fork, chainId))
}
export function getCompatibleChain(
fork: HardFork,
chainId: number
): ChainCompatibleInfo | undefined {
for (const [forkKey, forkData] of evmMap) {
const compatibleChain = forkData.chainId.find(chain => chain.id === chainId)
if (compatibleChain) {
return {
chain: compatibleChain,
minCompilerVersion: forkData.minCompilerVersion,
evmVersion: forkKey
}
}
}
return undefined;
}

@ -462,6 +462,7 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
<div> <div>
<ContractGUI <ContractGUI
title={intl.formatMessage({ id: 'udapp.deploy' })} title={intl.formatMessage({ id: 'udapp.deploy' })}
getCompilerDetails={props.getCompilerDetails}
isDeploy={true} isDeploy={true}
deployOption={deployOptions[currentFile] && deployOptions[currentFile][currentContract] ? deployOptions[currentFile][currentContract].options : null} deployOption={deployOptions[currentFile] && deployOptions[currentFile][currentContract] ? deployOptions[currentFile][currentContract].options : null}
initializerOptions={ initializerOptions={
@ -481,6 +482,10 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
solcVersion={props.solCompilerVersion} solcVersion={props.solCompilerVersion}
setSolcVersion={props.setCompilerVersion} setSolcVersion={props.setCompilerVersion}
getVersion={props.getCompilerVersion} getVersion={props.getCompilerVersion}
evmCheckComplete={props.evmCheckComplete}
setEvmCheckComplete={props.setEvmCheckComplete}
plugin={props.plugin}
runTabState={props.runTabState}
/> />
<div className="d-flex py-1 align-items-center custom-control custom-checkbox"> <div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input <input

@ -6,6 +6,7 @@ import { ContractGUIProps } from '../types'
import { CopyToClipboard } from '@remix-ui/clipboard' import { CopyToClipboard } from '@remix-ui/clipboard'
import { CustomTooltip, ProxyAddressToggle, ProxyDropdownMenu, shortenDate, shortenProxyAddress, unavailableProxyLayoutMsg, upgradeReportMsg } from '@remix-ui/helper' import { CustomTooltip, ProxyAddressToggle, ProxyDropdownMenu, shortenDate, shortenProxyAddress, unavailableProxyLayoutMsg, upgradeReportMsg } from '@remix-ui/helper'
import { Dropdown } from 'react-bootstrap' import { Dropdown } from 'react-bootstrap'
import { getCompatibleChains, isChainCompatible, isChainCompatibleWithAnyFork } from '../actions/evmmap'
const txFormat = remixLib.execution.txFormat const txFormat = remixLib.execution.txFormat
const txHelper = remixLib.execution.txHelper const txHelper = remixLib.execution.txHelper
@ -171,8 +172,7 @@ export function ContractGUI(props: ContractGUIProps) {
} }
} }
const handleActionClick = async () => { const handleDeploy = async () => {
props.getVersion()
if (deployState.deploy) { if (deployState.deploy) {
const proxyInitializeString = getMultiValsString(initializeFields.current) const proxyInitializeString = getMultiValsString(initializeFields.current)
props.clickCallBack(props.initializerOptions.inputs.inputs, proxyInitializeString, ['Deploy with Proxy']) props.clickCallBack(props.initializerOptions.inputs.inputs, proxyInitializeString, ['Deploy with Proxy'])
@ -224,6 +224,23 @@ export function ContractGUI(props: ContractGUIProps) {
} }
} }
const handleActionClick = async () => {
props.getVersion()
if (props.runTabState.selectExEnv.toLowerCase().startsWith('vm-') || props.runTabState.selectExEnv.toLowerCase().includes('basic-http-provider')) {
await handleDeploy()
} else {
const status = await props.getCompilerDetails()
if (status === 'Failed') {
props.plugin.call('terminal', 'log', { type: 'log', value: 'Consider opening an issue to update our internal store with your desired chainId.' })
return
}
if (props.evmCheckComplete) {
await handleDeploy()
}
}
}
const handleBasicInput = (e) => { const handleBasicInput = (e) => {
const value = e.target.value const value = e.target.value

@ -1,5 +1,5 @@
// eslint-disable-next-line no-use-before-define // eslint-disable-next-line no-use-before-define
import React from 'react' import React, { useEffect } from 'react'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import { EnvironmentProps, Provider } from '../types' import { EnvironmentProps, Provider } from '../types'
import { Dropdown } from 'react-bootstrap' import { Dropdown } from 'react-bootstrap'
@ -66,7 +66,7 @@ export function EnvironmentUI(props: EnvironmentProps) {
{ (props.providers.providerList.filter((provider) => { return provider.isInjected })).map(({ name, displayName }) => ( { (props.providers.providerList.filter((provider) => { return provider.isInjected })).map(({ name, displayName }) => (
<Dropdown.Item <Dropdown.Item
key={name} key={name}
onClick={() => { onClick={async () => {
handleChangeExEnv(name) handleChangeExEnv(name)
}} }}
data-id={`dropdown-item-${name}`} data-id={`dropdown-item-${name}`}

@ -62,6 +62,8 @@ export function InstanceContainerUI(props: InstanceContainerProps) {
editInstance={props.editInstance} editInstance={props.editInstance}
solcVersion={props.solcVersion} solcVersion={props.solcVersion}
getVersion={props.getVersion} getVersion={props.getVersion}
getCompilerDetails={props.getCompilerDetails}
runTabState={props.runTabState}
/> />
) )
})} })}

@ -1,5 +1,5 @@
// eslint-disable-next-line no-use-before-define // eslint-disable-next-line no-use-before-define
import React from 'react' import React, { useEffect } from 'react'
import { SettingsProps } from '../types' import { SettingsProps } from '../types'
import { EnvironmentUI } from './environment' import { EnvironmentUI } from './environment'
import { NetworkUI } from './network' import { NetworkUI } from './network'
@ -12,7 +12,7 @@ export function SettingsUI(props: SettingsProps) {
return ( return (
<div className="udapp_settings"> <div className="udapp_settings">
<EnvironmentUI selectedEnv={props.selectExEnv} providers={props.providers} setExecutionContext={props.setExecutionContext} /> <EnvironmentUI runTabPlugin={props.runTabPlugin} selectedEnv={props.selectExEnv} providers={props.providers} setExecutionContext={props.setExecutionContext} checkSelectionCorrectness={props.EvaluateEnvironmentSelection} />
<NetworkUI networkName={props.networkName} /> <NetworkUI networkName={props.networkName} />
<AccountUI <AccountUI
addFile={props.addFile} addFile={props.addFile}

@ -326,6 +326,10 @@ export function UniversalDappUI(props: UdappProps) {
<div key={index}> <div key={index}>
<ContractGUI <ContractGUI
getVersion={props.getVersion} getVersion={props.getVersion}
getCompilerDetails={props.getCompilerDetails}
evmCheckComplete={false}
plugin={props.plugin}
runTabState={props.runTabState}
funcABI={funcABI} funcABI={funcABI}
clickCallBack={(valArray: {name: string; type: string}[], inputsValues: string) => { clickCallBack={(valArray: {name: string; type: string}[], inputsValues: string) => {
runTransaction(lookupOnly, funcABI, valArray, inputsValues, index) runTransaction(lookupOnly, funcABI, valArray, inputsValues, index)

@ -1,5 +1,5 @@
// eslint-disable-next-line no-use-before-define // eslint-disable-next-line no-use-before-define
import React, { Fragment, useEffect, useReducer, useState } from 'react' import React, { Fragment, useCallback, useEffect, useReducer, useState } from 'react'
import semver from 'semver' import semver from 'semver'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import { ModalDialog } from '@remix-ui/modal-dialog' import { ModalDialog } from '@remix-ui/modal-dialog'
@ -56,6 +56,9 @@ import { PassphrasePrompt } from './components/passphrase'
import { MainnetPrompt } from './components/mainnet' import { MainnetPrompt } from './components/mainnet'
import { ScenarioPrompt } from './components/scenario' import { ScenarioPrompt } from './components/scenario'
import { setIpfsCheckedState, setRemixDActivated } from './actions/payload' import { setIpfsCheckedState, setRemixDActivated } from './actions/payload'
import { ChainCompatibleInfo, getCompatibleChain, getCompatibleChains, HardFork, isChainCompatible, isChainCompatibleWithAnyFork } from './actions/evmmap'
export type CheckStatus = 'Passed' | 'Failed'
export function RunTabUI(props: RunTabProps) { export function RunTabUI(props: RunTabProps) {
const { plugin } = props const { plugin } = props
@ -85,6 +88,7 @@ export function RunTabUI(props: RunTabProps) {
const REACT_API = { runTab } const REACT_API = { runTab }
const currentfile = plugin.config.get('currentFile') const currentfile = plugin.config.get('currentFile')
const [solcVersion, setSolcVersion] = useState<{version: string, canReceive: boolean}>({ version: '', canReceive: true }) const [solcVersion, setSolcVersion] = useState<{version: string, canReceive: boolean}>({ version: '', canReceive: true })
const [evmCheckComplete, setEvmCheckComplete] = useState(false)
const getVersion = () => { const getVersion = () => {
let version = '0.8.25' let version = '0.8.25'
@ -102,6 +106,67 @@ export function RunTabUI(props: RunTabProps) {
} }
} }
const getCompilerDetails = async () => await checkEvmChainCompatibility()
const returnCompatibleChain = async (evmVersion: HardFork, targetChainId: number) => {
const result = getCompatibleChain(evmVersion ?? 'paris', targetChainId) // using paris evm as a default fallback version
return result
}
const checkEvmChainCompatibilityOkFunction = async (fetchDetails: ChainCompatibleInfo) => {
const compilerParams = {
evmVersion: fetchDetails.evmVersion,
optimize: false,
language: 'Solidity',
runs: '200',
version: fetchDetails.minCompilerVersion
}
await plugin.call('solidity', 'setCompilerConfig', compilerParams)
const currentFile = await plugin.call('fileManager', 'getCurrentFile')
await plugin.call('solidity', 'compile', currentFile)
setEvmCheckComplete(true)
}
const checkEvmChainCompatibility = async () => {
const fetchDetails = await plugin.call('solidity', 'getCompilerQueryParameters')
const compilerState = await plugin.call('solidity', 'getCompilerState')
// if no contract file is open, don't do anything
if (compilerState.target !== null) {
const targetChainId = runTab.chainId
const ideDefault = fetchDetails && fetchDetails.evmVersion !== null ? fetchDetails.evmVersion : 'cancun'
const IsCompatible = isChainCompatible(ideDefault, targetChainId)
const chain = await returnCompatibleChain(ideDefault, targetChainId)
if (chain === undefined) {
//show modal
plugin.call('terminal', 'log', { type: 'log', value: 'No compatible chain found for the selected EVM version.' })
return 'Failed'
} else {
if (!IsCompatible) {
//show modal
plugin.call('notification', 'modal', {
id: 'evm-chainId-incompatible',
title: 'Incompatible EVM for the selected chain',
message: <div className="px-3">
<p>The smart contract has not been compiled with an EVM version that is compatible with the selected chain.</p>
<ul className="px-3">
<li>Have Remix switch to a compatible EVM version for this chain and recompile the contract.</li>
<li>Cancel to keep the current EVM version.</li>
</ul>
<p>To manually change the EVM version, go to the Advanced Configurations section of the Solidity compiler.</p>
</div>,
modalType: 'modal',
okLabel: 'Switch EVM and Recompile',
cancelLabel: 'Cancel',
okFn: () => checkEvmChainCompatibilityOkFunction(chain),
cancelFn: () => {}
})
}
}
return 'Passed'
}
}
useEffect(() => { useEffect(() => {
if (!props.initialState) { if (!props.initialState) {
initRunTab(plugin, true)(dispatch) initRunTab(plugin, true)(dispatch)
@ -285,6 +350,7 @@ export function RunTabUI(props: RunTabProps) {
networkName={runTab.networkName} networkName={runTab.networkName}
personalMode={runTab.personalMode} personalMode={runTab.personalMode}
selectExEnv={runTab.selectExEnv} selectExEnv={runTab.selectExEnv}
EvaluateEnvironmentSelection={checkEvmChainCompatibility}
accounts={runTab.accounts} accounts={runTab.accounts}
setAccount={setAccountAddress} setAccount={setAccountAddress}
setUnit={setUnitValue} setUnit={setUnitValue}
@ -294,6 +360,7 @@ export function RunTabUI(props: RunTabProps) {
gasLimit={runTab.gasLimit} gasLimit={runTab.gasLimit}
setGasFee={setGasFeeAmount} setGasFee={setGasFeeAmount}
providers={runTab.providers} providers={runTab.providers}
runTabPlugin={plugin}
setExecutionContext={setExecutionEnvironment} setExecutionContext={setExecutionEnvironment}
createNewBlockchainAccount={createNewAddress} createNewBlockchainAccount={createNewAddress}
setPassphrase={setPassphraseModal} setPassphrase={setPassphraseModal}
@ -331,6 +398,11 @@ export function RunTabUI(props: RunTabProps) {
solCompilerVersion={solcVersion} solCompilerVersion={solcVersion}
setCompilerVersion={setSolcVersion} setCompilerVersion={setSolcVersion}
getCompilerVersion={getVersion} getCompilerVersion={getVersion}
getCompilerDetails={getCompilerDetails}
evmCheckComplete={evmCheckComplete}
setEvmCheckComplete={setEvmCheckComplete}
plugin={plugin}
runTabState={runTab}
/> />
<RecorderUI <RecorderUI
plugin={plugin} plugin={plugin}
@ -345,6 +417,8 @@ export function RunTabUI(props: RunTabProps) {
/> />
<InstanceContainerUI <InstanceContainerUI
plugin={plugin} plugin={plugin}
getCompilerDetails={getCompilerDetails}
runTabState={runTab}
instances={runTab.instances} instances={runTab.instances}
clearInstances={removeInstances} clearInstances={removeInstances}
unpinInstance={unpinPinnedInstance} unpinInstance={unpinPinnedInstance}

@ -1,9 +1,10 @@
import { Ref } from 'react' import { Dispatch, Ref } from 'react'
import { CompilerAbstract } from '@remix-project/remix-solidity' import { CompilerAbstract } from '@remix-project/remix-solidity'
import { ContractData, FuncABI, OverSizeLimit } from '@remix-project/core-plugin' import { ContractData, FuncABI, OverSizeLimit } from '@remix-project/core-plugin'
import { RunTab } from './run-tab' import { RunTab } from './run-tab'
import { SolcInput, SolcOutput } from '@openzeppelin/upgrades-core' import { SolcInput, SolcOutput } from '@openzeppelin/upgrades-core'
import { LayoutCompatibilityReport } from '@openzeppelin/upgrades-core/dist/storage/report' import { LayoutCompatibilityReport } from '@openzeppelin/upgrades-core/dist/storage/report'
import { CheckStatus } from '../run-tab'
export interface RunTabProps { export interface RunTabProps {
plugin: RunTab, plugin: RunTab,
initialState?: RunTabState initialState?: RunTabState
@ -123,7 +124,9 @@ export interface RunTabState {
} }
export interface SettingsProps { export interface SettingsProps {
runTabPlugin: RunTab,
selectExEnv: string, selectExEnv: string,
EvaluateEnvironmentSelection: any
accounts: { accounts: {
loadedAccounts: Record<string, any>, loadedAccounts: Record<string, any>,
selectedAccount: string, selectedAccount: string,
@ -158,6 +161,8 @@ export interface SettingsProps {
} }
export interface EnvironmentProps { export interface EnvironmentProps {
checkSelectionCorrectness: any
runTabPlugin: RunTab,
selectedEnv: string, selectedEnv: string,
providers: { providers: {
providerList: Provider[], providerList: Provider[],
@ -228,6 +233,11 @@ export type MainnetPrompt = (
) => JSX.Element ) => JSX.Element
export interface ContractDropdownProps { export interface ContractDropdownProps {
getCompilerDetails: () => Promise<CheckStatus>
evmCheckComplete?: boolean,
setEvmCheckComplete?: Dispatch<React.SetStateAction<boolean>>,
plugin: RunTab,
runTabState: RunTabState
selectedAccount: string, selectedAccount: string,
exEnvironment: string, exEnvironment: string,
contracts: { contracts: {
@ -292,6 +302,8 @@ export interface RecorderProps {
} }
export interface InstanceContainerProps { export interface InstanceContainerProps {
getCompilerDetails: () => Promise<CheckStatus>
runTabState: RunTabState
instances: { instances: {
instanceList: { instanceList: {
contractData?: ContractData, contractData?: ContractData,
@ -373,6 +385,11 @@ export interface DeployOptions {
} }
export interface ContractGUIProps { export interface ContractGUIProps {
getCompilerDetails: () => Promise<CheckStatus>
evmCheckComplete?: boolean,
setEvmCheckComplete?: React.Dispatch<React.SetStateAction<boolean>>,
plugin: RunTab,
runTabState: RunTabState
title?: string, title?: string,
funcABI: FuncABI, funcABI: FuncABI,
inputs: string, inputs: string,
@ -412,6 +429,8 @@ export interface MainnetProps {
} }
export interface UdappProps { export interface UdappProps {
getCompilerDetails: () => Promise<CheckStatus>
runTabState: RunTabState
instance: { instance: {
contractData?: ContractData, contractData?: ContractData,
address: string, address: string,

@ -473,7 +473,7 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
<span <span
data-id="remix_ai_docs" data-id="remix_ai_docs"
id="remix_ai_docs" id="remix_ai_docs"
className="btn pl-2 pr-0 py-0 d-inline ai-docs" className="btn pl-2 pr-0 py-0 d-inline ai-docs text-dark"
role='link' role='link'
onClick={()=>{ onClick={()=>{
window.open("https://remix-ide.readthedocs.io/en/latest/ai.html") window.open("https://remix-ide.readthedocs.io/en/latest/ai.html")

@ -974,7 +974,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
> >
{compileTabLogic.evmVersions.map((version, index) => ( {compileTabLogic.evmVersions.map((version, index) => (
<option key={index} data-id={state.evmVersion === version ? 'selected' : ''} value={version}> <option key={index} data-id={state.evmVersion === version ? 'selected' : ''} value={version}>
{version} {version === 'default' ? `default (${compileTabLogic.evmVersions[index + 1]})` : version}
</option> </option>
))} ))}
</select> </select>

Loading…
Cancel
Save