Merge branch 'master' into urltest

pull/5491/head
Joseph Izang 2 months ago committed by GitHub
commit 882369043c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      apps/circuit-compiler/src/app/actions/constant.ts
  2. 2
      apps/circuit-compiler/src/app/app.tsx
  3. 2
      apps/remix-dapp/src/locales/en/terminal.json
  4. 4
      apps/remix-dapp/src/locales/en/udapp.json
  5. 229
      apps/remix-ide/src/app/providers/environment-explorer.tsx
  6. 8
      apps/remix-ide/src/app/providers/vm-provider.tsx
  7. 2
      apps/remix-ide/src/app/tabs/locale-module.js
  8. 4
      apps/remix-ide/src/app/tabs/locales/en/udapp.json
  9. 76
      apps/remix-ide/src/app/udapp/run-tab.tsx
  10. 40
      apps/remix-ide/src/blockchain/blockchain.tsx
  11. 8
      apps/remix-ide/team-best-practices.md
  12. 2
      libs/remix-ui/environment-explorer/src/index.ts
  13. 111
      libs/remix-ui/environment-explorer/src/lib/components/environment-explorer-ui.tsx
  14. 45
      libs/remix-ui/environment-explorer/src/lib/types/index.ts
  15. 1
      libs/remix-ui/grid-view/src/lib/remix-ui-grid-cell.css
  16. 8
      libs/remix-ui/grid-view/src/lib/remix-ui-grid-cell.tsx
  17. 57
      libs/remix-ui/run-tab/src/lib/components/environment.tsx
  18. 10
      libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx
  19. 2
      libs/remix-ui/run-tab/src/lib/types/index.ts
  20. 4
      libs/remix-ws-templates/src/templates/hashchecker/templates/plonk_verifier.sol.ejs
  21. 4
      libs/remix-ws-templates/src/templates/rln/templates/plonk_verifier.sol.ejs
  22. 4
      libs/remix-ws-templates/src/templates/semaphore/templates/plonk_verifier.sol.ejs
  23. 2
      release-process.md
  24. 5
      tsconfig.paths.json

