Merge pull request #5600 from ethereum/delFS

delete forked state environment from env explorer
pull/5629/head
Aniket 2 weeks ago committed by GitHub
commit 74df73b3b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 13
      apps/remix-dapp/src/locales/en/udapp.json
  2. 8
      apps/remix-ide-e2e/src/tests/vm_state.test.ts
  3. 16
      apps/remix-ide/src/app/providers/environment-explorer.tsx
  4. 13
      apps/remix-ide/src/app/tabs/locales/en/udapp.json
  5. 3
      apps/remix-ide/src/blockchain/blockchain.tsx
  6. 1
      libs/remix-simulator/src/provider.ts
  7. 13
      libs/remix-ui/environment-explorer/src/lib/components/environment-explorer-ui.tsx
  8. 1
      libs/remix-ui/environment-explorer/src/lib/types/index.ts
  9. 41
      libs/remix-ui/run-tab/src/lib/components/environment.tsx

@ -50,12 +50,15 @@
"udapp.hash": "hash", "udapp.hash": "hash",
"udapp.signature": "signature", "udapp.signature": "signature",
"udapp.forkStateTitle": "Fork VM state", "udapp.forkStateTitle": "Fork VM state",
"udapp.forkStateLabel": "State Name", "udapp.forkStateLabel": "New environment name",
"udapp.forkVmStateDesc1":"Forking state will create a new environment with same state as selected environment",
"udapp.forkVmStateDesc2":"New environment will be pinned, which can be unpinned or deleted using Envionment Explorer",
"udapp.fork": "Fork", "udapp.fork": "Fork",
"udapp.deleteVmStateTitle": "Delete VM state", "udapp.resetVmStateTitle": "Reset VM state",
"udapp.deleteVmStateDesc1": "Deleting the state of this VM will delete the associated transaction details in this Workspace.", "udapp.resetVmStateDesc1": "Resetting the state of this VM will delete the associated transaction details in this Workspace.",
"udapp.deleteVmStateDesc2": "It will also delete the data of contracts deployed and pinned in this Workspace.", "udapp.resetVmStateDesc2": "It will also delete the data of contracts deployed and pinned in this Workspace.",
"udapp.deleteVmStateDesc3": "Do you want to continue?", "udapp.resetVmStateDesc3": "Do you want to continue?",
"udapp.reset": "Reset",
"udapp.delete": "Delete", "udapp.delete": "Delete",
"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.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.createNewAccount": "Create a new account",

