From ab1bf04e6180f180dbeb6eb4cb5db56248074fe5 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 4 Jul 2022 19:23:02 +0200 Subject: [PATCH 01/11] add L2 networks --- apps/remix-ide/src/app.js | 6 ++ .../src/app/tabs/abstract-provider.tsx | 8 +-- .../tabs/injected-arbitrum-one-provider.tsx | 21 ++++++ .../app/tabs/injected-optimism-provider.tsx | 21 ++++++ .../src/app/tabs/injected-provider.tsx | 69 +++++++++++++++++++ apps/remix-ide/src/app/udapp/run-tab.js | 34 +++++++++ .../src/blockchain/execution-context.js | 20 ++++-- apps/remix-ide/src/remixAppManager.js | 2 +- 8 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 apps/remix-ide/src/app/tabs/injected-arbitrum-one-provider.tsx create mode 100644 apps/remix-ide/src/app/tabs/injected-optimism-provider.tsx create mode 100644 apps/remix-ide/src/app/tabs/injected-provider.tsx diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index 464356b902..d9c93fd4f6 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -29,6 +29,8 @@ import { HardhatProvider } from './app/tabs/hardhat-provider' import { GanacheProvider } from './app/tabs/ganache-provider' import { FoundryProvider } from './app/tabs/foundry-provider' import { ExternalHttpProvider } from './app/tabs/external-http-provider' +import { Injected0ptimismProvider } from './app/tabs/injected-optimism-provider' +import { InjectedArbitrumOneProvider } from './app/tabs/injected-arbitrum-one-provider' const isElectron = require('is-electron') @@ -181,6 +183,8 @@ class AppComponent { const ganacheProvider = new GanacheProvider(blockchain) const foundryProvider = new FoundryProvider(blockchain) const externalHttpProvider = new ExternalHttpProvider(blockchain) + const injected0ptimismProvider = new Injected0ptimismProvider(blockchain) + const injectedArbitrumOneProvider = new InjectedArbitrumOneProvider(blockchain) // ----------------- convert offset to line/column service ----------- const offsetToLineColumnConverter = new OffsetToLineColumnConverter() Registry.getInstance().put({ @@ -239,6 +243,8 @@ class AppComponent { ganacheProvider, foundryProvider, externalHttpProvider, + injected0ptimismProvider, + injectedArbitrumOneProvider, this.walkthroughService, search ]) diff --git a/apps/remix-ide/src/app/tabs/abstract-provider.tsx b/apps/remix-ide/src/app/tabs/abstract-provider.tsx index ff924a618a..31b1a4e317 100644 --- a/apps/remix-ide/src/app/tabs/abstract-provider.tsx +++ b/apps/remix-ide/src/app/tabs/abstract-provider.tsx @@ -3,21 +3,21 @@ import { AppModal, AlertModal, ModalTypes } from '@remix-ui/app' import { Blockchain } from '../../blockchain/blockchain' import { ethers } from 'ethers' -type JsonDataRequest = { +export type JsonDataRequest = { id: number, jsonrpc: string // version method: string, params: Array, } -type JsonDataResult = { +export type JsonDataResult = { id: number, jsonrpc: string // version result: any } -type RejectRequest = (error: Error) => void -type SuccessRequest = (data: JsonDataResult) => void +export type RejectRequest = (error: Error) => void +export type SuccessRequest = (data: JsonDataResult) => void export abstract class AbstractProvider extends Plugin { provider: ethers.providers.JsonRpcProvider diff --git a/apps/remix-ide/src/app/tabs/injected-arbitrum-one-provider.tsx b/apps/remix-ide/src/app/tabs/injected-arbitrum-one-provider.tsx new file mode 100644 index 0000000000..283dacdf24 --- /dev/null +++ b/apps/remix-ide/src/app/tabs/injected-arbitrum-one-provider.tsx @@ -0,0 +1,21 @@ +import * as packageJson from '../../../../../package.json' +import { InjectedProvider } from './injected-provider' + +const profile = { + name: 'injected-arbitrum-one-provider', + displayName: 'Injected Arbitrum One Provider', + kind: 'provider', + description: 'injected Arbitrum One Provider', + methods: ['sendAsync'], + version: packageJson.version +} + +export class InjectedArbitrumOneProvider extends InjectedProvider { + + constructor () { + super(profile) + this.chainName = 'Arbitrum One' + this.chainId = '0xa4b1' + this.rpcUrls = ['https://arb1.arbitrum.io/rpc'] + } +} \ No newline at end of file diff --git a/apps/remix-ide/src/app/tabs/injected-optimism-provider.tsx b/apps/remix-ide/src/app/tabs/injected-optimism-provider.tsx new file mode 100644 index 0000000000..64c8c4e91a --- /dev/null +++ b/apps/remix-ide/src/app/tabs/injected-optimism-provider.tsx @@ -0,0 +1,21 @@ +import * as packageJson from '../../../../../package.json' +import { InjectedProvider } from './injected-provider' + +const profile = { + name: 'injected-optimism-provider', + displayName: 'Injected Optimism Provider', + kind: 'provider', + description: 'injected Optimism Provider', + methods: ['sendAsync'], + version: packageJson.version +} + +export class Injected0ptimismProvider extends InjectedProvider { + + constructor () { + super(profile) + this.chainName = 'Optimism' + this.chainId = '0xa' + this.rpcUrls = ['https://mainnet.optimism.io'] + } +} \ No newline at end of file diff --git a/apps/remix-ide/src/app/tabs/injected-provider.tsx b/apps/remix-ide/src/app/tabs/injected-provider.tsx new file mode 100644 index 0000000000..a633c66a64 --- /dev/null +++ b/apps/remix-ide/src/app/tabs/injected-provider.tsx @@ -0,0 +1,69 @@ +import { Plugin } from '@remixproject/engine' +import { JsonDataRequest, RejectRequest, SuccessRequest } from './abstract-provider' +import { ethers } from 'ethers' +import Web3 from 'web3' + +export class InjectedProvider extends Plugin { + provider: any + chainName: string + chainId: string + rpcUrls: Array + + constructor (profile) { + super(profile) + this.provider = new Web3((window as any).ethereum) + } + + sendAsync (data: JsonDataRequest): Promise { + return new Promise((resolve, reject) => { + this.sendAsyncInternal(data, resolve, reject) + }) + } + + private async sendAsyncInternal (data: JsonDataRequest, resolve: SuccessRequest, reject: RejectRequest): Promise { + // Check the case where current environment is VM on UI and it still sends RPC requests + // This will be displayed on UI tooltip as 'cannot get account list: Environment Updated !!' + + try { + if ((window as any) && typeof (window as any).ethereum.enable === 'function') (window as any).ethereum.enable() + await addL2Network(this.chainName, this.chainId, this.rpcUrls) + const resultData = await this.provider.currentProvider.send(data.method, data.params) + resolve({ jsonrpc: '2.0', result: resultData.result, id: data.id }) + } catch (error) { + reject(error) + } + } +} + +export const addL2Network = async (chainName: string, chainId: string, rpcUrls: Array) => { + try { + await (window as any).ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: chainId }], + }); + } catch (switchError) { + // This error code indicates that the chain has not been added to MetaMask. + if (switchError.code === 4902) { + try { + await (window as any).ethereum.request({ + method: 'wallet_addEthereumChain', + params: [ + { + chainId: chainId, + chainName: chainName, + rpcUrls: rpcUrls, + }, + ], + }); + + await (window as any).ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: chainId }], + }); + } catch (addError) { + // handle "add" error + } + } + // handle other "switch" errors + } +} \ No newline at end of file diff --git a/apps/remix-ide/src/app/udapp/run-tab.js b/apps/remix-ide/src/app/udapp/run-tab.js index cf71ad3780..c9912ecb4c 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.js +++ b/apps/remix-ide/src/app/udapp/run-tab.js @@ -102,6 +102,7 @@ export class RunTab extends ViewPlugin { await this.call('blockchain', 'addProvider', { name: 'Hardhat Provider', + isInjected: false, provider: { async sendAsync (payload, callback) { try { @@ -116,6 +117,7 @@ export class RunTab extends ViewPlugin { await this.call('blockchain', 'addProvider', { name: 'Ganache Provider', + isInjected: false, provider: { async sendAsync (payload, callback) { try { @@ -130,6 +132,7 @@ export class RunTab extends ViewPlugin { await this.call('blockchain', 'addProvider', { name: 'Foundry Provider', + isInjected: false, provider: { async sendAsync (payload, callback) { try { @@ -144,6 +147,7 @@ export class RunTab extends ViewPlugin { await this.call('blockchain', 'addProvider', { name: 'Wallet Connect', + isInjected: false, provider: { async sendAsync (payload, callback) { try { @@ -169,6 +173,36 @@ export class RunTab extends ViewPlugin { } } }) + + await this.call('blockchain', 'addProvider', { + name: 'Optimism Provider', + isInjected: true, + provider: { + async sendAsync (payload, callback) { + try { + const result = await udapp.call('injected-optimism-provider', 'sendAsync', payload) + callback(null, result) + } catch (e) { + callback(e) + } + } + } + }) + + await this.call('blockchain', 'addProvider', { + name: 'Arbitrum One Provider', + isInjected: true, + provider: { + async sendAsync (payload, callback) { + try { + const result = await udapp.call('injected-arbitrum-one-provider', 'sendAsync', payload) + callback(null, result) + } catch (e) { + callback(e) + } + } + } + }) } writeFile (fileName, content) { diff --git a/apps/remix-ide/src/blockchain/execution-context.js b/apps/remix-ide/src/blockchain/execution-context.js index 95b4abe45d..b04e83d656 100644 --- a/apps/remix-ide/src/blockchain/execution-context.js +++ b/apps/remix-ide/src/blockchain/execution-context.js @@ -166,11 +166,21 @@ export class ExecutionContext { if (this.customNetWorks[context]) { var network = this.customNetWorks[context] - this.setProviderFromEndpoint(network.provider, { context: network.name }, (error) => { - if (error) infoCb(error) - cb() - }) - } + if (!this.customNetWorks[context].isInjected) { + this.setProviderFromEndpoint(network.provider, { context: network.name }, (error) => { + if (error) infoCb(error) + cb() + }) + } else { + // injected + this.askPermission() + this.executionContext = context + web3.setProvider(network.provider) + await this._updateChainContext() + this.event.trigger('contextChanged', [context]) + return cb() + } + } } currentblockGasLimit () { diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js index 9c00f8ab46..fbe147a67b 100644 --- a/apps/remix-ide/src/remixAppManager.js +++ b/apps/remix-ide/src/remixAppManager.js @@ -19,7 +19,7 @@ const sensitiveCalls = { } export function isNative(name) { - const nativePlugins = ['vyper', 'workshops', 'debugger', 'remixd', 'menuicons', 'solidity', 'solidity-logic', 'solidityStaticAnalysis', 'solidityUnitTesting', 'layout', 'notification', 'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider'] + const nativePlugins = ['vyper', 'workshops', 'debugger', 'remixd', 'menuicons', 'solidity', 'solidity-logic', 'solidityStaticAnalysis', 'solidityUnitTesting', 'layout', 'notification', 'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider', 'injected-optimism-provider', 'injected-arbitrum-one-provider'] return nativePlugins.includes(name) || requiredModules.includes(name) } From 084731705868fc45e0df831ec6e943b849b230f4 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 6 Jul 2022 09:39:32 +0200 Subject: [PATCH 02/11] move custom dropdown to helper --- libs/remix-ui/helper/src/index.ts | 3 ++- .../src/lib/components/custom-dropdown.tsx | 0 libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename libs/remix-ui/{workspace => helper}/src/lib/components/custom-dropdown.tsx (100%) diff --git a/libs/remix-ui/helper/src/index.ts b/libs/remix-ui/helper/src/index.ts index 36d73ef523..9f050ea8b8 100644 --- a/libs/remix-ui/helper/src/index.ts +++ b/libs/remix-ui/helper/src/index.ts @@ -1,3 +1,4 @@ export * from './lib/remix-ui-helper' export * from './lib/helper-components' -export * from './lib/components/PluginViewWrapper' \ No newline at end of file +export * from './lib/components/PluginViewWrapper' +export * from './lib/components/custom-dropdown' \ No newline at end of file diff --git a/libs/remix-ui/workspace/src/lib/components/custom-dropdown.tsx b/libs/remix-ui/helper/src/lib/components/custom-dropdown.tsx similarity index 100% rename from libs/remix-ui/workspace/src/lib/components/custom-dropdown.tsx rename to libs/remix-ui/helper/src/lib/components/custom-dropdown.tsx diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index 5302d907ed..0870442cb2 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef, useContext } from 'react' // eslint-disable-line import { Dropdown } from 'react-bootstrap' -import { CustomMenu, CustomToggle } from './components/custom-dropdown' +import { CustomMenu, CustomToggle } from '@remix-ui/helper' import { FileExplorer } from './components/file-explorer' // eslint-disable-line import { FileSystemContext } from './contexts' import './css/remix-ui-workspace.css' From 26901fc7fc4022a9e06f8bc34995023173c2a973 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 6 Jul 2022 10:02:55 +0200 Subject: [PATCH 03/11] use custom dropdown --- .../src/lib/components/environment.tsx | 60 +++++++++++++++---- libs/remix-ui/run-tab/src/lib/css/run-tab.css | 3 + 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index be6b4a3f94..0a311deb30 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -1,8 +1,13 @@ // eslint-disable-next-line no-use-before-define import React from 'react' import { EnvironmentProps } from '../types' +import { Dropdown } from 'react-bootstrap' +import { CustomMenu, CustomToggle } from '@remix-ui/helper' +import { OverlayTrigger, Tooltip } from 'react-bootstrap' // eslint-disable-line export function EnvironmentUI (props: EnvironmentProps) { + + const handleChangeExEnv = (env: string) => { const provider = props.providers.providerList.find(exEnv => exEnv.value === env) const fork = provider.fork // can be undefined if connected to an external source (web3 provider / injected) @@ -13,22 +18,55 @@ export function EnvironmentUI (props: EnvironmentProps) { props.setExecutionContext({ context, fork }) } + const currentProvider = props.providers.providerList.find(exEnv => exEnv.value === props.selectedEnv) + const bridges = { + 'Optimism Provider': 'https://www.optimism.io/apps/bridges', + 'Arbitrum One Provider': 'https://bridge.arbitrum.io/' + } + + + const isL2 = (provider) => provider && (provider.value === 'Optimism Provider' || provider.value === 'Arbitrum One Provider') return (
- + + + + { isL2(currentProvider) && 'L2 - '} + { currentProvider && currentProvider.content } + { currentProvider && bridges[currentProvider.value] && + Click here to open a bridge. + + }> + + } + + + { + props.providers.providerList.map(({ content, value }, index) => ( + { + handleChangeExEnv(value) + }} + data-id={`dropdown-item-${value}`} + > + { isL2({ value }) && 'L2 - ' }{ content } + + )) + } + +
diff --git a/libs/remix-ui/run-tab/src/lib/css/run-tab.css b/libs/remix-ui/run-tab/src/lib/css/run-tab.css index c4c65e4e01..2921381007 100644 --- a/libs/remix-ui/run-tab/src/lib/css/run-tab.css +++ b/libs/remix-ui/run-tab/src/lib/css/run-tab.css @@ -529,4 +529,7 @@ text-decoration: none; background-color: #007aa6; } +.udapp_selectExEnvOptions { + width: 100%; +} From bbd156c384b34ffcae3d25688297b2ef9ee91299 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 6 Jul 2022 12:24:07 +0200 Subject: [PATCH 04/11] fix tests --- .../src/commands/switchEnvironment.ts | 18 ++++++++++++++++++ apps/remix-ide-e2e/src/tests/ballot.test.ts | 5 +++-- .../src/tests/ballot_0_4_11.test.ts | 4 ++-- apps/remix-ide-e2e/src/tests/debugger.test.ts | 8 ++++---- apps/remix-ide-e2e/src/tests/plugin_api.ts | 4 ++-- apps/remix-ide-e2e/src/tests/providers.test.ts | 8 ++++---- .../src/tests/runAndDeploy.test.ts | 2 +- apps/remix-ide-e2e/src/tests/terminal.test.ts | 6 +++--- .../src/tests/transactionExecution.test.ts | 2 +- apps/remix-ide-e2e/src/types/index.d.ts | 1 + 10 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 apps/remix-ide-e2e/src/commands/switchEnvironment.ts diff --git a/apps/remix-ide-e2e/src/commands/switchEnvironment.ts b/apps/remix-ide-e2e/src/commands/switchEnvironment.ts new file mode 100644 index 0000000000..03564ced41 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/switchEnvironment.ts @@ -0,0 +1,18 @@ +import { NightwatchBrowser } from 'nightwatch' +import EventEmitter from 'events' + +class switchEnvironment extends EventEmitter { + command (this: NightwatchBrowser, provider: string): NightwatchBrowser { + this.api.waitForElementVisible('[data-id="settingsSelectEnvOptions"]') + .click('[data-id="settingsSelectEnvOptions"] button') + .waitForElementVisible(`[data-id="dropdown-item-${provider}"]`) + .click(`[data-id="dropdown-item-${provider}"]`) + .perform((done) => { + done() + this.emit('complete') + }) + return this + } +} + +module.exports = switchEnvironment diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index 9d2e9c5b07..0fd5fa1788 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -83,14 +83,15 @@ module.exports = { browser .openFile('Untitled.sol') .clickLaunchIcon('udapp') - .click('*[data-id="settingsSelectEnvOptions"] *[data-id="External Http Provider"]') - .waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]') + .switchEnvironment('web3') + .waitForElementPresent('[data-id="envNotification-modal-footer-ok-react"]') .execute(function () { const modal = document.querySelector('[data-id="basic-http-provider-modal-footer-ok-react"]') as any modal.click() }) .pause(5000) + .waitForElementContainsText('#selectExEnvOptions button', 'External HTTP Provider') .execute(function () { const env: any = document.getElementById('selectExEnvOptions') diff --git a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts index 95696e3882..afe6a8545b 100644 --- a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts @@ -78,8 +78,8 @@ module.exports = { browser .openFile('Untitled.sol') .clickLaunchIcon('udapp') - .click('*[data-id="settingsSelectEnvOptions"] *[data-id="External Http Provider"]') - .waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]') + .switchEnvironment('web3') + .waitForElementPresent('[data-id="envNotification-modal-footer-ok-react"]') .execute(function () { const modal = document.querySelector('[data-id="basic-http-provider-modal-footer-ok-react"]') as any diff --git a/apps/remix-ide-e2e/src/tests/debugger.test.ts b/apps/remix-ide-e2e/src/tests/debugger.test.ts index 9b8da7e7df..bc8db41a09 100644 --- a/apps/remix-ide-e2e/src/tests/debugger.test.ts +++ b/apps/remix-ide-e2e/src/tests/debugger.test.ts @@ -214,10 +214,10 @@ module.exports = { .setSolidityCompilerVersion('soljson-v0.8.7+commit.e28d00a7.js') .addFile('useDebugNodes.sol', sources[5]['useDebugNodes.sol']) // compile contract .clickLaunchIcon('udapp') - .click('*[data-id="settingsSelectEnvOptions"] *[data-id="External Http Provider"]') // select web3 provider with debug nodes URL - .clearValue('*[data-id="modalDialogCustomPromp"]') - .setValue('*[data-id="modalDialogCustomPromp"]', 'https://remix-rinkeby.ethdevops.io') - .modalFooterOKClick('basic-http-provider') + .switchEnvironment('web3') // select web3 provider with debug nodes URL + .clearValue('*[data-id="modalDialogCustomPromptText"]') + .setValue('*[data-id="modalDialogCustomPromptText"]', 'https://remix-rinkeby.ethdevops.io') + .modalFooterOKClick() .waitForElementPresent('*[title="Deploy - transact (not payable)"]', 65000) // wait for the compilation to succeed .clickLaunchIcon('debugger') .clearValue('*[data-id="debuggerTransactionInput"]') diff --git a/apps/remix-ide-e2e/src/tests/plugin_api.ts b/apps/remix-ide-e2e/src/tests/plugin_api.ts index f05a2fe130..c7ef41a231 100644 --- a/apps/remix-ide-e2e/src/tests/plugin_api.ts +++ b/apps/remix-ide-e2e/src/tests/plugin_api.ts @@ -188,7 +188,7 @@ module.exports = { .frameParent() .useCss() .clickLaunchIcon('udapp') - .waitForElementContainsText('#selectExEnvOptions option:checked', 'Remix VM (Berlin)') + .waitForElementContainsText('#selectExEnvOptions button', 'Remix VM (Berlin)') .clickLaunchIcon('localPlugin') .useXpath() // @ts-ignore @@ -391,7 +391,7 @@ module.exports = { .useCss() .clickLaunchIcon('pluginManager') .clickLaunchIcon('udapp') - .click('*[data-id="Hardhat Provider"]') + .switchEnvironment('Hardhat Provider') .modalFooterOKClick('hardhat-provider') .waitForElementContainsText('*[data-id="settingsNetworkEnv"]', 'Custom') // e.g Custom (1337) network .clickLaunchIcon('localPlugin') diff --git a/apps/remix-ide-e2e/src/tests/providers.test.ts b/apps/remix-ide-e2e/src/tests/providers.test.ts index fe6dcde8bf..5cb1048d91 100644 --- a/apps/remix-ide-e2e/src/tests/providers.test.ts +++ b/apps/remix-ide-e2e/src/tests/providers.test.ts @@ -10,7 +10,7 @@ module.exports = { 'Should switch to ganache provider, set a custom URL and fail to connect': function (browser: NightwatchBrowser) { browser.waitForElementVisible('div[data-id="remixIdeIconPanel"]', 10000) .clickLaunchIcon('udapp') - .click('*[data-id="Ganache Provider"]') + .switchEnvironment('Ganache Provider') .waitForElementVisible('*[data-id="ganache-providerModalDialogModalBody-react"]') .execute(() => { (document.querySelector('*[data-id="ganache-providerModalDialogModalBody-react"] input') as any).focus() @@ -25,7 +25,7 @@ module.exports = { }, 'Should switch to ganache provider, use the default ganache URL and succeed to connect': function (browser: NightwatchBrowser) { - browser.click('*[data-id="Ganache Provider"]') + browser.switchEnvironment('Ganache Provider') .waitForElementVisible('*[data-id="ganache-providerModalDialogModalBody-react"]') .modalFooterOKClick('ganache-provider') .waitForElementContainsText('*[data-id="settingsNetworkEnv"]', 'Custom (') @@ -33,7 +33,7 @@ module.exports = { 'Should switch to foundry provider, set a custom URL and fail to connect': function (browser: NightwatchBrowser) { browser.waitForElementVisible('div[data-id="remixIdeIconPanel"]', 10000) - .click('*[data-id="Foundry Provider"]') + .switchEnvironment('Foundry Provider') .waitForElementVisible('*[data-id="foundry-providerModalDialogModalBody-react"]') .execute(() => { (document.querySelector('*[data-id="foundry-providerModalDialogModalBody-react"] input') as any).focus() @@ -48,7 +48,7 @@ module.exports = { }, 'Should switch to foundry provider, use the default foundry URL and succeed to connect': function (browser: NightwatchBrowser) { - browser.click('*[data-id="Foundry Provider"]') + browser.switchEnvironment('Foundry Provider') .waitForElementVisible('*[data-id="foundry-providerModalDialogModalBody-react"]') .modalFooterOKClick('foundry-provider') .waitForElementContainsText('*[data-id="settingsNetworkEnv"]', 'Custom (') diff --git a/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts b/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts index dc00530bdd..6d87899d79 100644 --- a/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts +++ b/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts @@ -32,7 +32,7 @@ module.exports = { 'Should sign message using account key #group2': function (browser: NightwatchBrowser) { browser.waitForElementVisible('*[data-id="settingsRemixRunSignMsg"]') - .click('select[id="selectExEnvOptions"] option[value="vm-berlin"]') + .switchEnvironment('vm-berlin') .pause(2000) .click('*[data-id="settingsRemixRunSignMsg"]') .pause(2000) diff --git a/apps/remix-ide-e2e/src/tests/terminal.test.ts b/apps/remix-ide-e2e/src/tests/terminal.test.ts index 59af766031..610875074f 100644 --- a/apps/remix-ide-e2e/src/tests/terminal.test.ts +++ b/apps/remix-ide-e2e/src/tests/terminal.test.ts @@ -50,8 +50,8 @@ module.exports = { browser .click('*[data-id="terminalClearConsole"]') // clear the terminal .clickLaunchIcon('udapp') - .click('*[data-id="settingsSelectEnvOptions"] *[data-id="External Http Provider"]') - .modalFooterOKClick('basic-http-provider') + .switchEnvironment('web3') + .modalFooterOKClick('envNotification') .executeScript('web3.eth.getAccounts()') .waitForElementContainsText('*[data-id="terminalJournal"]', '["', 60000) // we check if an array is present, don't need to check for the content .waitForElementContainsText('*[data-id="terminalJournal"]', '"]', 60000) @@ -95,7 +95,7 @@ module.exports = { browser .clickLaunchIcon('settings') .clickLaunchIcon('udapp') - .click('*[data-id="settingsVMLondonMode"]') + .switchEnvironment('vm-london') .click('*[data-id="terminalClearConsole"]') // clear the terminal .clickLaunchIcon('filePanel') .click('*[data-id="treeViewDivtreeViewItem"]') // make sure we create the file at the root folder diff --git a/apps/remix-ide-e2e/src/tests/transactionExecution.test.ts b/apps/remix-ide-e2e/src/tests/transactionExecution.test.ts index 3eac406fcd..842da3b3c7 100644 --- a/apps/remix-ide-e2e/src/tests/transactionExecution.test.ts +++ b/apps/remix-ide-e2e/src/tests/transactionExecution.test.ts @@ -161,7 +161,7 @@ module.exports = { browser .clickLaunchIcon('udapp') .clearTransactions() - .click('*[data-id="settingsVMLondonMode"]') // switch to London fork + .switchEnvironment('vm-london') // switch to London fork .selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite .click('.udapp_contractActionsContainerSingle > button') .clickInstance(0) diff --git a/apps/remix-ide-e2e/src/types/index.d.ts b/apps/remix-ide-e2e/src/types/index.d.ts index eccd50bad5..9ba94f470b 100644 --- a/apps/remix-ide-e2e/src/types/index.d.ts +++ b/apps/remix-ide-e2e/src/types/index.d.ts @@ -64,6 +64,7 @@ declare module 'nightwatch' { getBrowserLogs (this: NightwatchBrowser): NightwatchBrowser currentSelectedFileIs (name: string): NightwatchBrowser, switchWorkspace: (workspaceName: string) => NightwatchBrowser + switchEnvironment: (provider: string) => NightwatchBrowser } export interface NightwatchBrowser { From 78385e16983dc0414de8288e87cb4be273b5243a Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 7 Jul 2022 14:21:45 +0200 Subject: [PATCH 05/11] fix tests --- apps/remix-ide-e2e/src/tests/ballot.test.ts | 2 +- apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts | 2 +- apps/remix-ide-e2e/src/tests/debugger.test.ts | 2 +- apps/remix-ide-e2e/src/tests/terminal.test.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index 0fd5fa1788..7d562d8e19 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -83,7 +83,7 @@ module.exports = { browser .openFile('Untitled.sol') .clickLaunchIcon('udapp') - .switchEnvironment('web3') + .switchEnvironment('External Http Provider') .waitForElementPresent('[data-id="envNotification-modal-footer-ok-react"]') .execute(function () { const modal = document.querySelector('[data-id="basic-http-provider-modal-footer-ok-react"]') as any diff --git a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts index afe6a8545b..b6ac2edc53 100644 --- a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts @@ -78,7 +78,7 @@ module.exports = { browser .openFile('Untitled.sol') .clickLaunchIcon('udapp') - .switchEnvironment('web3') + .switchEnvironment('External Http Provider') .waitForElementPresent('[data-id="envNotification-modal-footer-ok-react"]') .execute(function () { const modal = document.querySelector('[data-id="basic-http-provider-modal-footer-ok-react"]') as any diff --git a/apps/remix-ide-e2e/src/tests/debugger.test.ts b/apps/remix-ide-e2e/src/tests/debugger.test.ts index bc8db41a09..19aa196b60 100644 --- a/apps/remix-ide-e2e/src/tests/debugger.test.ts +++ b/apps/remix-ide-e2e/src/tests/debugger.test.ts @@ -214,7 +214,7 @@ module.exports = { .setSolidityCompilerVersion('soljson-v0.8.7+commit.e28d00a7.js') .addFile('useDebugNodes.sol', sources[5]['useDebugNodes.sol']) // compile contract .clickLaunchIcon('udapp') - .switchEnvironment('web3') // select web3 provider with debug nodes URL + .switchEnvironment('External Http Provider') // select web3 provider with debug nodes URL .clearValue('*[data-id="modalDialogCustomPromptText"]') .setValue('*[data-id="modalDialogCustomPromptText"]', 'https://remix-rinkeby.ethdevops.io') .modalFooterOKClick() diff --git a/apps/remix-ide-e2e/src/tests/terminal.test.ts b/apps/remix-ide-e2e/src/tests/terminal.test.ts index 610875074f..4a451eba20 100644 --- a/apps/remix-ide-e2e/src/tests/terminal.test.ts +++ b/apps/remix-ide-e2e/src/tests/terminal.test.ts @@ -50,7 +50,7 @@ module.exports = { browser .click('*[data-id="terminalClearConsole"]') // clear the terminal .clickLaunchIcon('udapp') - .switchEnvironment('web3') + .switchEnvironment('External Http Provider') .modalFooterOKClick('envNotification') .executeScript('web3.eth.getAccounts()') .waitForElementContainsText('*[data-id="terminalJournal"]', '["', 60000) // we check if an array is present, don't need to check for the content From 9b94c4de6b58a4bb1fdf2730a914b82ee2f39c03 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 7 Jul 2022 14:31:05 +0200 Subject: [PATCH 06/11] notify if no injected provider --- apps/remix-ide/src/app/tabs/injected-provider.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide/src/app/tabs/injected-provider.tsx b/apps/remix-ide/src/app/tabs/injected-provider.tsx index a633c66a64..77f36f08f5 100644 --- a/apps/remix-ide/src/app/tabs/injected-provider.tsx +++ b/apps/remix-ide/src/app/tabs/injected-provider.tsx @@ -11,7 +11,9 @@ export class InjectedProvider extends Plugin { constructor (profile) { super(profile) - this.provider = new Web3((window as any).ethereum) + if ((window as any).ethereum) { + this.provider = new Web3((window as any).ethereum) + } } sendAsync (data: JsonDataRequest): Promise { @@ -23,7 +25,10 @@ export class InjectedProvider extends Plugin { private async sendAsyncInternal (data: JsonDataRequest, resolve: SuccessRequest, reject: RejectRequest): Promise { // Check the case where current environment is VM on UI and it still sends RPC requests // This will be displayed on UI tooltip as 'cannot get account list: Environment Updated !!' - + if (!this.provider) { + this.call('notification', 'toast', 'No injected provider (e.g Metamask) has been found.') + return reject(new Error('no injected provider found.')) + } try { if ((window as any) && typeof (window as any).ethereum.enable === 'function') (window as any).ethereum.enable() await addL2Network(this.chainName, this.chainId, this.rpcUrls) From 3f6746581cb2ab84bd136be06262d832b9419d60 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 7 Jul 2022 14:43:56 +0200 Subject: [PATCH 07/11] fix tests --- apps/remix-ide-e2e/src/tests/ballot.test.ts | 2 +- apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts | 2 +- apps/remix-ide-e2e/src/tests/terminal.test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index 7d562d8e19..f857f1a385 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -84,7 +84,7 @@ module.exports = { .openFile('Untitled.sol') .clickLaunchIcon('udapp') .switchEnvironment('External Http Provider') - .waitForElementPresent('[data-id="envNotification-modal-footer-ok-react"]') + .waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]') .execute(function () { const modal = document.querySelector('[data-id="basic-http-provider-modal-footer-ok-react"]') as any diff --git a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts index b6ac2edc53..9a36ad67f4 100644 --- a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts @@ -79,7 +79,7 @@ module.exports = { .openFile('Untitled.sol') .clickLaunchIcon('udapp') .switchEnvironment('External Http Provider') - .waitForElementPresent('[data-id="envNotification-modal-footer-ok-react"]') + .waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]') .execute(function () { const modal = document.querySelector('[data-id="basic-http-provider-modal-footer-ok-react"]') as any diff --git a/apps/remix-ide-e2e/src/tests/terminal.test.ts b/apps/remix-ide-e2e/src/tests/terminal.test.ts index 4a451eba20..c061d8fd39 100644 --- a/apps/remix-ide-e2e/src/tests/terminal.test.ts +++ b/apps/remix-ide-e2e/src/tests/terminal.test.ts @@ -51,7 +51,7 @@ module.exports = { .click('*[data-id="terminalClearConsole"]') // clear the terminal .clickLaunchIcon('udapp') .switchEnvironment('External Http Provider') - .modalFooterOKClick('envNotification') + .modalFooterOKClick('basic-http-provider') .executeScript('web3.eth.getAccounts()') .waitForElementContainsText('*[data-id="terminalJournal"]', '["', 60000) // we check if an array is present, don't need to check for the content .waitForElementContainsText('*[data-id="terminalJournal"]', '"]', 60000) From 8c692c62c66f8854b0fdab71b4c8af1f9067f6cc Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 7 Jul 2022 15:14:44 +0200 Subject: [PATCH 08/11] update labels --- libs/remix-ui/run-tab/src/lib/components/environment.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index 0a311deb30..6a346fcf53 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -31,7 +31,7 @@ export function EnvironmentUI (props: EnvironmentProps) {