Merge branch 'master' into monacoverUpdate

pull/5370/head
Aniket 1 year ago committed by GitHub
commit 6b198113cf
  1. 2
      .lintstagedrc.json
  2. 9
      .prettierrc.json
  3. 240
      apps/remix-ide/src/app.js
  4. 4
      apps/remix-ide/src/app/providers/injected-arbitrum-one-provider.tsx
  5. 8
      apps/remix-ide/src/app/providers/injected-custom-provider.tsx
  6. 17
      apps/remix-ide/src/app/providers/injected-ephemery-testnet-provider.tsx
  7. 4
      apps/remix-ide/src/app/providers/injected-optimism-provider.tsx
  8. 92
      apps/remix-ide/src/app/udapp/run-tab.js
  9. 152
      apps/remix-ide/src/remixAppManager.js
  10. 2
      libs/remix-ui/editor/src/lib/remix-ui-editor.css
  11. 310
      libs/remix-ws-templates/src/script-templates/contract-deployer/create2-factory-deploy.ts

@ -1,3 +1,3 @@
{
"*.{tsx,ts,js,jsx,mjs,cjs}": ["prettier --write","eslint --fix"]
"**/*.{tsx,ts,js,jsx,mjs,cjs}": ["prettier --write","eslint --fix"]
}

@ -3,12 +3,5 @@
"useTabs": false,
"printWidth": 180,
"semi": false,
"singleQuote": true,
"quoteProps": "consistent",
"jsxSingleQuote": false,
"bracketSpacing": false,
"trailingComma": "none",
"jsxBracketSameLine": false,
"arrowParens": "always",
"singleAttributePerLine": false
"singleQuote": true
}