@ -318,7 +318,7 @@ contract PlonkVerifier {
///////
// Computes the inverse of an array of values
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
// See https://vitalik.eth.limo/general/2018/07/21/starks_part_3.html in section where explain fields operations
//////
function inverseArray(pVals, n) {

@ -144,7 +144,7 @@ function App() {
dispatch({ type: 'SET_COMPILER_FEEDBACK', payload: report })
} catch (e) {
if (process.platform === 'win32' && err.message.includes('3221225781')) return dispatch({ type: 'SET_COMPILER_FEEDBACK', payload: 'The compiler failed to start because of some missing dependecies. Please install or repair the Microsoft Visual C++ Redistributable package to resolve this issue.' })
if (process.platform === 'win32' && err.message.includes('3221225781')) return dispatch({ type: 'SET_COMPILER_FEEDBACK', payload: 'The compiler failed to start because of some missing dependencies. Please install or repair the Microsoft Visual C++ Redistributable package to resolve this issue.' })
dispatch({ type: 'SET_COMPILER_FEEDBACK', payload: err.message })
}
}

@ -15,7 +15,7 @@
"terminal.welcomeText8": "Right-click on a JavaScript file in the file explorer and then click `Run`",
"terminal.welcomeText9": "The following libraries are accessible",
"terminal.welcomeText10": "Type the library name to see available commands",
"terminal.text1": "This type of command has been deprecated and is not functionning anymore. Please run remix.help() to list available commands.",
"terminal.text1": "This type of command has been deprecated and is not functioning anymore. Please run remix.help() to list available commands.",
"terminal.hideTerminal": "Hide Terminal",
"terminal.showTerminal": "Show Terminal",
"terminal.clearConsole": "Clear console",

@ -49,6 +49,9 @@
"udapp.enterAMessageToSign": "Enter a message to sign",
"udapp.hash": "hash",
"udapp.signature": "signature",
"udapp.saveVmStateTitle": "Save VM state",
"udapp.saveVmStateLabel": "State Name",
"udapp.saveVmStateTip": "Saved VM states can be pinned as environment using Environment Explorer",
"udapp.injectedTitle": "Unfortunately it's not possible to create an account using injected provider. Please create the account directly from your provider (i.e metamask or other of the same type).",
"udapp.createNewAccount": "Create a new account",
"udapp.web3Title": "Creating an account is possible only in Personal mode. Please go to Settings to enable it.",
@ -63,6 +66,7 @@
"udapp._comment_environment.tsx": "libs/remix-ui/run-tab/src/lib/components/environment.tsx",
"udapp.environment": "Environment",
"udapp.environmentDocs": "Click for docs about Environment",
"udapp.saveVmState": "Save VM state",
"udapp.tooltipText2": "Open chainlist.org and get the connection specs of the chain you want to interact with.",
"udapp.tooltipText3": "Click to open a bridge for converting L1 mainnet ETH to the selected network currency.",

@ -1,11 +1,8 @@
import React from 'react' // eslint-disable-line
import { ViewPlugin } from '@remixproject/engine-web'
import { PluginViewWrapper } from '@remix-ui/helper'
import { RemixUIGridView } from '@remix-ui/remix-ui-grid-view'
import { RemixUIGridSection } from '@remix-ui/remix-ui-grid-section'
import { RemixUIGridCell } from '@remix-ui/remix-ui-grid-cell'
import './style/environment-explorer.css'
import type { Provider } from '../../blockchain/blockchain'
import { EnvironmentExplorerUI, Provider } from '@remix-ui/environment-explorer'
import * as packageJson from '../../../../../package.json'
@ -25,41 +22,31 @@ const profile = {
methods: []
}
type ProvidersSection = `Injected` | 'Remix VMs' | 'Externals' | 'Remix forked VMs'
type EnvironmentExplorerState = {
providersFlat: { [key: string]: Provider },
pinnedProviders: string[],
}
export class EnvironmentExplorer extends ViewPlugin {
providers: { [key in ProvidersSection]: Provider[] }
providersFlat: { [key: string]: Provider }
pinnedProviders: string[]
dispatch: React.Dispatch<any> = () => {}
dispatch: React.Dispatch<any> = () => { }
state: EnvironmentExplorerState
constructor() {
super(profile)
this.providersFlat = {}
this.providers = {
'Injected': [],
'Remix VMs': [],
'Remix forked VMs': [],
'Externals': []
this.state = {
providersFlat: {},
pinnedProviders: [],
}
}
async onActivation(): Promise<void> {
this.providersFlat = await this.call('blockchain', 'getAllProviders')
this.pinnedProviders = await this.call('blockchain', 'getPinnedProviders')
this.renderComponent()
this.on('blockchain', 'providersChanged', this.updateProviders.bind(this))
await this.updateProviders()
}
addProvider (provider: Provider) {
if (provider.isInjected) {
this.providers['Injected'].push(provider)
} else if (provider.isForkedVM) {
this.providers['Remix forked VMs'].push(provider)
} else if (provider.isVM) {
this.providers['Remix VMs'].push(provider)
} else {
this.providers['Externals'].push(provider)
}
async updateProviders() {
this.state.providersFlat = await this.call('blockchain', 'getAllProviders')
this.state.pinnedProviders = await this.call('blockchain', 'getPinnedProviders')
this.renderComponent()
}
setDispatch(dispatch: React.Dispatch<any>): void {
@ -74,172 +61,32 @@ export class EnvironmentExplorer extends ViewPlugin {
)
}
async pinStateCallback(provider: Provider, pinned: boolean) {
if (pinned) {
this.emit('providerPinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been added to the Environment list of the Deploy & Run Transactions plugin.`)
} else {
const providerName = await this.call('blockchain', 'getProvider')
if (providerName !== provider.name) {
this.emit('providerUnpinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been removed from the Environment list of the Deploy & Run Transactions plugin.`)
return true
} else {
this.call('notification', 'toast', 'Cannot unpin the current selected provider')
return false
}
}
}
renderComponent() {
this.dispatch({
...this
...this.state
})
}
updateComponent(state: any) {
this.providers = {
'Injected': [],
'Remix VMs': [],
'Externals': [],
'Remix forked VMs': []
}
for (const [key, provider] of Object.entries(this.providersFlat)) {
this.addProvider(provider)
}
return (
<RemixUIGridView
plugin={this}
styleList={""}
logo={profile.icon}
enableFilter={true}
showUntagged={true}
showPin={true}
title={profile.description}
description="Select the providers and chains to include them in the ENVIRONMENT select box of the Deploy & Run Transactions plugin."
>
<RemixUIGridSection
plugin={this}
title='Deploy using a Browser Extension.'
hScrollable={false}
>
{this.providers['Injected'].map(provider => {
return <RemixUIGridCell
plugin={this}
title={provider.displayName}
logos={provider.logos}
classList='EECellStyle'
searchKeywords={['Injected', provider.name, provider.displayName, provider.title, provider.description]}
pinned={this.pinnedProviders.includes(provider.name)}
key={provider.name}
id={provider.name}
pinStateCallback={async (pinned: boolean) => {
if (pinned) {
this.emit('providerPinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been added to the Environment list of the Deploy & Run Transactions plugin.`)
return true
}
const providerName = await this.call('blockchain', 'getProvider')
if (providerName !== provider.name) {
this.emit('providerUnpinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been removed from the Environment list of the Deploy & Run Transactions plugin.`)
return true
} else {
this.call('notification', 'toast', 'Cannot unpin the current selected provider')
return false
}
}}
>
<div>{provider.description}</div>
</RemixUIGridCell>
})}
</RemixUIGridSection>
<RemixUIGridSection
plugin={this}
title='Deploy to an In-browser Virtual Machine.'
hScrollable={false}
>{this.providers['Remix VMs'].map(provider => {
return <RemixUIGridCell
plugin={this}
title={provider.displayName}
logos={provider.logos}
classList='EECellStyle'
searchKeywords={['Remix VMs', provider.name, provider.displayName, provider.title, provider.description]}
pinned={this.pinnedProviders.includes(provider.name)}
key={provider.name}
id={provider.name}
pinStateCallback={async (pinned: boolean) => {
if (pinned) {
this.emit('providerPinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been added to the Environment list of the Deploy & Run Transactions plugin.`)
return true
}
const providerName = await this.call('blockchain', 'getProvider')
if (providerName !== provider.name) {
this.emit('providerUnpinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been removed from the Environment list of the Deploy & Run Transactions plugin.`)
return true
} else {
this.call('notification', 'toast', 'Cannot unpin the current selected provider')
return false
}
}}
>
<div>{provider.description}</div>
</RemixUIGridCell>
})}</RemixUIGridSection>
<RemixUIGridSection
plugin={this}
title='Deploy to an In-browser forked Virtual Machine.'
hScrollable={false}
>{this.providers['Remix forked VMs'].map(provider => {
return <RemixUIGridCell
plugin={this}
title={provider.displayName}
logos={provider.logos}
classList='EECellStyle'
searchKeywords={['Remix VMs', provider.name, provider.displayName, provider.title, provider.description]}
pinned={this.pinnedProviders.includes(provider.name)}
key={provider.name}
id={provider.name}
pinStateCallback={async (pinned: boolean) => {
if (pinned) {
this.emit('providerPinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been added to the Environment list of the Deploy & Run Transactions plugin.`)
return true
}
const providerName = await this.call('blockchain', 'getProvider')
if (providerName !== provider.name) {
this.emit('providerUnpinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been removed from the Environment list of the Deploy & Run Transactions plugin.`)
return true
} else {
this.call('notification', 'toast', 'Cannot unpin the current selected provider')
return false
}
}}
>
<div>{provider.description}</div>
</RemixUIGridCell>
})}</RemixUIGridSection>
<RemixUIGridSection
plugin={this}
title='Deploy to an external Provider.'
hScrollable={false}
>{this.providers['Externals'].map(provider => {
return <RemixUIGridCell
plugin={this}
title={provider.displayName}
logos={provider.logos}
classList='EECellStyle'
searchKeywords={['Externals', provider.name, provider.displayName, provider.title, provider.description]}
pinned={this.pinnedProviders.includes(provider.name)}
key={provider.name}
id={provider.name}
pinStateCallback={async (pinned: boolean) => {
if (pinned) {
this.emit('providerPinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been added to the Environment list of the Deploy & Run Transactions plugin.`)
return true
}
const providerName = await this.call('blockchain', 'getProvider')
if (providerName !== provider.name) {
this.emit('providerUnpinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been removed from the Environment list of the Deploy & Run Transactions plugin.`)
return true
} else {
this.call('notification', 'toast', 'Cannot unpin the current selected provider')
return false
}
}}
>
<div>{provider.description}</div>
</RemixUIGridCell>
})}</RemixUIGridSection>
</RemixUIGridView>
)
updateComponent(state: EnvironmentExplorerState) {
return (<>
<EnvironmentExplorerUI pinStateCallback={this.pinStateCallback.bind(this)} profile={profile} state={state} />
</>)
}
}

@ -131,3 +131,11 @@ export class CancunVMProvider extends BasicVMProvider {
this.fork = 'cancun'
}
}
export class SavedVMStateProvider extends BasicVMProvider {
constructor(profile, blockchain, fork) {
super(profile, blockchain)
this.blockchain = blockchain
this.fork = fork
}
}

@ -38,7 +38,7 @@ export class LocaleModule extends Plugin {
config: Registry.getInstance().get('config') && Registry.getInstance().get('config').api
}
this.locales = {}
locales.map((locale) => {
locales.forEach((locale) => {
this.locales[locale.code.toLocaleLowerCase()] = locale
})
this._paq = _paq

@ -49,6 +49,9 @@
"udapp.enterAMessageToSign": "Enter a message to sign and click `Sign`",
"udapp.hash": "hash",
"udapp.signature": "signature",
"udapp.saveVmStateTitle": "Save VM state",
"udapp.saveVmStateLabel": "State Name",
"udapp.saveVmStateTip": "Saved VM states can be pinned as environment using Environment Explorer",
"udapp.injectedTitle": "Unfortunately it's not possible to create an account using injected provider. Please create the account directly from your provider (i.e metamask or other of the same type).",
"udapp.createNewAccount": "Create new account",
"udapp.web3Title": "Creating an account is possible only in Personal mode. Please go to Settings to enable it.",
@ -63,6 +66,7 @@
"udapp._comment_environment.tsx": "libs/remix-ui/run-tab/src/lib/components/environment.tsx",
"udapp.environment": "Environment",
"udapp.environmentDocs": "Click for docs about Environment",
"udapp.saveVmState": "Save VM state",
"udapp.tooltipText2": "Open chainlist.org and get the connection specs of the chain you want to interact with.",
"udapp.tooltipText3": "Click to open a bridge for converting L1 mainnet ETH to the selected network currency.",

@ -9,8 +9,7 @@ import * as packageJson from '../../../../../package.json'
import { EventManager } from '@remix-project/remix-lib'
import type { Blockchain } from '../../blockchain/blockchain'
import type { CompilerArtefacts } from '@remix-project/core-plugin'
// import type { NetworkModule } from '../tabs/network-module'
// import type FileProvider from '../files/fileProvider'
import { SavedVMStateProvider } from '../providers/vm-provider'
import { Recorder } from '../tabs/runTab/model/recorder'
const _paq = (window._paq = window._paq || [])
@ -178,7 +177,7 @@ export class RunTab extends ViewPlugin {
'foundry-provider': ['assets/img/foundry.png']
}
const addProvider = async (position, name, displayName, isInjected, isVM, fork = '', dataId = '', title = '', forkedVM = false) => {
const addProvider = async (position, name, displayName, isInjected, isVM, isSavedState, fork = '', dataId = '', title = '', forkedVM = false) => {
await this.call('blockchain', 'addProvider', {
position,
options: {},
@ -191,6 +190,7 @@ export class RunTab extends ViewPlugin {
isInjected,
isForkedVM: forkedVM,
isVM,
isSavedState,
title,
init: async function () {
const options = await udapp.call(name, 'init')
@ -206,13 +206,13 @@ export class RunTab extends ViewPlugin {
const addCustomInjectedProvider = async (position, event, name, displayName, networkId, urls, nativeCurrency?) => {
// name = `${name} through ${event.detail.info.name}`
await this.engine.register([new InjectedCustomProvider(event.detail.provider, name, displayName, networkId, urls, nativeCurrency)])
await addProvider(position, name, displayName + ' - ' + event.detail.info.name, true, false)
await addProvider(position, name, displayName + ' - ' + event.detail.info.name, true, false, false)
}
const registerInjectedProvider = async (event) => {
const name = 'injected-' + event.detail.info.name
const displayName = 'Injected Provider - ' + event.detail.info.name
await this.engine.register([new InjectedProviderDefault(event.detail.provider, name)])
await addProvider(0, name, displayName, true, false)
await addProvider(0, name, displayName, true, false, false)
if (event.detail.info.name === 'MetaMask') {
await addCustomInjectedProvider(7, event, 'injected-metamask-optimism', 'L2 - Optimism', '0xa', ['https://mainnet.optimism.io'])
@ -248,23 +248,63 @@ export class RunTab extends ViewPlugin {
// VM
const titleVM = 'Execution environment is local to Remix. Data is only saved to browser memory and will vanish upon reload.'
await addProvider(1, 'vm-cancun', 'Remix VM (Cancun)', false, true, 'cancun', 'settingsVMCancunMode', titleVM)
await addProvider(50, 'vm-shanghai', 'Remix VM (Shanghai)', false, true, 'shanghai', 'settingsVMShanghaiMode', titleVM)
await addProvider(51, 'vm-paris', 'Remix VM (Paris)', false, true, 'paris', 'settingsVMParisMode', titleVM)
await addProvider(52, 'vm-london', 'Remix VM (London)', false, true, 'london', 'settingsVMLondonMode', titleVM)
await addProvider(53, 'vm-berlin', 'Remix VM (Berlin)', false, true, 'berlin', 'settingsVMBerlinMode', titleVM)
await addProvider(2, 'vm-mainnet-fork', 'Remix VM - Mainnet fork', false, true, 'cancun', 'settingsVMMainnetMode', titleVM, true)
await addProvider(3, 'vm-sepolia-fork', 'Remix VM - Sepolia fork', false, true, 'cancun', 'settingsVMSepoliaMode', titleVM, true)
await addProvider(4, 'vm-custom-fork', 'Remix VM - Custom fork', false, true, '', 'settingsVMCustomMode', titleVM, true)
await addProvider(1, 'vm-cancun', 'Remix VM (Cancun)', false, true, false, 'cancun', 'settingsVMCancunMode', titleVM)
await addProvider(50, 'vm-shanghai', 'Remix VM (Shanghai)', false, true, false, 'shanghai', 'settingsVMShanghaiMode', titleVM)
await addProvider(51, 'vm-paris', 'Remix VM (Paris)', false, true, false, 'paris', 'settingsVMParisMode', titleVM)
await addProvider(52, 'vm-london', 'Remix VM (London)', false, true, false, 'london', 'settingsVMLondonMode', titleVM)
await addProvider(53, 'vm-berlin', 'Remix VM (Berlin)', false, true, false, 'berlin', 'settingsVMBerlinMode', titleVM)
await addProvider(2, 'vm-mainnet-fork', 'Remix VM - Mainnet fork', false, true, false, 'cancun', 'settingsVMMainnetMode', titleVM, true)
await addProvider(3, 'vm-sepolia-fork', 'Remix VM - Sepolia fork', false, true, false, 'cancun', 'settingsVMSepoliaMode', titleVM, true)
await addProvider(4, 'vm-custom-fork', 'Remix VM - Custom fork', false, true, false, '', 'settingsVMCustomMode', titleVM, true)
// Saved VM States
const addSVSProvider = async(stateFilePath, pos) => {
let stateDetail = await this.call('fileManager', 'readFile', stateFilePath)
stateDetail = JSON.parse(stateDetail)
const providerName = 'vm-svs-' + stateDetail.stateName
descriptions[providerName] = JSON.stringify({
name: providerName,
latestBlock: stateDetail.latestBlockNumber,
timestamp: stateDetail.savingTimestamp
})
// Create and register provider plugin for saved states
const svsProvider = new SavedVMStateProvider({
name: providerName,
displayName: stateDetail.stateName,
kind: 'provider',
description: descriptions[providerName],
methods: ['sendAsync', 'init'],
version: packageJson.version
}, this.blockchain, stateDetail.forkName)
this.engine.register(svsProvider)
await addProvider(pos, providerName, stateDetail.stateName, false, false, true, stateDetail.forkName)
}
this.on('filePanel', 'workspaceInitializationCompleted', async () => {
const ssExists = await this.call('fileManager', 'exists', '.states/saved_states')
if (ssExists) {
const savedStatesDetails = await this.call('fileManager', 'readdir', '.states/saved_states')
const savedStatesFiles = Object.keys(savedStatesDetails)
let pos = 10
for (const filePath of savedStatesFiles) {
pos += 1
await addSVSProvider(filePath, pos)
}
}
})
this.on('udapp', 'vmStateSaved', async (stateName) => {
await addSVSProvider(`.states/saved_states/${stateName}.json`, 20)
})
// wallet connect
await addProvider(6, 'walletconnect', 'WalletConnect', false, false)
await addProvider(6, 'walletconnect', 'WalletConnect', false, false, false)
// external provider
await addProvider(10, 'basic-http-provider', 'Custom - External Http Provider', false, false)
await addProvider(20, 'hardhat-provider', 'Dev - Hardhat Provider', false, false)
await addProvider(21, 'ganache-provider', 'Dev - Ganache Provider', false, false)
await addProvider(22, 'foundry-provider', 'Dev - Foundry Provider', false, false)
await addProvider(10, 'basic-http-provider', 'Custom - External Http Provider', false, false, false)
await addProvider(20, 'hardhat-provider', 'Dev - Hardhat Provider', false, false, false)
await addProvider(21, 'ganache-provider', 'Dev - Ganache Provider', false, false, false)
await addProvider(22, 'foundry-provider', 'Dev - Foundry Provider', false, false, false)
// register injected providers

@ -55,6 +55,7 @@ export type Provider = {
description?: string
isInjected: boolean
isVM: boolean
isSavedState: boolean
isForkedVM: boolean
title: string
init: () => Promise<void>
@ -78,7 +79,7 @@ export class Blockchain extends Plugin {
}
error?: string
}
providers: {[key: string]: VMProvider | InjectedProvider | NodeProvider}
providers: {[key: string]: VMProvider | InjectedProvider | NodeProvider }
transactionContextAPI: TransactionContextAPI
registeredPluginEvents: string[]
defaultPinnedProviders: string[]
@ -145,6 +146,7 @@ export class Blockchain extends Plugin {
this.pinnedProviders.push(name)
this.call('config', 'setAppParameter', 'settings/pinned-providers', JSON.stringify(this.pinnedProviders))
_paq.push(['trackEvent', 'blockchain', 'providerPinned', name])
this.emit('providersChanged')
})
this.on('environmentExplorer', 'providerUnpinned', (name, provider) => {
@ -153,6 +155,7 @@ export class Blockchain extends Plugin {
this.pinnedProviders.splice(index, 1)
this.call('config', 'setAppParameter', 'settings/pinned-providers', JSON.stringify(this.pinnedProviders))
_paq.push(['trackEvent', 'blockchain', 'providerUnpinned', name])
this.emit('providersChanged')
})
this.call('config', 'getAppParameter', 'settings/pinned-providers').then((providers) => {
@ -204,9 +207,8 @@ export class Blockchain extends Plugin {
}
setupProviders() {
const vmProvider = new VMProvider(this.executionContext)
this.providers = {}
this.providers['vm'] = vmProvider
this.providers['vm'] = new VMProvider(this.executionContext)
this.providers.injected = new InjectedProvider(this.executionContext)
this.providers.web3 = new NodeProvider(this.executionContext, this.config)
}
@ -665,10 +667,12 @@ export class Blockchain extends Plugin {
addProvider(provider: Provider) {
if (this.pinnedProviders.includes(provider.name)) this.emit('shouldAddProvidertoUdapp', provider.name, provider)
this.executionContext.addProvider(provider)
this.emit('providersChanged')
}
removeProvider(name) {
this.executionContext.removeProvider(name)
this.emit('providersChanged')
}
getAllProviders() {
@ -692,13 +696,17 @@ export class Blockchain extends Plugin {
if (saveEvmState) {
const contextExists = await this.call('fileManager', 'exists', `.states/${context}/state.json`)
if (contextExists) {
const stateDb = await this.call('fileManager', 'readFile', `.states/${context}/state.json`)
await this.getCurrentProvider().resetEnvironment(stateDb)
} else {
await this.getCurrentProvider().resetEnvironment()
// check if saved VM state is used as provider
const stateName = context.replace('vm-svs-', '')
const contextExists = await this.call('fileManager', 'exists', `.states/saved_states/${stateName}.json`)
if (contextExists) {
const stateDb = await this.call('fileManager', 'readFile', `.states/saved_states/${stateName}.json`)
await this.getCurrentProvider().resetEnvironment(stateDb)
} else await this.getCurrentProvider().resetEnvironment()
}
} else {
await this.getCurrentProvider().resetEnvironment()
@ -952,8 +960,23 @@ export class Blockchain extends Plugin {
if (isVM) {
if (!tx.useCall && this.config.get('settings/save-evm-state')) {
try {
const state = await this.executionContext.getStateDetails()
this.call('fileManager', 'writeFile', `.states/${this.executionContext.getProvider()}/state.json`, state)
let state = await this.executionContext.getStateDetails()
const provider = this.executionContext.getProvider()
if (provider.startsWith('vm-svs-')) {
const stateName = provider.replace('vm-svs-', '')
const stateFileExists = this.call('fileManager', 'exists', `.states/saved_states/${stateName}.json`)
if (stateFileExists) {
let stateDetails = await this.call('fileManager', 'readFile', `.states/saved_states/${stateName}.json`)
stateDetails = JSON.parse(stateDetails)
state = JSON.parse(state)
state['stateName'] = stateDetails.stateName
state['forkName'] = stateDetails.forkName
state['savingTimestamp'] = stateDetails.savingTimestamp
state = JSON.stringify(state, null, 2)
}
this.call('fileManager', 'writeFile', `.states/saved_states/${stateName}.json`, state)
}
else this.call('fileManager', 'writeFile', `.states/${provider}/state.json`, state)
} catch (e) {
console.error(e)
}
@ -985,7 +1008,6 @@ export class Blockchain extends Plugin {
this.call('terminal', 'logHtml', finalLogs)
}
execResult = await this.web3().remix.getExecutionResultFromSimulator(txResult.transactionHash)
if (execResult) {
// if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value.
returnValue = execResult

@ -5,7 +5,7 @@ This document aims to address contributors best practices of the following repos
- remix-ide https://github.com/ethereum/remix-project
- remix-plugin https://github.com/ethereum/remix-plugin
This document is not in its final version, **a team meeting which aims to address new/old best practices, feedback, workflows, all kind of issues related to how the team work together occurs every 2 weeks.**
This document is not in its final version, **a team meeting which aims to address new/old best practices, feedback, workflows, all kind of issues related to how the team works together occurs every 2 weeks.**
This document link to other specialised best practices (like coding best practices).
Related links:
@ -122,9 +122,9 @@ Before starting to coding, we should ensure all devs / contributors are aware of
- A milestone should **only** contain items we are sure to finish.
- The end of a milestone trigger a new release.
- Milestone items and duration should take in account time spent in bugs fixing and support.
- Milestone items and duration should take into account time spent in bugs fixing and support.
- The team should commit to the milestone duration.
- If a dev finish early he/she can help other to push remaining tasks.
- If a dev finish early he/she can help others to push remaining tasks.
- If a dev finish early he/she can work on specifying / integrating the next milestone.
- A milestone duration is fixed at the start of the milestone (but should better not exceed 1 month).
- Progress and issues regarding a milestone are discussed on regular standups.
@ -146,7 +146,7 @@ Before starting to coding, we should ensure all devs / contributors are aware of
- After a new release we should stay in alert for possible regression and better not release on Friday at 5pm :)
### 2) Community:
- Before the official release, we should select a group of power users and invite them to test and give feedbacks.
- Before the official release, we should select a group of power users and invite them to test and give feedback.
- Users need to know upfront a new release is coming and we should prepare them for it by showcasing some new features they can expect and when it will happen (fixed date, published at least 1 week in advance).
- Whenever we have a new release we have to communicate this efficiently (twitter, reddit, ...).

@ -0,0 +1,2 @@
export * from './lib/types'
export { EnvironmentExplorerUI } from './lib/components/environment-explorer-ui'

@ -0,0 +1,111 @@
// eslint-disable-next-line no-use-before-define
import React, { useEffect, useState } from 'react'
import { environmentExplorerUIGridSections, environmentExplorerUIProps } from '../types'
import { RemixUIGridCell, RemixUIGridSection, RemixUIGridView } from '@remix-ui/remix-ui-grid-view'
import { CustomTooltip } from '@remix-ui/helper'
const defaultSections: environmentExplorerUIGridSections = {
Injected: {
title: 'Deploy using a Browser Extension.',
keywords: ['Injected'],
providers: [],
filterFn: (provider) => provider.isInjected
},
'Remix VMs': {
title: 'Deploy to an In-browser Virtual Machine.',
keywords: ['Remix VMs'],
providers: [],
filterFn: (provider) => provider.isVM
},
'Saved VM States': {
title: 'Deploy to an In-browser Saved VM State.',
keywords: ['Saved VM States'],
providers: [],
filterFn: (provider) => provider.isSavedState,
descriptionFn: (provider) => {
const { latestBlock, timestamp } = JSON.parse(provider.description)
return (
<>
<div><b>Latest Block: </b>{parseInt(latestBlock)}</div>
<CustomTooltip
placement="auto"
tooltipId="overlay-tooltip-compile"
tooltipText={`Saved at: ${(new Date(timestamp)).toLocaleString()}`}
>
<div><b>Saved at: </b>{(new Date(timestamp)).toDateString()}</div>
</CustomTooltip>
</>)
}
},
'Remix forked VMs': {
title: 'Deploy to a Remix forked Virtual Machine.',
keywords: ['Remix forked VMs'],
providers: [],
filterFn: (provider) => provider.isForkedVM
},
'Externals': {
title: 'Deploy to an external Provider.',
keywords: ['Externals'],
providers: [],
filterFn: (provider) => (!provider.isInjected && !provider.isVM && !provider.isSavedState && !provider.isForkedVM)
},
}
export const EnvironmentExplorerUI = (props: environmentExplorerUIProps) => {
const [sections, setSections] = useState(defaultSections)
const { state, pinStateCallback, profile } = props
useEffect(() => {
setSections((prevSections) => {
const newSections = { ...prevSections }
Object.keys(newSections).forEach((section) => {
newSections[section].providers = Object.values(state.providersFlat).filter(newSections[section].filterFn)
})
return newSections
})
}, [state])
return (
<>
<RemixUIGridView
plugin={null}
styleList={""}
logo={profile.icon}
enableFilter={true}
showUntagged={true}
showPin={true}
title={profile.description}
description="Select the providers and chains to include them in the ENVIRONMENT select box of the Deploy & Run Transactions plugin."
>{
Object.values(sections).length && Object.values(sections).map((section) => (
<RemixUIGridSection
plugin={this}
title={section.title}
hScrollable={false}
key={section.title}
>
{section.providers.map(provider => {
return <RemixUIGridCell
plugin={this}
title={provider.displayName}
logos={provider.logos}
classList='EECellStyle'
searchKeywords={['Injected', provider.name, provider.displayName, provider.title, provider.description]}
pinned={state.pinnedProviders.includes(provider.name)}
key={provider.name}
id={provider.name}
pinStateCallback={async (pinned: boolean) => {
await pinStateCallback(provider, pinned)
}}
>
<div>{(section.descriptionFn && section.descriptionFn(provider)) || provider.description}</div>
</RemixUIGridCell>
})}
</RemixUIGridSection>
))
}
</RemixUIGridView>
</>
)
}

@ -0,0 +1,45 @@
import { Plugin } from '@remixproject/engine'
import { Profile } from '@remixproject/plugin-utils'
export type ProvidersSection = `Injected` | 'Remix VMs' | 'Externals' | 'Remix forked VMs' | 'Saved VM States'
export type environmentExplorerUIProps = {
state: {
providersFlat: { [key: string]: Provider }
pinnedProviders: string[]
}
pinStateCallback (provider: Provider, pinned: boolean): Promise<void>
profile: Profile
}
export type environmentExplorerUIGridSection = {
title: string
keywords: string[],
providers: Provider[]
filterFn: (provider: Provider) => boolean
descriptionFn?: (provider: Provider) => string | JSX.Element | null
}
export type environmentExplorerUIGridSections = {
[key in ProvidersSection]: environmentExplorerUIGridSection
}
export type Provider = {
options: { [key: string]: string }
dataId: string
name: string
displayName: string
logo?: string,
logos?: string[],
fork: string
description?: string
isInjected: boolean
isVM: boolean
isSavedState: boolean
isForkedVM: boolean
title: string
init: () => Promise<void>
provider: {
sendAsync: (payload: any) => Promise<void>
}
}

@ -31,6 +31,7 @@
right: 0.9rem;
top: -0.7rem;
background: transparent;
z-index: 1000;
}
.remixui_grid_cell_tags {

@ -54,6 +54,12 @@ export const RemixUIGridCell = (props: RemixUIGridCellProps) => {
setAnyEnabled(enabled)
}, [filterCon, props.tagList])
useEffect(() => {
if (props.pinned!== pinned) {
setPinned(props.pinned)
}
},[props.pinned])
/*const listenOnExpand = (key) => {
if (key === props.key) setExpand(props.toggleExpandView)
console.log('expand ----> ', key)
@ -86,7 +92,7 @@ export const RemixUIGridCell = (props: RemixUIGridCellProps) => {
<img className='remixui_grid_view_logo mr-1' src={props.logo} style={{ width: '1rem', height: '1rem' }}/> :
<></>
}
{ props.logos && props.logos.map((logo) => <img className='remixui_grid_view_logo mr-1' src={logo} style={{ width: '1rem', height: '1rem' }}/>)}
{ props.logos && props.logos.map((logo, index) => <img key={index} className='remixui_grid_view_logo mr-1' src={logo} style={{ width: '1rem', height: '1rem' }}/>)}
{ props.title &&
<CustomTooltip
placement="top"

@ -1,11 +1,12 @@
// eslint-disable-next-line no-use-before-define
import React, { useEffect } from 'react'
import { FormattedMessage } from 'react-intl'
import React, { useEffect, useRef } from 'react'
import { FormattedMessage, useIntl } from 'react-intl'
import { EnvironmentProps, Provider } from '../types'
import { Dropdown } from 'react-bootstrap'
import { CustomMenu, CustomToggle, CustomTooltip } from '@remix-ui/helper'
export function EnvironmentUI(props: EnvironmentProps) {
const vmStateName = useRef('')
Object.entries(props.providers.providerList.filter((provider) => { return provider.isVM }))
Object.entries(props.providers.providerList.filter((provider) => { return provider.isInjected }))
@ -23,6 +24,55 @@ export function EnvironmentUI(props: EnvironmentProps) {
'L2 - Arbitrum': 'https://bridge.arbitrum.io/'
}
const intl = useIntl()
const isSaveEvmStateChecked = props.config.get('settings/save-evm-state')
const saveVmStatePrompt = (defaultName: string) => {
return (
<div>
<label id="wsName" className="form-check-label" style={{ fontWeight: 'bolder' }}>
<FormattedMessage id="udapp.saveVmStateLabel" />
</label>
<input
type="text"
data-id="modalDialogSaveVmState"
defaultValue={defaultName}
className="form-control"
onChange={(e) => vmStateName.current = e.target.value}
/>
<br/>
<div className='text-secondary'>
<b>Tip: </b><FormattedMessage id="udapp.saveVmStateTip" />
</div>
</div>
)
}
const saveVmState = () => {
const context = currentProvider.name
vmStateName.current = `${context}_${Date.now()}`
props.modal(
intl.formatMessage({ id: 'udapp.saveVmStateTitle' }),
saveVmStatePrompt(vmStateName.current),
intl.formatMessage({ id: 'udapp.save' }),
async () => {
const contextExists = await props.runTabPlugin.call('fileManager', 'exists', `.states/${context}/state.json`)
if (contextExists) {
let currentStateDb = await props.runTabPlugin.call('fileManager', 'readFile', `.states/${context}/state.json`)
currentStateDb = JSON.parse(currentStateDb)
currentStateDb.stateName = vmStateName.current
currentStateDb.forkName = currentProvider.fork
currentStateDb.savingTimestamp = Date.now()
await props.runTabPlugin.call('fileManager', 'writeFile', `.states/saved_states/${vmStateName.current}.json`, JSON.stringify(currentStateDb, null, 2))
props.runTabPlugin.emit('vmStateSaved', vmStateName.current)
props.runTabPlugin.call('notification', 'toast', `VM state ${vmStateName.current} saved.`)
}
},
intl.formatMessage({ id: 'udapp.cancel' }),
null
)
}
const isL2 = (providerDisplayName: string) => providerDisplayName && (providerDisplayName.startsWith('L2 - Optimism') || providerDisplayName.startsWith('L2 - Arbitrum'))
return (
<div className="udapp_crow">
@ -38,6 +88,9 @@ export function EnvironmentUI(props: EnvironmentProps) {
<i className="udapp_infoDeployAction ml-2 fas fa-info"></i>
</a>
</CustomTooltip>
{ currentProvider && currentProvider.isVM && isSaveEvmStateChecked && <CustomTooltip placement={'auto-end'} tooltipClasses="text-wrap" tooltipId="saveVMStatetooltip" tooltipText={<FormattedMessage id="udapp.saveVmState" />}>
<i className="udapp_infoDeployAction ml-2 fas fa-save" onClick={saveVmState}></i>
</CustomTooltip> }
</label>
<div className="udapp_environment" data-id={`selected-provider-${currentProvider && currentProvider.name}`}>
<Dropdown id="selectExEnvOptions" data-id="settingsSelectEnvOptions" className="udapp_selectExEnvOptions">

@ -12,7 +12,15 @@ export function SettingsUI(props: SettingsProps) {
return (
<div className="udapp_settings">
<EnvironmentUI runTabPlugin={props.runTabPlugin} selectedEnv={props.selectExEnv} providers={props.providers} setExecutionContext={props.setExecutionContext} checkSelectionCorrectness={props.EvaluateEnvironmentSelection} />
<EnvironmentUI
runTabPlugin={props.runTabPlugin}
selectedEnv={props.selectExEnv}
providers={props.providers}
setExecutionContext={props.setExecutionContext}
checkSelectionCorrectness={props.EvaluateEnvironmentSelection}
modal={props.modal}
config={props.runTabPlugin.config}
/>
<NetworkUI networkName={props.networkName} />
<AccountUI
addFile={props.addFile}

@ -171,6 +171,8 @@ export interface EnvironmentProps {
error: string
},
setExecutionContext: (executionContext: { context: string }) => void
modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void, okBtnClass?: string, cancelBtnClass?: string) => void,
config: any
}
export interface NetworkProps {

@ -152,7 +152,7 @@ contract PlonkVerifier {
///////
// Computes the inverse of an array of values
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
// See https://vitalik.eth.limo/general/2018/07/21/starks_part_3.html in section where explain fields operations
//////
function inverseArray(pVals, n) {
@ -707,4 +707,4 @@ contract PlonkVerifier {
}
}
}
}

@ -152,7 +152,7 @@ contract PlonkVerifier {
///////
// Computes the inverse of an array of values
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
// See https://vitalik.eth.limo/general/2018/07/21/starks_part_3.html in section where explain fields operations
//////
function inverseArray(pVals, n) {
@ -707,4 +707,4 @@ contract PlonkVerifier {
}
}
}
}

@ -152,7 +152,7 @@ contract PlonkVerifier {
///////
// Computes the inverse of an array of values
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
// See https://vitalik.eth.limo/general/2018/07/21/starks_part_3.html in section where explain fields operations
//////
function inverseArray(pVals, n) {
@ -707,4 +707,4 @@ contract PlonkVerifier {
}
}
}
}

@ -49,7 +49,7 @@ This command will ask for a new version.
This command uses `lerna` and is solely responsible for publishing all the remix libraries. It will ask for a new version of each library. Make sure you are logged in to NPM.
Once these commands run successfully, the version for each remix library will be updated to latest in the libs' package.json file.
Once these commands run successfully, the version for each remix library will be updated to the latest in the libs' package.json file.
- Create and merge bump PR to master

@ -183,8 +183,11 @@
"libs/remix-ai-core/src/index.ts"
],
"@remix-ui/git": [
"libs/remix-ui/git/src/index.ts"
"libs/remix-ui/git/src/index.ts"
],
"@remix-ui/environment-explorer": [
"libs/remix-ui/environment-explorer/src/index.ts"
],
"@remix-api": [
"libs/remix-api/src/index.ts"
],

Loading…
Cancel
Save