@ -33,7 +33,7 @@ const tests = {
.click('*[data-id="delete-state-icon"]') .click('*[data-id="delete-state-icon"]')
.waitForElementVisible( .waitForElementVisible(
{ {
selector: "//*[@data-shared='tooltipPopup' and contains(.,'State not available to delete')]", selector: "//*[@data-shared='tooltipPopup' and contains(.,'State not available to reset')]",
locateStrategy: 'xpath' locateStrategy: 'xpath'
} }
) )
@ -65,7 +65,7 @@ const tests = {
// check toaster for forked state // check toaster for forked state
.waitForElementVisible( .waitForElementVisible(
{ {
selector: '//*[@data-shared="tooltipPopup" and contains(.,"VM state \'forkedState_1\' forked")]', selector: '//*[@data-shared="tooltipPopup" and contains(.,"New environment \'forkedState_1\' created with forked state.")]',
locateStrategy: 'xpath' locateStrategy: 'xpath'
} }
) )
@ -105,7 +105,7 @@ const tests = {
.setValue('input[data-id="modalDialogForkState"]', 'forkedState_2') .setValue('input[data-id="modalDialogForkState"]', 'forkedState_2')
.modalFooterOKClick('udappNotify') .modalFooterOKClick('udappNotify')
.waitForElementVisible('*[data-shared="tooltipPopup"]', 10000) .waitForElementVisible('*[data-shared="tooltipPopup"]', 10000)
.assert.textContains('*[data-shared="tooltipPopup"]', `VM state 'forkedState_2' forked and selected as current environment.`) .assert.textContains('*[data-shared="tooltipPopup"]', `New environment 'forkedState_2' created with forked state.`)
// check if 'forkedState_2' is selected as current environment // check if 'forkedState_2' is selected as current environment
.assert.elementPresent('*[data-id="selected-provider-vm-fs-forkedState_2"]') .assert.elementPresent('*[data-id="selected-provider-vm-fs-forkedState_2"]')
// check if 'forkedState_2' is present in environment explorer // check if 'forkedState_2' is present in environment explorer
@ -140,7 +140,7 @@ const tests = {
.modalFooterOKClick('udappNotify') .modalFooterOKClick('udappNotify')
.waitForElementVisible('*[data-shared="tooltipPopup"]', 10000) .waitForElementVisible('*[data-shared="tooltipPopup"]', 10000)
// check if toaster is shown // check if toaster is shown
.assert.textContains('*[data-shared="tooltipPopup"]', `VM state deleted successfully.`) .assert.textContains('*[data-shared="tooltipPopup"]', `VM state reset successfully.`)
// check that there are no instances // check that there are no instances
.assert.textContains('*[data-id="deployedContractsBadge"]', '0') .assert.textContains('*[data-id="deployedContractsBadge"]', '0')
// check if state file is deleted // check if state file is deleted

@ -78,6 +78,15 @@ export class EnvironmentExplorer extends ViewPlugin {
} }
} }
async deleteForkedState (provider) {
const providerName = await this.call('blockchain', 'getProvider')
if (providerName !== provider.name) {
await this.call('fileManager', 'remove', `.states/forked_states/${provider.displayName}.json`)
await this.call('blockchain', 'removeProvider', provider.name)
this.call('notification', 'toast', `Environment "${provider.displayName}" deleted successfully.`)
} else this.call('notification', 'toast', 'Cannot delete the current selected environment')
}
renderComponent() { renderComponent() {
this.dispatch({ this.dispatch({
...this.state ...this.state
@ -86,7 +95,12 @@ export class EnvironmentExplorer extends ViewPlugin {
updateComponent(state: EnvironmentExplorerState) { updateComponent(state: EnvironmentExplorerState) {
return (<> return (<>
<EnvironmentExplorerUI pinStateCallback={this.pinStateCallback.bind(this)} profile={profile} state={state} /> <EnvironmentExplorerUI
pinStateCallback={this.pinStateCallback.bind(this)}
deleteForkedState={this.deleteForkedState.bind(this)}
profile={profile}
state={state}
/>
</>) </>)
} }
} }

@ -50,12 +50,15 @@
"udapp.hash": "hash", "udapp.hash": "hash",
"udapp.signature": "signature", "udapp.signature": "signature",
"udapp.forkStateTitle": "Fork VM state", "udapp.forkStateTitle": "Fork VM state",
"udapp.forkStateLabel": "State Name", "udapp.forkStateLabel": "New environment name",
"udapp.forkVmStateDesc1":"Forking state will create a new environment with same state as selected environment",
"udapp.forkVmStateDesc2":"After forking, new environment will be pinned and selected automatically. It can be unpinned or deleted using Envionment Explorer",
"udapp.fork": "Fork", "udapp.fork": "Fork",
"udapp.deleteVmStateTitle": "Delete VM state", "udapp.resetVmStateTitle": "Reset VM state",
"udapp.deleteVmStateDesc1": "Deleting the state of this VM will delete the associated transaction details in this Workspace.", "udapp.resetVmStateDesc1": "Resetting the state of this VM will delete the associated transaction details in this Workspace.",
"udapp.deleteVmStateDesc2": "It will also delete the data of contracts deployed and pinned in this Workspace.", "udapp.resetVmStateDesc2": "It will also delete the data of contracts deployed and pinned in this Workspace.",
"udapp.deleteVmStateDesc3": "Do you want to continue?", "udapp.resetVmStateDesc3": "Do you want to continue?",
"udapp.reset": "Reset",
"udapp.delete": "Delete", "udapp.delete": "Delete",
"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.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.createNewAccount": "Create new account",

@ -157,7 +157,7 @@ export class Blockchain extends Plugin {
_paq.push(['trackEvent', 'blockchain', 'providerPinned', name]) _paq.push(['trackEvent', 'blockchain', 'providerPinned', name])
this.emit('providersChanged') this.emit('providersChanged')
this.changeExecutionContext({ context: name }, null, null, null) this.changeExecutionContext({ context: name }, null, null, null)
this.call('notification', 'toast', `VM state '${providerName}' forked and selected as current environment.`) this.call('notification', 'toast', `New environment '${providerName}' created with forked state.`)
}) })
this.on('environmentExplorer', 'providerUnpinned', (name, provider) => { this.on('environmentExplorer', 'providerUnpinned', (name, provider) => {
@ -687,6 +687,7 @@ export class Blockchain extends Plugin {
} }
removeProvider(name) { removeProvider(name) {
if (this.pinnedProviders.includes(name)) this.emit('shouldRemoveProviderFromUdapp', name, this.getProviderObjByName(name))
this.executionContext.removeProvider(name) this.executionContext.removeProvider(name)
this.emit('providersChanged') this.emit('providersChanged')
} }

@ -54,7 +54,6 @@ export class Provider {
pendingRequests: Array<any> pendingRequests: Array<any>
constructor (options: ProviderOptions = {} as ProviderOptions) { constructor (options: ProviderOptions = {} as ProviderOptions) {
console.log(options)
this.options = options this.options = options
this.connected = true this.connected = true
this.vmContext = new VMContext(options['fork'], options['nodeUrl'], options['blockNumber'], options['stateDb'], options['blocks']) this.vmContext = new VMContext(options['fork'], options['nodeUrl'], options['blockNumber'], options['stateDb'], options['blocks'])

@ -102,6 +102,19 @@ export const EnvironmentExplorerUI = (props: environmentExplorerUIProps) => {
}} }}
> >
<div data-id={`${provider.name}desc`}>{(section.descriptionFn && section.descriptionFn(provider)) || provider.description}</div> <div data-id={`${provider.name}desc`}>{(section.descriptionFn && section.descriptionFn(provider)) || provider.description}</div>
{ provider.isForkedState && <CustomTooltip
placement="auto"
tooltipId={`overlay-tooltip-${provider.name}`}
tooltipText="Delete Environment Immediately"
>
<span
onClick={async () => props.deleteForkedState(provider)}
className="btn btn-sm mt-1 border border-danger"
>
Delete Environment
</span>
</CustomTooltip>
}
</RemixUIGridCell> </RemixUIGridCell>
))} ))}
</RemixUIGridSection> </RemixUIGridSection>