@ -1,57 +1,58 @@
'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 {InjectedArbitrumOneProvider} from './app/providers/injected-arbitrum-one-provider'
import {InjectedEphemeryTestnetProvider} from './app/providers/injected-ephemery-testnet-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 +68,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 +85,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 = {}
@ -93,9 +94,7 @@ class AppComponent {
api: this._components.filesProviders.browser,
name: 'fileproviders/browser'
})
this._components.filesProviders.localhost = new RemixDProvider(
this.appManager
)
this._components.filesProviders.localhost = new RemixDProvider(this.appManager)
Registry.getInstance().put({
api: this._components.filesProviders.localhost,
name: 'fileproviders/localhost'
@ -119,7 +118,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,
@ -127,15 +126,8 @@ class AppComponent {
'remix.ethereum.org': 23,
'6fd22d6fe5549ad4c4d8fd3ca0b7816b.mod': 35 // remix desktop
}
this.showMatamo =
matomoDomains[window.location.hostname] &&
!Registry.getInstance()
.get('config')
.api.exists('settings/matomo-analytics')
this.walkthroughService = new WalkthroughService(
appManager,
this.showMatamo
)
this.showMatamo = matomoDomains[window.location.hostname] && !Registry.getInstance().get('config').api.exists('settings/matomo-analytics')
this.walkthroughService = new WalkthroughService(appManager, this.showMatamo)
const hosts = ['127.0.0.1:8080', '192.168.0.101:8080', 'localhost:8080']
// workaround for Electron support
@ -153,12 +145,12 @@ 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', (currentFile) => {
fileManager.saveCurrentFile()
if (currentFile.endsWith('.circom')) this.appManager.activatePlugin(['circuit-compiler'])
@ -166,7 +158,7 @@ class AppComponent {
// ----------------- 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()
@ -221,9 +213,10 @@ 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({
@ -233,11 +226,11 @@ 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
@ -299,6 +292,7 @@ class AppComponent {
trustWalletInjectedProvider,
injected0ptimismProvider,
injectedArbitrumOneProvider,
injectedEphemeryTestnetProvider,
this.walkthroughService,
search,
solidityumlgen,
@ -308,7 +302,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])
@ -317,42 +311,18 @@ class AppComponent {
this.sidePanel = new SidePanel()
this.hiddenPanel = new HiddenPanel()
const pluginManagerComponent = new PluginManagerComponent(
appManager,
this.engine
)
const pluginManagerComponent = new PluginManagerComponent(appManager, this.engine)
const filePanel = new FilePanel(appManager)
const landingPage = new LandingPage(
appManager,
this.menuicons,
fileManager,
filePanel,
contentImport
)
this.settings = new SettingsTab(
Registry.getInstance().get('config').api,
editor,
appManager
)
const landingPage = new LandingPage(appManager, this.menuicons, fileManager, filePanel, contentImport)
this.settings = new SettingsTab(Registry.getInstance().get('config').api, editor, appManager)
this.engine.register([
this.menuicons,
landingPage,
this.hiddenPanel,
this.sidePanel,
filePanel,
pluginManagerComponent,
this.settings
])
this.engine.register([this.menuicons, landingPage, this.hiddenPanel, this.sidePanel, filePanel, pluginManagerComponent, this.settings])
// CONTENT VIEWS & DEFAULT PLUGINS
const openZeppelinProxy = new OpenZeppelinProxy(blockchain)
const linkLibraries = new LinkLibraries(blockchain)
const deployLibraries = new DeployLibraries(blockchain)
const compileTab = new CompileTab(
Registry.getInstance().get('config').api,
Registry.getInstance().get('filemanager').api
)
const compileTab = new CompileTab(Registry.getInstance().get('config').api, Registry.getInstance().get('filemanager').api)
const run = new RunTab(
blockchain,
Registry.getInstance().get('config').api,
@ -392,10 +362,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}
}
}
@ -411,27 +381,44 @@ 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(['solidity-script'])
this.appManager.on(
'filePanel',
'workspaceInitializationCompleted',
async () => {
// for e2e tests
const loadedElement = document.createElement('span')
loadedElement.setAttribute('data-id', 'workspaceloaded')
document.body.appendChild(loadedElement)
await this.appManager.registerContextMenuItems()
}
)
this.appManager.on('filePanel', 'workspaceInitializationCompleted', async () => {
// for e2e tests
const loadedElement = document.createElement('span')
loadedElement.setAttribute('data-id', 'workspaceloaded')
document.body.appendChild(loadedElement)
await this.appManager.registerContextMenuItems()
})
await this.appManager.activatePlugin(['filePanel'])
// Set workspace after initial activation
@ -442,9 +429,7 @@ class AppComponent {
.then(async () => {
try {
if (params.deactivate) {
await this.appManager.deactivatePlugin(
params.deactivate.split(',')
)
await this.appManager.deactivatePlugin(params.deactivate.split(','))
}
} catch (e) {
console.log(e)
@ -454,10 +439,7 @@ class AppComponent {
this.menuicons.select('solidity')
} else {
// If plugins are loaded from the URL params, we focus on the last one.
if (
this.appManager.pluginLoader.current === 'queryParams' &&
this.workspace.length > 0
) {
if (this.appManager.pluginLoader.current === 'queryParams' && this.workspace.length > 0) {
this.menuicons.select(this.workspace[this.workspace.length - 1])
} else {
this.appManager.call('tabs', 'focus', 'home')
@ -474,17 +456,13 @@ class AppComponent {
}
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",
`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)
try {

@ -1,5 +1,5 @@
import * as packageJson from '../../../../../package.json'
import {InjectedL2Provider} from './injected-L2-provider'
import {InjectedCustomProvider} from './injected-custom-provider'
const profile = {
name: 'injected-arbitrum-one-provider',
@ -10,7 +10,7 @@ const profile = {
version: packageJson.version
}
export class InjectedArbitrumOneProvider extends InjectedL2Provider {
export class InjectedArbitrumOneProvider extends InjectedCustomProvider {
constructor() {
super(profile, 'Arbitrum One', '0xa4b1', ['https://arb1.arbitrum.io/rpc'])
}

@ -1,6 +1,6 @@
import {InjectedProviderDefaultBase} from './injected-provider-default'
export class InjectedL2Provider extends InjectedProviderDefaultBase {
export class InjectedCustomProvider extends InjectedProviderDefaultBase {
chainName: string
chainId: string
rpcUrls: Array<string>
@ -14,13 +14,13 @@ export class InjectedL2Provider extends InjectedProviderDefaultBase {
async init() {
await super.init()
if (this.chainName && this.rpcUrls && this.rpcUrls.length > 0) await addL2Network(this.chainName, this.chainId, this.rpcUrls)
else throw new Error('Cannot add the L2 network to main injected provider')
if (this.chainName && this.rpcUrls && this.rpcUrls.length > 0) await addCustomNetwork(this.chainName, this.chainId, this.rpcUrls)
else throw new Error('Cannot add the custom network to main injected provider')
return {}
}
}
export const addL2Network = async (chainName: string, chainId: string, rpcUrls: Array<string>) => {
export const addCustomNetwork = async (chainName: string, chainId: string, rpcUrls: Array<string>) => {
try {
await (window as any).ethereum.request({
method: 'wallet_switchEthereumChain',

@ -0,0 +1,17 @@
import * as packageJson from '../../../../../package.json'
import {InjectedCustomProvider} from './injected-custom-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 InjectedCustomProvider {
constructor() {
super(profile, 'Ephemery Testnet', '0x259C709', ['https://otter.bordel.wtf/erigon', 'https://eth.ephemeral.zeus.fyi'])
}
}

@ -1,5 +1,5 @@
import * as packageJson from '../../../../../package.json'
import {InjectedL2Provider} from './injected-L2-provider'
import {InjectedCustomProvider} from './injected-custom-provider'
const profile = {
name: 'injected-optimism-provider',
@ -10,7 +10,7 @@ const profile = {
version: packageJson.version
}
export class Injected0ptimismProvider extends InjectedL2Provider {
export class Injected0ptimismProvider extends InjectedCustomProvider {
constructor() {
super(profile, 'Optimism', '0xa', ['https://mainnet.optimism.io'])
}

@ -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,21 @@ 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 +51,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,48 +67,52 @@ export class RunTab extends ViewPlugin {
})
}
async setEnvironmentMode (env) {
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 <div><RunTabUI plugin={this} /></div>
render() {
return (
<div>
<RunTabUI plugin={this} />
</div>
)
}
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 = '') => {
@ -113,13 +127,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)
@ -134,10 +148,17 @@ 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' : '' : ''}`
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,10 +166,10 @@ export class RunTab extends ViewPlugin {
}
if (window && window.trustwallet) {
const displayNameInjected = `Injected Provider - TrustWallet`
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)
@ -163,26 +184,29 @@ export class RunTab extends ViewPlugin {
// 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('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) {
async resolveContractAndAddInstance(contractObject, address) {
const data = await this.compilersArtefacts.getCompilerAbstract(contractObject.contract.file)
this.compilersArtefacts.addResolvedContract(addressToString(address), data)

@ -1,35 +1,116 @@
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-arbitrum-one-provider',
'injected-ephemery-testnet-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", "circuit-compiler"]
const loadLocalPlugins = ['doc-gen', 'doc-viewer', 'etherscan', 'vyper', 'solhint', 'walletconnect', 'circuit-compiler']
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',
'tabs',
'injected-arbitrum-one-provider',
'injected-ephemery-testnet-provider',
'injected',
'doc-gen',
'doc-viewer'
]
return nativePlugins.includes(name) || requiredModules.includes(name)
}
@ -44,9 +125,7 @@ export function isNative(name) {
* @returns {boolean}
*/
export function canActivate(from, to) {
return ['ethdoc'].includes(from.name) ||
isNative(from.name) ||
(to && from && from.canActivate && from.canActivate.includes(to.name))
return ['ethdoc'].includes(from.name) || isNative(from.name) || (to && from && from.canActivate && from.canActivate.includes(to.name))
}
export class RemixAppManager extends PluginManager {
@ -72,10 +151,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 {
@ -104,7 +180,10 @@ export class RemixAppManager extends PluginManager {
}
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])
@ -121,7 +200,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])
}
@ -142,7 +224,7 @@ export class RemixAppManager extends PluginManager {
plugins = await res.json()
plugins = plugins.filter((plugin) => {
if (plugin.targets && Array.isArray(plugin.targets) && plugin.targets.length > 0) {
return (plugin.targets.includes('remix'))
return plugin.targets.includes('remix')
}
return true
})
@ -177,7 +259,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)
})
@ -249,13 +331,17 @@ class PluginLoader {
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(',')
}

@ -1,9 +1,9 @@
.hover-row {
white-space: pre;
margin-left : 10px;
background : var(--light);
font-weight : bold;
font-family : monospace;
font-size: smaller;
padding : 10px;
border-radius : 10px;
height: auto;

@ -1,8 +1,7 @@
import { ethers } from 'ethers'
// https://etherscan.io/address/0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2#code
export const CREATE2_DEPLOYER_ADDRESS =
"0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2";
export const CREATE2_DEPLOYER_ADDRESS = '0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2'
/**
* Deploy the given contract using a factory
@ -13,20 +12,19 @@ export const CREATE2_DEPLOYER_ADDRESS =
* @param {number} accountIndex account index from the exposed account
* @return {string} deployed contract address
*/
export const deploy = async (contractName: string, args: Array<any>, salt: string, accountIndex?: number): Promise<string> => {
export const deploy = async (contractName: string, args: Array<any>, salt: string, accountIndex?: number): Promise<string> => {
console.log(`deploying ${contractName}`)
const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner(accountIndex)
const factory = new ethers.Contract(CREATE2_DEPLOYER_ADDRESS, contractDeployerAbi, signer);
const signer = new ethers.providers.Web3Provider(web3Provider).getSigner(accountIndex)
const factory = new ethers.Contract(CREATE2_DEPLOYER_ADDRESS, contractDeployerAbi, signer)
//@ts-ignore
const contract = await ethers.getContractFactory(contractName)
const initCode = contract.getDeployTransaction(args)
const codeHash = ethers.utils.keccak256(initCode.data)
const saltBytes = ethers.utils.id(salt)
const deployedAddress = await factory.computeAddress(saltBytes, codeHash)
const deployedAddress = await factory.computeAddress(saltBytes, codeHash)
try {
const tx = await factory.deploy(0, saltBytes, initCode.data)
await tx.wait()
@ -40,219 +38,219 @@ export const deploy = async (contractName: string, args: Array<any>, salt: strin
export const contractDeployerAbi = [
{
"anonymous": false,
"inputs": [
anonymous: false,
inputs: [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
indexed: true,
internalType: 'address',
name: 'previousOwner',
type: 'address',
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
indexed: true,
internalType: 'address',
name: 'newOwner',
type: 'address',
},
],
"name": "OwnershipTransferred",
"type": "event"
name: 'OwnershipTransferred',
type: 'event',
},
{
"anonymous": false,
"inputs": [
anonymous: false,
inputs: [
{
"indexed": false,
"internalType": "address",
"name": "account",
"type": "address"
}
indexed: false,
internalType: 'address',
name: 'account',
type: 'address',
},
],
"name": "Paused",
"type": "event"
name: 'Paused',
type: 'event',
},
{
"anonymous": false,
"inputs": [
anonymous: false,
inputs: [
{
"indexed": false,
"internalType": "address",
"name": "account",
"type": "address"
}
indexed: false,
internalType: 'address',
name: 'account',
type: 'address',
},
],
"name": "Unpaused",
"type": "event"
name: 'Unpaused',
type: 'event',
},
{
"inputs": [
inputs: [
{
"internalType": "bytes32",
"name": "salt",
"type": "bytes32"
internalType: 'bytes32',
name: 'salt',
type: 'bytes32',
},
{
"internalType": "bytes32",
"name": "codeHash",
"type": "bytes32"
}
internalType: 'bytes32',
name: 'codeHash',
type: 'bytes32',
},
],
"name": "computeAddress",
"outputs": [
name: 'computeAddress',
outputs: [
{
"internalType": "address",
"name": "",
"type": "address"
}
internalType: 'address',
name: '',
type: 'address',
},
],
"stateMutability": "view",
"type": "function"
stateMutability: 'view',
type: 'function',
},
{
"inputs": [
inputs: [
{
"internalType": "bytes32",
"name": "salt",
"type": "bytes32"
internalType: 'bytes32',
name: 'salt',
type: 'bytes32',
},
{
"internalType": "bytes32",
"name": "codeHash",
"type": "bytes32"
internalType: 'bytes32',
name: 'codeHash',
type: 'bytes32',
},
{
"internalType": "address",
"name": "deployer",
"type": "address"
}
internalType: 'address',
name: 'deployer',
type: 'address',
},
],
"name": "computeAddressWithDeployer",
"outputs": [
name: 'computeAddressWithDeployer',
outputs: [
{
"internalType": "address",
"name": "",
"type": "address"
}
internalType: 'address',
name: '',
type: 'address',
},
],
"stateMutability": "pure",
"type": "function"
stateMutability: 'pure',
type: 'function',
},
{
"inputs": [
inputs: [
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
internalType: 'uint256',
name: 'value',
type: 'uint256',
},
{
"internalType": "bytes32",
"name": "salt",
"type": "bytes32"
internalType: 'bytes32',
name: 'salt',
type: 'bytes32',
},
{
"internalType": "bytes",
"name": "code",
"type": "bytes"
}
internalType: 'bytes',
name: 'code',
type: 'bytes',
},
],
"name": "deploy",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
name: 'deploy',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
"inputs": [
inputs: [
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
internalType: 'uint256',
name: 'value',
type: 'uint256',
},
{
"internalType": "bytes32",
"name": "salt",
"type": "bytes32"
}
internalType: 'bytes32',
name: 'salt',
type: 'bytes32',
},
],
"name": "deployERC1820Implementer",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
name: 'deployERC1820Implementer',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
"inputs": [
inputs: [
{
"internalType": "address payable",
"name": "payoutAddress",
"type": "address"
}
internalType: 'address payable',
name: 'payoutAddress',
type: 'address',
},
],
"name": "killCreate2Deployer",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
name: 'killCreate2Deployer',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
"inputs": [],
"name": "owner",
"outputs": [
inputs: [],
name: 'owner',
outputs: [
{
"internalType": "address",
"name": "",
"type": "address"
}
internalType: 'address',
name: '',
type: 'address',
},
],
"stateMutability": "view",
"type": "function"
stateMutability: 'view',
type: 'function',
},
{
"inputs": [],
"name": "pause",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
inputs: [],
name: 'pause',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
"inputs": [],
"name": "paused",
"outputs": [
inputs: [],
name: 'paused',
outputs: [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
internalType: 'bool',
name: '',
type: 'bool',
},
],
"stateMutability": "view",
"type": "function"
stateMutability: 'view',
type: 'function',
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
inputs: [],
name: 'renounceOwnership',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
"inputs": [
inputs: [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
internalType: 'address',
name: 'newOwner',
type: 'address',
},
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
name: 'transferOwnership',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
"inputs": [],
"name": "unpause",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
inputs: [],
name: 'unpause',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
"stateMutability": "payable",
"type": "receive"
}
]
stateMutability: 'payable',
type: 'receive',
},
]

Loading…
Cancel
Save