From 5ba9cca2ec5bb5d5280f17c8de250de43d705d10 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 23 Aug 2023 12:58:57 +0200 Subject: [PATCH] add ephemery provider --- apps/remix-ide/src/app.js | 211 +++++++++----- .../injected-ephemery-testnet-provider.tsx | 20 ++ apps/remix-ide/src/app/udapp/run-tab.js | 269 ++++++++++++++---- apps/remix-ide/src/remixAppManager.js | 194 ++++++++++--- 4 files changed, 529 insertions(+), 165 deletions(-) create mode 100644 apps/remix-ide/src/app/providers/injected-ephemery-testnet-provider.tsx diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index 27e2e5de88..85b205c3d3 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -1,57 +1,74 @@ 'use strict' -import { RunTab, makeUdapp } from './app/udapp' -import { RemixEngine } from './remixEngine' -import { RemixAppManager } from './remixAppManager' -import { ThemeModule } from './app/tabs/theme-module' -import { LocaleModule } from './app/tabs/locale-module' -import { NetworkModule } from './app/tabs/network-module' -import { Web3ProviderModule } from './app/tabs/web3-provider' -import { CompileAndRun } from './app/tabs/compile-and-run' -import { SidePanel } from './app/components/side-panel' -import { HiddenPanel } from './app/components/hidden-panel' -import { VerticalIcons } from './app/components/vertical-icons' -import { LandingPage } from './app/ui/landing-page/landing-page' -import { MainPanel } from './app/components/main-panel' -import { PermissionHandlerPlugin } from './app/plugins/permission-handler-plugin' -import { AstWalker } from '@remix-project/remix-astwalker' -import { LinkLibraries, DeployLibraries, OpenZeppelinProxy } from '@remix-project/core-plugin' -import { CodeParser } from './app/plugins/parser/code-parser' -import { SolidityScript } from './app/plugins/solidity-script' - -import { WalkthroughService } from './walkthroughService' - -import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports, GistHandler } from '@remix-project/core-plugin' +import {RunTab, makeUdapp} from './app/udapp' +import {RemixEngine} from './remixEngine' +import {RemixAppManager} from './remixAppManager' +import {ThemeModule} from './app/tabs/theme-module' +import {LocaleModule} from './app/tabs/locale-module' +import {NetworkModule} from './app/tabs/network-module' +import {Web3ProviderModule} from './app/tabs/web3-provider' +import {CompileAndRun} from './app/tabs/compile-and-run' +import {SidePanel} from './app/components/side-panel' +import {HiddenPanel} from './app/components/hidden-panel' +import {VerticalIcons} from './app/components/vertical-icons' +import {LandingPage} from './app/ui/landing-page/landing-page' +import {MainPanel} from './app/components/main-panel' +import {PermissionHandlerPlugin} from './app/plugins/permission-handler-plugin' +import {AstWalker} from '@remix-project/remix-astwalker' +import { + LinkLibraries, + DeployLibraries, + OpenZeppelinProxy +} from '@remix-project/core-plugin' +import {CodeParser} from './app/plugins/parser/code-parser' +import {SolidityScript} from './app/plugins/solidity-script' + +import {WalkthroughService} from './walkthroughService' + +import { + OffsetToLineColumnConverter, + CompilerMetadata, + CompilerArtefacts, + FetchAndCompile, + CompilerImports, + GistHandler +} from '@remix-project/core-plugin' import Registry from './app/state/registry' -import { ConfigPlugin } from './app/plugins/config' -import { StoragePlugin } from './app/plugins/storage' -import { Layout } from './app/panels/layout' -import { NotificationPlugin } from './app/plugins/notification' -import { Blockchain } from './blockchain/blockchain' -import { MergeVMProvider, LondonVMProvider, BerlinVMProvider, ShanghaiVMProvider } from './app/providers/vm-provider' -import { MainnetForkVMProvider } from './app/providers/mainnet-vm-fork-provider' -import { SepoliaForkVMProvider } from './app/providers/sepolia-vm-fork-provider' -import { GoerliForkVMProvider } from './app/providers/goerli-vm-fork-provider' -import { CustomForkVMProvider } from './app/providers/custom-vm-fork-provider' -import { HardhatProvider } from './app/providers/hardhat-provider' -import { GanacheProvider } from './app/providers/ganache-provider' -import { FoundryProvider } from './app/providers/foundry-provider' -import { ExternalHttpProvider } from './app/providers/external-http-provider' -import { InjectedProviderDefault } from './app/providers/injected-provider-default' -import { InjectedProviderTrustWallet } from './app/providers/injected-provider-trustwallet' -import { Injected0ptimismProvider } from './app/providers/injected-optimism-provider' -import { InjectedArbitrumOneProvider } from './app/providers/injected-arbitrum-one-provider' -import { FileDecorator } from './app/plugins/file-decorator' -import { CodeFormat } from './app/plugins/code-format' -import { SolidityUmlGen } from './app/plugins/solidity-umlgen' -import { ContractFlattener } from './app/plugins/contractFlattener' +import {ConfigPlugin} from './app/plugins/config' +import {StoragePlugin} from './app/plugins/storage' +import {Layout} from './app/panels/layout' +import {NotificationPlugin} from './app/plugins/notification' +import {Blockchain} from './blockchain/blockchain' +import { + MergeVMProvider, + LondonVMProvider, + BerlinVMProvider, + ShanghaiVMProvider +} from './app/providers/vm-provider' +import {MainnetForkVMProvider} from './app/providers/mainnet-vm-fork-provider' +import {SepoliaForkVMProvider} from './app/providers/sepolia-vm-fork-provider' +import {GoerliForkVMProvider} from './app/providers/goerli-vm-fork-provider' +import {CustomForkVMProvider} from './app/providers/custom-vm-fork-provider' +import {HardhatProvider} from './app/providers/hardhat-provider' +import {GanacheProvider} from './app/providers/ganache-provider' +import {FoundryProvider} from './app/providers/foundry-provider' +import {ExternalHttpProvider} from './app/providers/external-http-provider' +import {InjectedProviderDefault} from './app/providers/injected-provider-default' +import {InjectedProviderTrustWallet} from './app/providers/injected-provider-trustwallet' +import {Injected0ptimismProvider} from './app/providers/injected-optimism-provider' +import {InjectedEphemeryTestnetProvider} from './app/providers/injected-ephemery-testnet-provider' +import {InjectedArbitrumOneProvider} from './app/providers/injected-arbitrum-one-provider' +import {FileDecorator} from './app/plugins/file-decorator' +import {CodeFormat} from './app/plugins/code-format' +import {SolidityUmlGen} from './app/plugins/solidity-umlgen' +import {ContractFlattener} from './app/plugins/contractFlattener' const isElectron = require('is-electron') const remixLib = require('@remix-project/remix-lib') -import { QueryParams } from '@remix-project/remix-lib' -import { SearchPlugin } from './app/tabs/search' +import {QueryParams} from '@remix-project/remix-lib' +import {SearchPlugin} from './app/tabs/search' const Storage = remixLib.Storage const RemixDProvider = require('./app/files/remixDProvider') @@ -67,12 +84,12 @@ const PluginManagerComponent = require('./app/components/plugin-manager-componen const CompileTab = require('./app/tabs/compile-tab') const SettingsTab = require('./app/tabs/settings-tab') const AnalysisTab = require('./app/tabs/analysis-tab') -const { DebuggerTab } = require('./app/tabs/debugger-tab') +const {DebuggerTab} = require('./app/tabs/debugger-tab') const TestTab = require('./app/tabs/test-tab') const FilePanel = require('./app/panels/file-panel') const Editor = require('./app/editor/editor') const Terminal = require('./app/panels/terminal') -const { TabProxy } = require('./app/panels/tab-proxy.js') +const {TabProxy} = require('./app/panels/tab-proxy.js') class AppComponent { constructor() { @@ -84,7 +101,7 @@ class AppComponent { // load app config const config = new Config(configStorage) - Registry.getInstance().put({ api: config, name: 'config' }) + Registry.getInstance().put({api: config, name: 'config'}) // load file system this._components.filesProviders = {} @@ -119,7 +136,7 @@ class AppComponent { this.panels = {} this.workspace = pluginLoader.get() this.engine = new RemixEngine() - this.engine.register(appManager); + this.engine.register(appManager) const matomoDomains = { 'remix-alpha.ethereum.org': 27, @@ -153,19 +170,19 @@ class AppComponent { this.themeModule = new ThemeModule() // ----------------- locale service --------------------------------- this.localeModule = new LocaleModule() - Registry.getInstance().put({ api: this.themeModule, name: 'themeModule' }) - Registry.getInstance().put({ api: this.localeModule, name: 'localeModule' }) + Registry.getInstance().put({api: this.themeModule, name: 'themeModule'}) + Registry.getInstance().put({api: this.localeModule, name: 'localeModule'}) // ----------------- editor service ---------------------------- const editor = new Editor() // wrapper around ace editor - Registry.getInstance().put({ api: editor, name: 'editor' }) + Registry.getInstance().put({api: editor, name: 'editor'}) editor.event.register('requiringToSaveCurrentfile', () => fileManager.saveCurrentFile() ) // ----------------- fileManager service ---------------------------- const fileManager = new FileManager(editor, appManager) - Registry.getInstance().put({ api: fileManager, name: 'filemanager' }) + Registry.getInstance().put({api: fileManager, name: 'filemanager'}) // ----------------- dGit provider --------------------------------- const dGitProvider = new DGitProvider() @@ -220,9 +237,11 @@ class AppComponent { const foundryProvider = new FoundryProvider(blockchain) const externalHttpProvider = new ExternalHttpProvider(blockchain) const trustWalletInjectedProvider = new InjectedProviderTrustWallet() - const defaultInjectedProvider = new InjectedProviderDefault + const defaultInjectedProvider = new InjectedProviderDefault() const injected0ptimismProvider = new Injected0ptimismProvider() const injectedArbitrumOneProvider = new InjectedArbitrumOneProvider() + const injectedEphemeryTestnetProvider = + new InjectedEphemeryTestnetProvider() // ----------------- convert offset to line/column service ----------- const offsetToLineColumnConverter = new OffsetToLineColumnConverter() Registry.getInstance().put({ @@ -232,11 +251,13 @@ class AppComponent { // ----------------- run script after each compilation results ----------- const compileAndRun = new CompileAndRun() // -------------------Terminal---------------------------------------- - makeUdapp(blockchain, compilersArtefacts, domEl => terminal.logHtml(domEl)) + makeUdapp(blockchain, compilersArtefacts, (domEl) => + terminal.logHtml(domEl) + ) const terminal = new Terminal( - { appManager, blockchain }, + {appManager, blockchain}, { - getPosition: event => { + getPosition: (event) => { const limitUp = 36 const limitDown = 20 const height = window.innerHeight @@ -298,6 +319,7 @@ class AppComponent { trustWalletInjectedProvider, injected0ptimismProvider, injectedArbitrumOneProvider, + injectedEphemeryTestnetProvider, this.walkthroughService, search, solidityumlgen, @@ -307,7 +329,7 @@ class AppComponent { // LAYOUT & SYSTEM VIEWS const appPanel = new MainPanel() - Registry.getInstance().put({ api: this.mainview, name: 'mainview' }) + Registry.getInstance().put({api: this.mainview, name: 'mainview'}) const tabProxy = new TabProxy(fileManager, editor) this.engine.register([appPanel, tabProxy]) @@ -391,10 +413,10 @@ class AppComponent { ]) this.layout.panels = { - tabs: { plugin: tabProxy, active: true }, - editor: { plugin: editor, active: true }, - main: { plugin: appPanel, active: false }, - terminal: { plugin: terminal, active: true, minimized: false } + tabs: {plugin: tabProxy, active: true}, + editor: {plugin: editor, active: true}, + main: {plugin: appPanel, active: false}, + terminal: {plugin: terminal, active: true, minimized: false} } } @@ -410,14 +432,41 @@ class AppComponent { await this.appManager.activatePlugin(['layout']) await this.appManager.activatePlugin(['notification']) await this.appManager.activatePlugin(['editor']) - await this.appManager.activatePlugin(['permissionhandler', 'theme', 'locale', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter']) + await this.appManager.activatePlugin([ + 'permissionhandler', + 'theme', + 'locale', + 'fileManager', + 'compilerMetadata', + 'compilerArtefacts', + 'network', + 'web3Provider', + 'offsetToLineColumnConverter' + ]) await this.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs']) await this.appManager.activatePlugin(['sidePanel']) // activating host plugin separately await this.appManager.activatePlugin(['home']) await this.appManager.activatePlugin(['settings', 'config']) - await this.appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'codeParser', 'codeFormatter', 'fileDecorator', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport', 'gistHandler']) + await this.appManager.activatePlugin([ + 'hiddenPanel', + 'pluginManager', + 'codeParser', + 'codeFormatter', + 'fileDecorator', + 'terminal', + 'blockchain', + 'fetchAndCompile', + 'contentImport', + 'gistHandler' + ]) await this.appManager.activatePlugin(['settings']) - await this.appManager.activatePlugin(['walkthrough', 'storage', 'search', 'compileAndRun', 'recorder']) + await this.appManager.activatePlugin([ + 'walkthrough', + 'storage', + 'search', + 'compileAndRun', + 'recorder' + ]) await this.appManager.activatePlugin(['solidity-script']) this.appManager.on( @@ -448,7 +497,11 @@ class AppComponent { } catch (e) { console.log(e) } - if (params.code && (!params.activate || params.activate.split(',').includes('solidity'))) { + if ( + params.code && + (!params.activate || + params.activate.split(',').includes('solidity')) + ) { // if code is given in url we focus on solidity plugin this.menuicons.select('solidity') } else { @@ -466,24 +519,28 @@ class AppComponent { if (params.call) { const callDetails = params.call.split('//') if (callDetails.length > 1) { - this.appManager.call('notification', 'toast', `initiating ${callDetails[0]} and calling "${callDetails[1]}" ...`) + this.appManager.call( + 'notification', + 'toast', + `initiating ${callDetails[0]} and calling "${callDetails[1]}" ...` + ) // @todo(remove the timeout when activatePlugin is on 0.3.0) await this.appManager.call(...callDetails).catch(console.error) } } if (params.calls) { - const calls = params.calls.split("///"); + const calls = params.calls.split('///') // call all functions in the list, one after the other for (const call of calls) { - const callDetails = call.split("//"); + const callDetails = call.split('//') if (callDetails.length > 1) { this.appManager.call( - "notification", - "toast", + 'notification', + 'toast', `initiating ${callDetails[0]} and calling "${callDetails[1]}" ...` - ); + ) // @todo(remove the timeout when activatePlugin is on 0.3.0) try { @@ -503,7 +560,13 @@ class AppComponent { }) // activate solidity plugin - this.appManager.activatePlugin(['solidity', 'udapp', 'deploy-libraries', 'link-libraries', 'openzeppelin-proxy']) + this.appManager.activatePlugin([ + 'solidity', + 'udapp', + 'deploy-libraries', + 'link-libraries', + 'openzeppelin-proxy' + ]) } } diff --git a/apps/remix-ide/src/app/providers/injected-ephemery-testnet-provider.tsx b/apps/remix-ide/src/app/providers/injected-ephemery-testnet-provider.tsx new file mode 100644 index 0000000000..34d0b8920c --- /dev/null +++ b/apps/remix-ide/src/app/providers/injected-ephemery-testnet-provider.tsx @@ -0,0 +1,20 @@ +import * as packageJson from '../../../../../package.json' +import {InjectedL2Provider} from './injected-L2-provider' + +const profile = { + name: 'injected-ephemery-testnet-provider', + displayName: 'Injected Ephemery Testnet Provider', + kind: 'provider', + description: 'Injected Ephemery Testnet Provider', + methods: ['sendAsync', 'init'], + version: packageJson.version +} + +export class InjectedEphemeryTestnetProvider extends InjectedL2Provider { + constructor() { + super(profile, 'Optimism', '0x259C709', [ + 'https://otter.bordel.wtf/erigon', + 'https://eth.ephemeral.zeus.fyi' + ]) + } +} diff --git a/apps/remix-ide/src/app/udapp/run-tab.js b/apps/remix-ide/src/app/udapp/run-tab.js index ec389b1db8..afa3aa9d5c 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.js +++ b/apps/remix-ide/src/app/udapp/run-tab.js @@ -1,12 +1,12 @@ import React from 'react' // eslint-disable-line -import { RunTabUI } from '@remix-ui/run-tab' -import { ViewPlugin } from '@remixproject/engine-web' -import { addressToString } from '@remix-ui/helper' +import {RunTabUI} from '@remix-ui/run-tab' +import {ViewPlugin} from '@remixproject/engine-web' +import {addressToString} from '@remix-ui/helper' import * as packageJson from '../../../../../package.json' const EventManager = require('../../lib/events') const Recorder = require('../tabs/runTab/model/recorder.js') -const _paq = window._paq = window._paq || [] +const _paq = (window._paq = window._paq || []) const profile = { name: 'udapp', @@ -20,11 +20,30 @@ const profile = { maintainedBy: 'Remix', permission: true, events: ['newTransaction'], - methods: ['createVMAccount', 'sendTransaction', 'getAccounts', 'pendingTransactionsCount', 'getSettings', 'setEnvironmentMode', 'clearAllInstances', 'addInstance', 'resolveContractAndAddInstance'] + methods: [ + 'createVMAccount', + 'sendTransaction', + 'getAccounts', + 'pendingTransactionsCount', + 'getSettings', + 'setEnvironmentMode', + 'clearAllInstances', + 'addInstance', + 'resolveContractAndAddInstance' + ] } export class RunTab extends ViewPlugin { - constructor (blockchain, config, fileManager, editor, filePanel, compilersArtefacts, networkModule, fileProvider) { + constructor( + blockchain, + config, + fileManager, + editor, + filePanel, + compilersArtefacts, + networkModule, + fileProvider + ) { super(profile) this.event = new EventManager() this.config = config @@ -41,13 +60,13 @@ export class RunTab extends ViewPlugin { this.el = document.createElement('div') } - setupEvents () { + setupEvents() { this.blockchain.events.on('newTransaction', (tx, receipt) => { this.emit('newTransaction', tx, receipt) }) } - getSettings () { + getSettings() { return new Promise((resolve, reject) => { resolve({ selectedAccount: this.REACT_API.accounts.selectedAccount, @@ -57,51 +76,66 @@ export class RunTab extends ViewPlugin { }) } - async setEnvironmentMode (env) { - const canCall = await this.askUserPermission('setEnvironmentMode', 'change the environment used') + async setEnvironmentMode(env) { + const canCall = await this.askUserPermission( + 'setEnvironmentMode', + 'change the environment used' + ) if (canCall) { - env = typeof env === 'string' ? { context: env } : env + env = typeof env === 'string' ? {context: env} : env this.emit('setEnvironmentModeReducer', env, this.currentRequest.from) } } - clearAllInstances () { + clearAllInstances() { this.emit('clearAllInstancesReducer') } - addInstance (address, abi, name) { + addInstance(address, abi, name) { this.emit('addInstanceReducer', address, abi, name) } - createVMAccount (newAccount) { + createVMAccount(newAccount) { return this.blockchain.createVMAccount(newAccount) } - sendTransaction (tx) { + sendTransaction(tx) { _paq.push(['trackEvent', 'udapp', 'sendTx', 'udappTransaction']) return this.blockchain.sendTransaction(tx) } - getAccounts (cb) { + getAccounts(cb) { return this.blockchain.getAccounts(cb) } - pendingTransactionsCount () { + pendingTransactionsCount() { return this.blockchain.pendingTransactionsCount() } - render () { - return
+ render() { + return ( +
+ +
+ ) } - onReady (api) { + onReady(api) { this.REACT_API = api } - async onInitDone () { + async onInitDone() { const udapp = this // eslint-disable-line - const addProvider = async (name, displayName, isInjected, isVM, fork = '', dataId = '', title = '') => { + const addProvider = async ( + name, + displayName, + isInjected, + isVM, + fork = '', + dataId = '', + title = '' + ) => { await this.call('blockchain', 'addProvider', { options: {}, dataId, @@ -113,13 +147,13 @@ export class RunTab extends ViewPlugin { title, init: async function () { const options = await udapp.call(name, 'init') - if (options) { + if (options) { this.options = options if (options['fork']) this.fork = options['fork'] } }, provider: { - async sendAsync (payload, callback) { + async sendAsync(payload, callback) { try { const result = await udapp.call(name, 'sendAsync', payload) callback(null, result) @@ -133,11 +167,30 @@ export class RunTab extends ViewPlugin { // basic injected // if it's the trust wallet provider, we have a specific provider for that, see below - if (window && window.ethereum && !(window.ethereum.isTrustWallet || window.ethereum.selectedProvider?.isTrustWallet)) { - const displayNameInjected = `Injected Provider${(window && window.ethereum && !(window.ethereum.providers && !window.ethereum.selectedProvider)) ? - window.ethereum.isCoinbaseWallet || window.ethereum.selectedProvider?.isCoinbaseWallet ? ' - Coinbase' : - window.ethereum.isBraveWallet || window.ethereum.selectedProvider?.isBraveWallet ? ' - Brave' : - window.ethereum.isMetaMask || window.ethereum.selectedProvider?.isMetaMask ? ' - MetaMask' : '' : ''}` + if ( + window && + window.ethereum && + !( + window.ethereum.isTrustWallet || + window.ethereum.selectedProvider?.isTrustWallet + ) + ) { + const displayNameInjected = `Injected Provider${ + window && + window.ethereum && + !(window.ethereum.providers && !window.ethereum.selectedProvider) + ? window.ethereum.isCoinbaseWallet || + window.ethereum.selectedProvider?.isCoinbaseWallet + ? ' - Coinbase' + : window.ethereum.isBraveWallet || + window.ethereum.selectedProvider?.isBraveWallet + ? ' - Brave' + : window.ethereum.isMetaMask || + window.ethereum.selectedProvider?.isMetaMask + ? ' - MetaMask' + : '' + : '' + }` await addProvider('injected', displayNameInjected, true, false) } else if (window && !window.ethereum) { // we still add "injected" if there's no provider (just so it's visible to the user). @@ -145,45 +198,155 @@ export class RunTab extends ViewPlugin { } if (window && window.trustwallet) { - const displayNameInjected = `Injected Provider - TrustWallet` - await addProvider('injected-trustwallet', displayNameInjected, true, false) + const displayNameInjected = `Injected Provider - TrustWallet` + await addProvider( + 'injected-trustwallet', + displayNameInjected, + true, + false + ) } - + // VM - const titleVM = 'Execution environment is local to Remix. Data is only saved to browser memory and will vanish upon reload.' - await addProvider('vm-shanghai', 'Remix VM (Shanghai)', false, true, 'shanghai', 'settingsVMShanghaiMode', titleVM) - await addProvider('vm-merge', 'Remix VM (Merge)', false, true, 'merge', 'settingsVMMergeMode', titleVM) - await addProvider('vm-london', 'Remix VM (London)', false, true, 'london', 'settingsVMLondonMode', titleVM) - await addProvider('vm-berlin', 'Remix VM (Berlin)', false, true, 'berlin', 'settingsVMBerlinMode', titleVM) - await addProvider('vm-mainnet-fork', 'Remix VM - Mainnet fork', false, true, 'merge', 'settingsVMMainnetMode', titleVM) - await addProvider('vm-sepolia-fork', 'Remix VM - Sepolia fork', false, true, 'merge', 'settingsVMSepoliaMode', titleVM) - await addProvider('vm-goerli-fork', 'Remix VM - Goerli fork', false, true, 'merge', 'settingsVMGoerliMode', titleVM) - await addProvider('vm-custom-fork', 'Remix VM - Custom fork', false, true, '', 'settingsVMCustomMode', titleVM) + const titleVM = + 'Execution environment is local to Remix. Data is only saved to browser memory and will vanish upon reload.' + await addProvider( + 'vm-shanghai', + 'Remix VM (Shanghai)', + false, + true, + 'shanghai', + 'settingsVMShanghaiMode', + titleVM + ) + await addProvider( + 'vm-merge', + 'Remix VM (Merge)', + false, + true, + 'merge', + 'settingsVMMergeMode', + titleVM + ) + await addProvider( + 'vm-london', + 'Remix VM (London)', + false, + true, + 'london', + 'settingsVMLondonMode', + titleVM + ) + await addProvider( + 'vm-berlin', + 'Remix VM (Berlin)', + false, + true, + 'berlin', + 'settingsVMBerlinMode', + titleVM + ) + await addProvider( + 'vm-mainnet-fork', + 'Remix VM - Mainnet fork', + false, + true, + 'merge', + 'settingsVMMainnetMode', + titleVM + ) + await addProvider( + 'vm-sepolia-fork', + 'Remix VM - Sepolia fork', + false, + true, + 'merge', + 'settingsVMSepoliaMode', + titleVM + ) + await addProvider( + 'vm-goerli-fork', + 'Remix VM - Goerli fork', + false, + true, + 'merge', + 'settingsVMGoerliMode', + titleVM + ) + await addProvider( + 'vm-custom-fork', + 'Remix VM - Custom fork', + false, + true, + '', + 'settingsVMCustomMode', + titleVM + ) // wallet connect await addProvider('walletconnect', 'WalletConnect', false, false) + // testnet + await addProvider( + 'injected-ephemery-testnet-provider', + 'Ephemery Testnet', + true, + false + ) + // external provider - await addProvider('basic-http-provider', 'Custom - External Http Provider', false, false) - await addProvider('hardhat-provider', 'Dev - Hardhat Provider', false, false) - await addProvider('ganache-provider', 'Dev - Ganache Provider', false, false) - await addProvider('foundry-provider', 'Dev - Foundry Provider', false, false) - - // injected provider - await addProvider('injected-optimism-provider', 'L2 - Optimism Provider', true, false) - await addProvider('injected-arbitrum-one-provider', 'L2 - Arbitrum One Provider', true, false) + await addProvider( + 'basic-http-provider', + 'Custom - External Http Provider', + false, + false + ) + await addProvider( + 'hardhat-provider', + 'Dev - Hardhat Provider', + false, + false + ) + await addProvider( + 'ganache-provider', + 'Dev - Ganache Provider', + false, + false + ) + await addProvider( + 'foundry-provider', + 'Dev - Foundry Provider', + false, + false + ) + + // injected provider + await addProvider( + 'injected-optimism-provider', + 'L2 - Optimism Provider', + true, + false + ) + await addProvider( + 'injected-arbitrum-one-provider', + 'L2 - Arbitrum One Provider', + true, + false + ) } - writeFile (fileName, content) { + writeFile(fileName, content) { return this.call('fileManager', 'writeFile', fileName, content) } - readFile (fileName) { + readFile(fileName) { return this.call('fileManager', 'readFile', fileName) } - async resolveContractAndAddInstance (contractObject, address) { - const data = await this.compilersArtefacts.getCompilerAbstract(contractObject.contract.file) + async resolveContractAndAddInstance(contractObject, address) { + const data = await this.compilersArtefacts.getCompilerAbstract( + contractObject.contract.file + ) this.compilersArtefacts.addResolvedContract(addressToString(address), data) this.addInstance(address, contractObject.abi, contractObject.name) diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js index 9c9f365f23..6bb5ebd510 100644 --- a/apps/remix-ide/src/remixAppManager.js +++ b/apps/remix-ide/src/remixAppManager.js @@ -1,35 +1,123 @@ -import { PluginManager } from '@remixproject/engine' -import { EventEmitter } from 'events' -import { QueryParams } from '@remix-project/remix-lib' -import { IframePlugin } from '@remixproject/engine-web' -const _paq = window._paq = window._paq || [] +import {PluginManager} from '@remixproject/engine' +import {EventEmitter} from 'events' +import {QueryParams} from '@remix-project/remix-lib' +import {IframePlugin} from '@remixproject/engine-web' +const _paq = (window._paq = window._paq || []) // requiredModule removes the plugin from the plugin manager list on UI -const requiredModules = [ // services + layout views + system views - 'manager', 'config', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme', 'locale', - 'fileManager', 'contentImport', 'blockchain', 'web3Provider', 'scriptRunner', 'fetchAndCompile', 'mainPanel', 'hiddenPanel', 'sidePanel', 'menuicons', - 'filePanel', 'terminal', 'settings', 'pluginManager', 'tabs', 'udapp', 'dGitProvider', 'solidity', 'solidity-logic', 'gistHandler', 'layout', - 'notification', 'permissionhandler', 'walkthrough', 'storage', 'restorebackupzip', 'link-libraries', 'deploy-libraries', 'openzeppelin-proxy', - 'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider', 'injected', 'injected-trustwallet', 'injected-optimism-provider', 'injected-arbitrum-one-provider', 'vm-custom-fork', 'vm-goerli-fork', 'vm-mainnet-fork', 'vm-sepolia-fork', 'vm-merge', 'vm-london', 'vm-berlin', +const requiredModules = [ + // services + layout views + system views + 'manager', + 'config', + 'compilerArtefacts', + 'compilerMetadata', + 'contextualListener', + 'editor', + 'offsetToLineColumnConverter', + 'network', + 'theme', + 'locale', + 'fileManager', + 'contentImport', + 'blockchain', + 'web3Provider', + 'scriptRunner', + 'fetchAndCompile', + 'mainPanel', + 'hiddenPanel', + 'sidePanel', + 'menuicons', + 'filePanel', + 'terminal', + 'settings', + 'pluginManager', + 'tabs', + 'udapp', + 'dGitProvider', + 'solidity', + 'solidity-logic', + 'gistHandler', + 'layout', + 'notification', + 'permissionhandler', + 'walkthrough', + 'storage', + 'restorebackupzip', + 'link-libraries', + 'deploy-libraries', + 'openzeppelin-proxy', + 'hardhat-provider', + 'ganache-provider', + 'foundry-provider', + 'basic-http-provider', + 'injected', + 'injected-trustwallet', + 'injected-optimism-provider', + 'injected-ephemery-testnet-provider', + 'injected-arbitrum-one-provider', + 'vm-custom-fork', + 'vm-goerli-fork', + 'vm-mainnet-fork', + 'vm-sepolia-fork', + 'vm-merge', + 'vm-london', + 'vm-berlin', 'vm-shanghai', - 'compileAndRun', 'search', 'recorder', 'fileDecorator', 'codeParser', 'codeFormatter', 'solidityumlgen', 'contractflattener', 'solidity-script'] + 'compileAndRun', + 'search', + 'recorder', + 'fileDecorator', + 'codeParser', + 'codeFormatter', + 'solidityumlgen', + 'contractflattener', + 'solidity-script' +] // dependentModules shouldn't be manually activated (e.g hardhat is activated by remixd) const dependentModules = ['foundry', 'hardhat', 'truffle', 'slither'] -const loadLocalPlugins = ["doc-gen", "doc-viewer", "etherscan", "vyper", 'solhint', 'walletconnect'] +const loadLocalPlugins = [ + 'doc-gen', + 'doc-viewer', + 'etherscan', + 'vyper', + 'solhint', + 'walletconnect' +] const sensitiveCalls = { - 'fileManager': ['writeFile', 'copyFile', 'rename', 'copyDir'], - 'contentImport': ['resolveAndSave'], - 'web3Provider': ['sendAsync'], + fileManager: ['writeFile', 'copyFile', 'rename', 'copyDir'], + contentImport: ['resolveAndSave'], + web3Provider: ['sendAsync'] } export function isNative(name) { // nativePlugin allows to bypass the permission request - 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', - 'tabs', 'injected-arbitrum-one-provider', 'injected', 'doc-gen', 'doc-viewer'] + 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-ephemery-testnet-provider', + 'tabs', + 'injected-arbitrum-one-provider', + 'injected', + 'doc-gen', + 'doc-viewer' + ] return nativePlugins.includes(name) || requiredModules.includes(name) } @@ -44,16 +132,19 @@ export function isNative(name) { * @returns {boolean} */ export function canActivate(from, to) { - return ['ethdoc'].includes(from.name) || + return ( + ['ethdoc'].includes(from.name) || isNative(from.name) || (to && from && from.canActivate && from.canActivate.includes(to.name)) + ) } export class RemixAppManager extends PluginManager { constructor() { super() this.event = new EventEmitter() - this.pluginsDirectory = 'https://raw.githubusercontent.com/ethereum/remix-plugins-directory/master/build/metadata.json' + this.pluginsDirectory = + 'https://raw.githubusercontent.com/ethereum/remix-plugins-directory/master/build/metadata.json' this.pluginLoader = new PluginLoader() } @@ -72,10 +163,7 @@ export class RemixAppManager extends PluginManager { async deactivatePlugin(name) { const profile = await this.getProfile(name) - const [to, from] = [ - profile, - await this.getProfile(this.requestFrom) - ] + const [to, from] = [profile, await this.getProfile(this.requestFrom)] if (this.canDeactivatePlugin(from, to)) { if (profile.methods.includes('deactivate')) { try { @@ -89,7 +177,8 @@ export class RemixAppManager extends PluginManager { } async canCall(from, to, method, message) { - const isSensitiveCall = sensitiveCalls[to] && sensitiveCalls[to].includes(method) + const isSensitiveCall = + sensitiveCalls[to] && sensitiveCalls[to].includes(method) // Make sure the caller of this methods is the target plugin if (to !== this.currentRequest.from) { return false @@ -100,14 +189,26 @@ export class RemixAppManager extends PluginManager { } // ask the user for permission - return await this.call('permissionhandler', 'askPermission', this.profiles[from], this.profiles[to], method, message, isSensitiveCall) + return await this.call( + 'permissionhandler', + 'askPermission', + this.profiles[from], + this.profiles[to], + method, + message, + isSensitiveCall + ) } onPluginActivated(plugin) { - this.pluginLoader.set(plugin, this.actives.filter((plugin) => !this.isDependent(plugin))) + this.pluginLoader.set( + plugin, + this.actives.filter((plugin) => !this.isDependent(plugin)) + ) this.event.emit('activate', plugin) this.emit('activate', plugin) - if (!requiredModules.includes(plugin.name)) _paq.push(['trackEvent', 'pluginManager', 'activate', plugin.name]) + if (!requiredModules.includes(plugin.name)) + _paq.push(['trackEvent', 'pluginManager', 'activate', plugin.name]) } getAll() { @@ -121,7 +222,10 @@ export class RemixAppManager extends PluginManager { } onPluginDeactivated(plugin) { - this.pluginLoader.set(plugin, this.actives.filter((plugin) => !this.isDependent(plugin))) + this.pluginLoader.set( + plugin, + this.actives.filter((plugin) => !this.isDependent(plugin)) + ) this.event.emit('deactivate', plugin) _paq.push(['trackEvent', 'pluginManager', 'deactivate', plugin.name]) } @@ -141,8 +245,12 @@ export class RemixAppManager extends PluginManager { const res = await fetch(this.pluginsDirectory) plugins = await res.json() plugins = plugins.filter((plugin) => { - if (plugin.targets && Array.isArray(plugin.targets) && plugin.targets.length > 0) { - return (plugin.targets.includes('remix')) + if ( + plugin.targets && + Array.isArray(plugin.targets) && + plugin.targets.length > 0 + ) { + return plugin.targets.includes('remix') } return true }) @@ -167,7 +275,11 @@ export class RemixAppManager extends PluginManager { const profile = await fetch(`plugins/${plugin}/profile.json`) const profileJson = await profile.json() // remove duplicates - plugins = plugins.filter((p) => p.name !== profileJson.name && p.displayName !== profileJson.displayName) + plugins = plugins.filter( + (p) => + p.name !== profileJson.name && + p.displayName !== profileJson.displayName + ) // change url profileJson.url = `plugins/${plugin}/index.html` // add the local plugin @@ -177,7 +289,7 @@ export class RemixAppManager extends PluginManager { } } - return plugins.map(plugin => { + return plugins.map((plugin) => { if (plugin.name === testPluginName) plugin.url = testPluginUrl return new IframePlugin(plugin) }) @@ -246,16 +358,22 @@ class PluginLoader { this.loaders = {} this.loaders.localStorage = { set: (plugin, actives) => { - const saved = actives.filter((name) => !this.donotAutoReload.includes(name)) + const saved = actives.filter( + (name) => !this.donotAutoReload.includes(name) + ) localStorage.setItem('workspace', JSON.stringify(saved)) }, - get: () => { return JSON.parse(localStorage.getItem('workspace')) } + get: () => { + return JSON.parse(localStorage.getItem('workspace')) + } } this.loaders.queryParams = { - set: () => { /* Do nothing. */ }, + set: () => { + /* Do nothing. */ + }, get: () => { - const { activate } = queryParams.get() + const {activate} = queryParams.get() if (!activate) return [] return activate.split(',') }