@ -8,6 +8,7 @@ export type environmentExplorerUIProps = {
providersFlat: { [key: string]: Provider } providersFlat: { [key: string]: Provider }
pinnedProviders: string[] pinnedProviders: string[]
} }
deleteForkedState (provider: Provider): Promise<void>
pinStateCallback (provider: Provider, pinned: boolean): Promise<void> pinStateCallback (provider: Provider, pinned: boolean): Promise<void>
profile: Profile profile: Profile
} }

@ -31,6 +31,10 @@ export function EnvironmentUI(props: EnvironmentProps) {
const forkStatePrompt = (defaultName: string) => { const forkStatePrompt = (defaultName: string) => {
return ( return (
<div data-id="forkVmStateModal"> <div data-id="forkVmStateModal">
<ul className='ml-3'>
<li><FormattedMessage id="udapp.forkVmStateDesc1"/></li>
<li><FormattedMessage id="udapp.forkVmStateDesc2"/></li>
</ul>
<label id="stateName" className="form-check-label" style={{ fontWeight: 'bolder' }}> <label id="stateName" className="form-check-label" style={{ fontWeight: 'bolder' }}>
<FormattedMessage id="udapp.forkStateLabel" /> <FormattedMessage id="udapp.forkStateLabel" />
</label> </label>
@ -49,10 +53,10 @@ export function EnvironmentUI(props: EnvironmentProps) {
return ( return (
<div data-id="deleteVmStateModal"> <div data-id="deleteVmStateModal">
<ul className='ml-3'> <ul className='ml-3'>
<li><FormattedMessage id="udapp.deleteVmStateDesc1"/></li> <li><FormattedMessage id="udapp.resetVmStateDesc1"/></li>
<li><FormattedMessage id="udapp.deleteVmStateDesc2"/></li> <li><FormattedMessage id="udapp.resetVmStateDesc2"/></li>
</ul> </ul>
<FormattedMessage id="udapp.deleteVmStateDesc3"/> <FormattedMessage id="udapp.resetVmStateDesc3"/>
</div> </div>
) )
} }
@ -83,15 +87,15 @@ export function EnvironmentUI(props: EnvironmentProps) {
} else props.runTabPlugin.call('notification', 'toast', `State not available to fork, as no transactions have been made for selected environment & selected workspace.`) } else props.runTabPlugin.call('notification', 'toast', `State not available to fork, as no transactions have been made for selected environment & selected workspace.`)
} }
const deleteVmState = async() => { const resetVmState = async() => {
_paq.push(['trackEvent', 'udapp', 'deleteState', `deleteState clicked`]) _paq.push(['trackEvent', 'udapp', 'deleteState', `deleteState clicked`])
const context = currentProvider.name const context = currentProvider.name
const contextExists = await props.runTabPlugin.call('fileManager', 'exists', `.states/${context}/state.json`) const contextExists = await props.runTabPlugin.call('fileManager', 'exists', `.states/${context}/state.json`)
if (contextExists) { if (contextExists) {
props.modal( props.modal(
intl.formatMessage({ id: 'udapp.deleteVmStateTitle' }), intl.formatMessage({ id: 'udapp.resetVmStateTitle' }),
deleteVmStatePrompt(), deleteVmStatePrompt(),
intl.formatMessage({ id: 'udapp.delete' }), intl.formatMessage({ id: 'udapp.reset' }),
async () => { async () => {
const currentProvider = await props.runTabPlugin.call('blockchain', 'getCurrentProvider') const currentProvider = await props.runTabPlugin.call('blockchain', 'getCurrentProvider')
// Reset environment blocks and account data // Reset environment blocks and account data
@ -103,35 +107,28 @@ export function EnvironmentUI(props: EnvironmentProps) {
// If there are pinned contracts, delete pinned contracts folder // If there are pinned contracts, delete pinned contracts folder
const isPinnedContracts = await props.runTabPlugin.call('fileManager', 'exists', `.deploys/pinned-contracts/${context}`) const isPinnedContracts = await props.runTabPlugin.call('fileManager', 'exists', `.deploys/pinned-contracts/${context}`)
if (isPinnedContracts) await props.runTabPlugin.call('fileManager', 'remove', `.deploys/pinned-contracts/${context}`) if (isPinnedContracts) await props.runTabPlugin.call('fileManager', 'remove', `.deploys/pinned-contracts/${context}`)
props.runTabPlugin.call('notification', 'toast', `VM state deleted successfully.`) props.runTabPlugin.call('notification', 'toast', `VM state reset successfully.`)
_paq.push(['trackEvent', 'udapp', 'deleteState', `VM state deleted`]) _paq.push(['trackEvent', 'udapp', 'deleteState', `VM state reset`])
}, },
intl.formatMessage({ id: 'udapp.cancel' }), intl.formatMessage({ id: 'udapp.cancel' }),
null null
) )
} else props.runTabPlugin.call('notification', 'toast', `State not available to delete, as no transactions have been made for selected environment & selected workspace.`) } else props.runTabPlugin.call('notification', 'toast', `State not available to reset, as no transactions have been made for selected environment & selected workspace.`)
} }
const isL2 = (providerDisplayName: string) => providerDisplayName && (providerDisplayName.startsWith('L2 - Optimism') || providerDisplayName.startsWith('L2 - Arbitrum')) const isL2 = (providerDisplayName: string) => providerDisplayName && (providerDisplayName.startsWith('L2 - Optimism') || providerDisplayName.startsWith('L2 - Arbitrum'))
return ( return (
<div className="udapp_crow"> <div className="udapp_crow">
<label id="selectExEnv" className="udapp_settingsLabel"> <label id="selectExEnv" className="udapp_settingsLabel w-100">
<FormattedMessage id="udapp.environment" /> <FormattedMessage id="udapp.environment" />
<CustomTooltip placement={'auto-end'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText={<FormattedMessage id="udapp.tooltipText2" />}>
<a href="https://chainlist.org/" target="_blank">
<i className={'ml-2 fas fa-plug'} aria-hidden="true"></i>
</a>
</CustomTooltip>
<CustomTooltip placement={'auto-end'} tooltipClasses="text-wrap" tooltipId="runAndDeployAddresstooltip" tooltipText={<FormattedMessage id="udapp.environmentDocs" />}>
<a href="https://remix-ide.readthedocs.io/en/latest/run.html#environment" target="_blank" rel="noreferrer">
<i className="udapp_infoDeployAction ml-2 fas fa-info"></i>
</a>
</CustomTooltip>
{ currentProvider && currentProvider.isVM && isSaveEvmStateChecked && <CustomTooltip placement={'auto-end'} tooltipClasses="text-wrap" tooltipId="forkStatetooltip" tooltipText={<FormattedMessage id="udapp.forkStateTitle" />}> { currentProvider && currentProvider.isVM && isSaveEvmStateChecked && <CustomTooltip placement={'auto-end'} tooltipClasses="text-wrap" tooltipId="forkStatetooltip" tooltipText={<FormattedMessage id="udapp.forkStateTitle" />}>
<i className="udapp_infoDeployAction ml-2 fas fa-code-branch" style={{ cursor: 'pointer' }} onClick={forkState} data-id="fork-state-icon"></i> <i className="udapp_infoDeployAction ml-2 fas fa-code-branch" style={{ cursor: 'pointer' }} onClick={forkState} data-id="fork-state-icon"></i>
</CustomTooltip> } </CustomTooltip> }
{ currentProvider && currentProvider.isVM && isSaveEvmStateChecked && <CustomTooltip placement={'auto-end'} tooltipClasses="text-wrap" tooltipId="deleteVMStatetooltip" tooltipText={<FormattedMessage id="udapp.deleteVmStateTitle" />}> { currentProvider && currentProvider.isVM && isSaveEvmStateChecked && <CustomTooltip placement={'auto-end'} tooltipClasses="text-wrap" tooltipId="deleteVMStatetooltip" tooltipText={<FormattedMessage id="udapp.resetVmStateTitle" />}>
<i className="udapp_infoDeployAction ml-2 fas fa-trash" style={{ cursor: 'pointer' }} onClick={deleteVmState} data-id="delete-state-icon"></i> <span onClick={resetVmState} style={{ cursor: 'pointer', float: 'right', textTransform: 'none' }}>
<i className="udapp_infoDeployAction ml-2 fas fa-refresh" data-id="delete-state-icon"></i>
<span className="ml-1" style = {{ textTransform: 'none', fontSize: '13px' }}>Reset State</span>
</span>
</CustomTooltip> } </CustomTooltip> }
</label> </label>
<div className="udapp_environment" data-id={`selected-provider-${currentProvider && currentProvider.name}`}> <div className="udapp_environment" data-id={`selected-provider-${currentProvider && currentProvider.name}`}>

Loading…
Cancel
Save