From 28c0eb8abbf0090179b083d2b46e9b09a81c84a2 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 9 Dec 2024 16:43:26 +0530 Subject: [PATCH 01/26] save Vm state icon --- apps/remix-dapp/src/locales/en/udapp.json | 1 + apps/remix-ide/src/app/tabs/locales/en/udapp.json | 1 + libs/remix-ui/run-tab/src/lib/components/environment.tsx | 3 +++ 3 files changed, 5 insertions(+) diff --git a/apps/remix-dapp/src/locales/en/udapp.json b/apps/remix-dapp/src/locales/en/udapp.json index d8ade051f8..fadb2ed75b 100644 --- a/apps/remix-dapp/src/locales/en/udapp.json +++ b/apps/remix-dapp/src/locales/en/udapp.json @@ -63,6 +63,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.", diff --git a/apps/remix-ide/src/app/tabs/locales/en/udapp.json b/apps/remix-ide/src/app/tabs/locales/en/udapp.json index 8fe443a37f..d56d7087a7 100644 --- a/apps/remix-ide/src/app/tabs/locales/en/udapp.json +++ b/apps/remix-ide/src/app/tabs/locales/en/udapp.json @@ -63,6 +63,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.", diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index a0428c42a1..8e304eed14 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -38,6 +38,9 @@ export function EnvironmentUI(props: EnvironmentProps) { + }> + +
From 7c796220c37bd1eae6e895ce0cb20b0e1932a4ca Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 9 Dec 2024 16:49:13 +0530 Subject: [PATCH 02/26] show icon only for VM --- libs/remix-ui/run-tab/src/lib/components/environment.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index 8e304eed14..12cb4daf2e 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -38,9 +38,9 @@ export function EnvironmentUI(props: EnvironmentProps) { - }> + { currentProvider && currentProvider.isVM && }> - + }
From 50bc70a070ebc5cfd491bd7bdc8314f7ffd88021 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 9 Dec 2024 17:31:21 +0530 Subject: [PATCH 03/26] show modal --- apps/remix-dapp/src/locales/en/udapp.json | 2 ++ .../src/app/tabs/locales/en/udapp.json | 2 ++ .../src/lib/components/environment.tsx | 36 +++++++++++++++++-- .../run-tab/src/lib/components/settingsUI.tsx | 9 ++++- libs/remix-ui/run-tab/src/lib/types/index.ts | 1 + 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/apps/remix-dapp/src/locales/en/udapp.json b/apps/remix-dapp/src/locales/en/udapp.json index fadb2ed75b..431eb59ed4 100644 --- a/apps/remix-dapp/src/locales/en/udapp.json +++ b/apps/remix-dapp/src/locales/en/udapp.json @@ -49,6 +49,8 @@ "udapp.enterAMessageToSign": "Enter a message to sign", "udapp.hash": "hash", "udapp.signature": "signature", + "udapp.saveVmStateTitle": "Save VM state", + "udapp.saveVmStateLabel": "State Name", "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.", diff --git a/apps/remix-ide/src/app/tabs/locales/en/udapp.json b/apps/remix-ide/src/app/tabs/locales/en/udapp.json index d56d7087a7..f9c88dc1e6 100644 --- a/apps/remix-ide/src/app/tabs/locales/en/udapp.json +++ b/apps/remix-ide/src/app/tabs/locales/en/udapp.json @@ -49,6 +49,8 @@ "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.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.", diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index 12cb4daf2e..fde65572a1 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -1,6 +1,6 @@ // eslint-disable-next-line no-use-before-define import React, { useEffect } from 'react' -import { FormattedMessage } from 'react-intl' +import { FormattedMessage, useIntl } from 'react-intl' import { EnvironmentProps, Provider } from '../types' import { Dropdown } from 'react-bootstrap' import { CustomMenu, CustomToggle, CustomTooltip } from '@remix-ui/helper' @@ -23,6 +23,38 @@ export function EnvironmentUI(props: EnvironmentProps) { 'L2 - Arbitrum': 'https://bridge.arbitrum.io/' } + const intl = useIntl() + + const saveVmStatePrompt = (defaultName: string) => { + return ( +
+ + +
+ ) + } + + const saveVmState = () => { + const defaultName: string = `${currentProvider.name}_${Date.now()}` + props.modal( + intl.formatMessage({ id: 'udapp.saveVmStateTitle' }), + saveVmStatePrompt(defaultName), + intl.formatMessage({ id: 'udapp.save' }), + () => { + console.log('Saved') + }, + intl.formatMessage({ id: 'udapp.cancel' }), + null + ) + } + const isL2 = (providerDisplayName: string) => providerDisplayName && (providerDisplayName.startsWith('L2 - Optimism') || providerDisplayName.startsWith('L2 - Arbitrum')) return (
@@ -39,7 +71,7 @@ export function EnvironmentUI(props: EnvironmentProps) { { currentProvider && currentProvider.isVM && }> - + }
diff --git a/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx b/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx index 12a7da58dd..44920f33f6 100644 --- a/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx @@ -12,7 +12,14 @@ export function SettingsUI(props: SettingsProps) { return (
- + void + modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void, okBtnClass?: string, cancelBtnClass?: string) => void, } export interface NetworkProps { From 90a4ad02e23315ffdf45d1e1dd7804aa0b8c47e4 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 9 Dec 2024 18:27:08 +0530 Subject: [PATCH 04/26] save state in file in FE --- .../src/lib/components/environment.tsx | 22 +++++++++++++------ .../run-tab/src/lib/components/settingsUI.tsx | 1 + libs/remix-ui/run-tab/src/lib/types/index.ts | 1 + 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index fde65572a1..0a3643750d 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -1,11 +1,12 @@ // eslint-disable-next-line no-use-before-define -import React, { useEffect } from 'react' +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 })) @@ -24,6 +25,7 @@ export function EnvironmentUI(props: EnvironmentProps) { } const intl = useIntl() + const isSaveEvmStateChecked = props.config.get('settings/save-evm-state') const saveVmStatePrompt = (defaultName: string) => { return ( @@ -33,22 +35,28 @@ export function EnvironmentUI(props: EnvironmentProps) { vmStateName.current = e.target.value} />
) } const saveVmState = () => { - const defaultName: string = `${currentProvider.name}_${Date.now()}` + const context = currentProvider.name + vmStateName.current = `${context}_${Date.now()}` props.modal( intl.formatMessage({ id: 'udapp.saveVmStateTitle' }), - saveVmStatePrompt(defaultName), + saveVmStatePrompt(vmStateName.current), intl.formatMessage({ id: 'udapp.save' }), - () => { - console.log('Saved') + async () => { + const contextExists = await props.runTabPlugin.call('fileManager', 'exists', `.states/${context}/state.json`) + if (contextExists) { + const currentStateDb = await props.runTabPlugin.call('fileManager', 'readFile', `.states/${context}/state.json`) + await props.runTabPlugin.call('fileManager', 'writeFile', `.states/saved_states/${vmStateName.current}.json`, currentStateDb) + } }, intl.formatMessage({ id: 'udapp.cancel' }), null @@ -70,7 +78,7 @@ export function EnvironmentUI(props: EnvironmentProps) { - { currentProvider && currentProvider.isVM && }> + { currentProvider && currentProvider.isVM && isSaveEvmStateChecked && }> } diff --git a/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx b/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx index 44920f33f6..b3d9b28087 100644 --- a/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx @@ -19,6 +19,7 @@ export function SettingsUI(props: SettingsProps) { setExecutionContext={props.setExecutionContext} checkSelectionCorrectness={props.EvaluateEnvironmentSelection} modal={props.modal} + config={props.runTabPlugin.config} /> 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 { From da5b57d9e0150636f1096b562259bebfc6faf361 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 10 Dec 2024 15:21:43 +0530 Subject: [PATCH 05/26] save timestamp --- libs/remix-ui/run-tab/src/lib/components/environment.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index 0a3643750d..86b14528fc 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -54,8 +54,11 @@ export function EnvironmentUI(props: EnvironmentProps) { async () => { const contextExists = await props.runTabPlugin.call('fileManager', 'exists', `.states/${context}/state.json`) if (contextExists) { - const currentStateDb = await props.runTabPlugin.call('fileManager', 'readFile', `.states/${context}/state.json`) - await props.runTabPlugin.call('fileManager', 'writeFile', `.states/saved_states/${vmStateName.current}.json`, currentStateDb) + let currentStateDb = await props.runTabPlugin.call('fileManager', 'readFile', `.states/${context}/state.json`) + currentStateDb = JSON.parse(currentStateDb) + currentStateDb.savingTimestamp = Date.now() + await props.runTabPlugin.call('fileManager', 'writeFile', `.states/saved_states/${vmStateName.current}.json`, JSON.stringify(currentStateDb, null, 2)) + props.runTabPlugin.call('notification', 'toast', `VM state ${vmStateName.current} saved.`) } }, intl.formatMessage({ id: 'udapp.cancel' }), From b7366a5eb24ee7ec40176ee15c1706c6c8243433 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 10 Dec 2024 17:15:01 +0530 Subject: [PATCH 06/26] list saved states --- .../app/providers/environment-explorer.tsx | 42 +++++++++++++++++++ .../src/lib/components/environment.tsx | 1 + 2 files changed, 43 insertions(+) diff --git a/apps/remix-ide/src/app/providers/environment-explorer.tsx b/apps/remix-ide/src/app/providers/environment-explorer.tsx index 8f25793db9..1b612d0ac0 100644 --- a/apps/remix-ide/src/app/providers/environment-explorer.tsx +++ b/apps/remix-ide/src/app/providers/environment-explorer.tsx @@ -30,6 +30,7 @@ type ProvidersSection = `Injected` | 'Remix VMs' | 'Externals' | 'Remix forked V export class EnvironmentExplorer extends ViewPlugin { providers: { [key in ProvidersSection]: Provider[] } providersFlat: { [key: string]: Provider } + savedStates pinnedProviders: string[] dispatch: React.Dispatch = () => {} @@ -42,11 +43,27 @@ export class EnvironmentExplorer extends ViewPlugin { 'Remix forked VMs': [], 'Externals': [] } + this.savedStates = [] } async onActivation(): Promise { this.providersFlat = await this.call('blockchain', 'getAllProviders') this.pinnedProviders = await this.call('blockchain', 'getPinnedProviders') + 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) + if (savedStatesFiles.length) this.savedStates = [] + for (const filePath of savedStatesFiles) { + let stateDetail = await this.call('fileManager', 'readFile', filePath) + stateDetail = JSON.parse(stateDetail) + this.savedStates.push({ + name: stateDetail.stateName, + latestBlock: stateDetail.latestBlockNumber, + timestamp: stateDetail.savingTimestamp + }) + } + } else this.savedStates = [] this.renderComponent() } @@ -171,6 +188,31 @@ export class EnvironmentExplorer extends ViewPlugin {
{provider.description}
})} + {this.savedStates && this.savedStates.length > 0 && ({this.savedStates.map(state => { + return { + console.log('pinned') + } + } + > +
Latest Block: {state.latestBlock}
+
Saved at: {(new Date(state.timestamp)).toDateString()}
+
+ })} + +
) + } Date: Wed, 11 Dec 2024 18:24:34 +0530 Subject: [PATCH 07/26] list as provider --- .../app/providers/environment-explorer.tsx | 64 +++++++++---------- apps/remix-ide/src/app/udapp/run-tab.tsx | 53 ++++++++++----- apps/remix-ide/src/blockchain/blockchain.tsx | 1 + .../src/lib/components/environment.tsx | 1 + 4 files changed, 71 insertions(+), 48 deletions(-) diff --git a/apps/remix-ide/src/app/providers/environment-explorer.tsx b/apps/remix-ide/src/app/providers/environment-explorer.tsx index 1b612d0ac0..c97436b928 100644 --- a/apps/remix-ide/src/app/providers/environment-explorer.tsx +++ b/apps/remix-ide/src/app/providers/environment-explorer.tsx @@ -25,7 +25,7 @@ const profile = { methods: [] } -type ProvidersSection = `Injected` | 'Remix VMs' | 'Externals' | 'Remix forked VMs' +type ProvidersSection = `Injected` | 'Remix VMs' | 'Externals' | 'Remix forked VMs' | 'Saved VM States' export class EnvironmentExplorer extends ViewPlugin { providers: { [key in ProvidersSection]: Provider[] } @@ -40,6 +40,7 @@ export class EnvironmentExplorer extends ViewPlugin { this.providers = { 'Injected': [], 'Remix VMs': [], + 'Saved VM States': [], 'Remix forked VMs': [], 'Externals': [] } @@ -49,21 +50,6 @@ export class EnvironmentExplorer extends ViewPlugin { async onActivation(): Promise { this.providersFlat = await this.call('blockchain', 'getAllProviders') this.pinnedProviders = await this.call('blockchain', 'getPinnedProviders') - 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) - if (savedStatesFiles.length) this.savedStates = [] - for (const filePath of savedStatesFiles) { - let stateDetail = await this.call('fileManager', 'readFile', filePath) - stateDetail = JSON.parse(stateDetail) - this.savedStates.push({ - name: stateDetail.stateName, - latestBlock: stateDetail.latestBlockNumber, - timestamp: stateDetail.savingTimestamp - }) - } - } else this.savedStates = [] this.renderComponent() } @@ -74,6 +60,8 @@ export class EnvironmentExplorer extends ViewPlugin { this.providers['Remix forked VMs'].push(provider) } else if (provider.isVM) { this.providers['Remix VMs'].push(provider) + } else if (provider.isSavedState) { + this.providers['Saved VM States'].push(provider) } else { this.providers['Externals'].push(provider) } @@ -101,6 +89,7 @@ export class EnvironmentExplorer extends ViewPlugin { this.providers = { 'Injected': [], 'Remix VMs': [], + 'Saved VM States': [], 'Externals': [], 'Remix forked VMs': [] } @@ -188,31 +177,42 @@ export class EnvironmentExplorer extends ViewPlugin {
{provider.description}
})}
- {this.savedStates && this.savedStates.length > 0 && ({this.savedStates.map(state => { + >{this.providers['Saved VM States'].map(provider => { + const {latestBlock, timestamp} = JSON.parse(provider.description) return { - console.log('pinned') - } - } + 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 + } + }} > -
Latest Block: {state.latestBlock}
-
Saved at: {(new Date(state.timestamp)).toDateString()}
+
Latest Block: {latestBlock}
+
Saved at: {(new Date(timestamp)).toDateString()}
- })} - -
) - } + })} { + const addProvider = async (position, name, displayName, isInjected, isVM, isSavedState, fork = '', dataId = '', title = '', forkedVM = false) => { await this.call('blockchain', 'addProvider', { position, options: {}, @@ -191,6 +191,7 @@ export class RunTab extends ViewPlugin { isInjected, isForkedVM: forkedVM, isVM, + isSavedState, title, init: async function () { const options = await udapp.call(name, 'init') @@ -206,13 +207,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 +249,43 @@ 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 + 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) { + let stateDetail = await this.call('fileManager', 'readFile', filePath) + stateDetail = JSON.parse(stateDetail) + descriptions[stateDetail.stateName] = JSON.stringify({ + name: stateDetail.stateName, + latestBlock: stateDetail.latestBlockNumber, + timestamp: stateDetail.savingTimestamp + }) + await addProvider(pos + 1, stateDetail.stateName, stateDetail.stateName, false, false, true, stateDetail.forkName) + } + } + }) // 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 diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index 6ccbaed7ac..0495a34993 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -55,6 +55,7 @@ export type Provider = { description?: string isInjected: boolean isVM: boolean + isSavedState: boolean isForkedVM: boolean title: string init: () => Promise diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index de60e8bedc..816d28cc45 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -57,6 +57,7 @@ export function EnvironmentUI(props: EnvironmentProps) { 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.call('notification', 'toast', `VM state ${vmStateName.current} saved.`) From 68095ec3c1c00cfa040422f15ffa52ca2c957f16 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Thu, 12 Dec 2024 19:47:34 +0530 Subject: [PATCH 08/26] saved state provider plugin --- apps/remix-ide/src/app/providers/vm-provider.tsx | 8 ++++++++ apps/remix-ide/src/app/udapp/run-tab.tsx | 12 ++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide/src/app/providers/vm-provider.tsx b/apps/remix-ide/src/app/providers/vm-provider.tsx index f43386bbed..c978779b0d 100644 --- a/apps/remix-ide/src/app/providers/vm-provider.tsx +++ b/apps/remix-ide/src/app/providers/vm-provider.tsx @@ -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 + } +} diff --git a/apps/remix-ide/src/app/udapp/run-tab.tsx b/apps/remix-ide/src/app/udapp/run-tab.tsx index 81583ddc86..1e7d8bea7f 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.tsx +++ b/apps/remix-ide/src/app/udapp/run-tab.tsx @@ -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 || []) @@ -273,6 +272,15 @@ export class RunTab extends ViewPlugin { latestBlock: stateDetail.latestBlockNumber, timestamp: stateDetail.savingTimestamp }) + const svsProvider = new SavedVMStateProvider({ + name: stateDetail.stateName, + displayName: stateDetail.stateName, + kind: 'provider', + description: descriptions[stateDetail.stateName], + methods: ['sendAsync', 'init'], + version: packageJson.version + }, this.blockchain, stateDetail.forkName) + this.engine.register(svsProvider) await addProvider(pos + 1, stateDetail.stateName, stateDetail.stateName, false, false, true, stateDetail.forkName) } } From 8145f49147be454616f99616d6d8fa89f0ea088b Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Thu, 12 Dec 2024 20:45:07 +0530 Subject: [PATCH 09/26] load fresh SVSprovider --- apps/remix-ide/src/app/udapp/run-tab.tsx | 11 +- apps/remix-ide/src/blockchain/blockchain.tsx | 17 +- .../src/blockchain/execution-context.js | 2 +- .../blockchain/providers/saved-vm-state.ts | 153 ++++++++++++++++++ 4 files changed, 171 insertions(+), 12 deletions(-) create mode 100644 apps/remix-ide/src/blockchain/providers/saved-vm-state.ts diff --git a/apps/remix-ide/src/app/udapp/run-tab.tsx b/apps/remix-ide/src/app/udapp/run-tab.tsx index 1e7d8bea7f..03954bbcfe 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.tsx +++ b/apps/remix-ide/src/app/udapp/run-tab.tsx @@ -267,21 +267,22 @@ export class RunTab extends ViewPlugin { for (const filePath of savedStatesFiles) { let stateDetail = await this.call('fileManager', 'readFile', filePath) stateDetail = JSON.parse(stateDetail) - descriptions[stateDetail.stateName] = JSON.stringify({ - name: stateDetail.stateName, + const providerName = 'svs-' + stateDetail.stateName + descriptions[providerName] = JSON.stringify({ + name: providerName, latestBlock: stateDetail.latestBlockNumber, timestamp: stateDetail.savingTimestamp }) const svsProvider = new SavedVMStateProvider({ - name: stateDetail.stateName, + name: providerName, displayName: stateDetail.stateName, kind: 'provider', - description: descriptions[stateDetail.stateName], + description: descriptions[providerName], methods: ['sendAsync', 'init'], version: packageJson.version }, this.blockchain, stateDetail.forkName) this.engine.register(svsProvider) - await addProvider(pos + 1, stateDetail.stateName, stateDetail.stateName, false, false, true, stateDetail.forkName) + await addProvider(pos + 1, providerName, stateDetail.stateName, false, false, true, stateDetail.forkName) } } }) diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index 0495a34993..75c89405a1 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -7,6 +7,7 @@ import { format } from 'util' import { ExecutionContext } from './execution-context' import Config from '../config' import { VMProvider } from './providers/vm' +import { SVSProvider } from './providers/saved-vm-state' import { InjectedProvider } from './providers/injected' import { NodeProvider } from './providers/node' import { execution, EventManager, helpers } from '@remix-project/remix-lib' @@ -79,7 +80,7 @@ export class Blockchain extends Plugin { } error?: string } - providers: {[key: string]: VMProvider | InjectedProvider | NodeProvider} + providers: {[key: string]: VMProvider | InjectedProvider | NodeProvider | SVSProvider} transactionContextAPI: TransactionContextAPI registeredPluginEvents: string[] defaultPinnedProviders: string[] @@ -205,9 +206,9 @@ 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['svs'] = new SVSProvider(this.executionContext) this.providers.injected = new InjectedProvider(this.executionContext) this.providers.web3 = new NodeProvider(this.executionContext, this.config) } @@ -215,6 +216,7 @@ export class Blockchain extends Plugin { getCurrentProvider() { const provider = this.getProvider() if (provider && provider.startsWith('vm')) return this.providers['vm'] + if (provider && provider.startsWith('svs')) return this.providers['svs'] if (provider && provider.startsWith('injected')) return this.providers['injected'] if (this.providers[provider]) return this.providers[provider] return this.providers.web3 // default to the common type of provider @@ -693,13 +695,16 @@ 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 contextExists = await this.call('fileManager', 'exists', `.states/saved_states/${context.replace('svs-', '')}.json`) + if (contextExists) { + const stateDb = await this.call('fileManager', 'readFile', `.states/saved_states/${context.replace('svs-', '')}.json`) + await this.getCurrentProvider().resetEnvironment(stateDb) + } else await this.getCurrentProvider().resetEnvironment() } } else { await this.getCurrentProvider().resetEnvironment() diff --git a/apps/remix-ide/src/blockchain/execution-context.js b/apps/remix-ide/src/blockchain/execution-context.js index cf82b96ad8..c291c71d0b 100644 --- a/apps/remix-ide/src/blockchain/execution-context.js +++ b/apps/remix-ide/src/blockchain/execution-context.js @@ -58,7 +58,7 @@ export class ExecutionContext { } isVM () { - return this.executionContext.startsWith('vm') + return this.executionContext.startsWith('vm') || this.executionContext.startsWith('svs') } setWeb3 (context, web3) { diff --git a/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts b/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts new file mode 100644 index 0000000000..774c7fdca6 --- /dev/null +++ b/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts @@ -0,0 +1,153 @@ +import { Web3, FMT_BYTES, FMT_NUMBER, LegacySendAsyncProvider, LegacyRequestProvider } from 'web3' +import { fromWei, toBigInt } from 'web3-utils' +import { privateToAddress, hashPersonalMessage, isHexString, bytesToHex } from '@ethereumjs/util' +import { extend, JSONRPCRequestPayload, JSONRPCResponseCallback } from '@remix-project/remix-simulator' +import { ExecutionContext } from '../execution-context' + +export class SVSProvider { + executionContext: ExecutionContext + web3: Web3 + worker: Worker + provider: { + sendAsync: (query: JSONRPCRequestPayload, callback: JSONRPCResponseCallback) => void + request: (query: JSONRPCRequestPayload) => Promise + } + newAccountCallback: {[stamp: number]: (error: Error, address: string) => void} + constructor (executionContext: ExecutionContext) { + this.executionContext = executionContext + this.worker = null + this.provider = null + this.newAccountCallback = {} + } + + getAccounts (cb) { + this.web3.eth.getAccounts() + .then(accounts => cb(null, accounts)) + .catch(err => { + cb('No accounts?') + }) + } + + async resetEnvironment (stringifiedState?: string) { + if (this.worker) this.worker.terminate() + this.worker = new Worker(new URL('./worker-vm', import.meta.url)) + const provider = this.executionContext.getProviderObject() + + let incr = 0 + const stamps = {} + + return new Promise((resolve, reject) => { + this.worker.addEventListener('message', (msg) => { + if (msg.data.cmd === 'requestResult' && stamps[msg.data.stamp]) { + if (msg.data.error) { + stamps[msg.data.stamp].reject(msg.data.error) + } else { + stamps[msg.data.stamp].resolve(msg.data.result) + } + } else if (msg.data.cmd === 'sendAsyncResult' && stamps[msg.data.stamp]) { + if (stamps[msg.data.stamp].callback) { + stamps[msg.data.stamp].callback(msg.data.error, msg.data.result) + return + } + if (msg.data.error) { + stamps[msg.data.stamp].reject(msg.data.error) + } else { + stamps[msg.data.stamp].resolve(msg.data.result) + } + } else if (msg.data.cmd === 'initiateResult') { + if (!msg.data.error) { + this.provider = { + sendAsync: (query, callback) => { + return new Promise((resolve, reject) => { + const stamp = Date.now() + incr + incr++ + stamps[stamp] = { callback, resolve, reject } + this.worker.postMessage({ cmd: 'sendAsync', query, stamp }) + }) + }, + request: (query) => { + return new Promise((resolve, reject) => { + const stamp = Date.now() + incr + incr++ + stamps[stamp] = { resolve, reject } + this.worker.postMessage({ cmd: 'request', query, stamp }) + }) + } + } + this.web3 = new Web3(this.provider as (LegacySendAsyncProvider | LegacyRequestProvider)) + this.web3.setConfig({ defaultTransactionType: '0x0' }) + extend(this.web3) + this.executionContext.setWeb3(this.executionContext.getProvider(), this.web3) + resolve({}) + } else { + reject(new Error(msg.data.error)) + } + } else if (msg.data.cmd === 'newAccountResult') { + if (this.newAccountCallback[msg.data.stamp]) { + this.newAccountCallback[msg.data.stamp](msg.data.error, msg.data.result) + delete this.newAccountCallback[msg.data.stamp] + } + } + }) + if (stringifiedState) { + try { + const blockchainState = JSON.parse(stringifiedState) + const blockNumber = parseInt(blockchainState.latestBlockNumber, 16) + console.log('blockNumber-in resetEnvironment-->', blockNumber) + const stateDb = blockchainState.db + + this.worker.postMessage({ + cmd: 'init', + fork: this.executionContext.getCurrentFork(), + nodeUrl: provider?.options['nodeUrl'], + blockNumber, + stateDb, + blocks: blockchainState.blocks + }) + } catch (e) { + console.error(e) + } + } else { + this.worker.postMessage({ + cmd: 'init', + fork: this.executionContext.getCurrentFork(), + nodeUrl: provider?.options['nodeUrl'], + blockNumber: provider?.options['blockNumber'] + }) + } + }) + } + + // TODO: is still here because of the plugin API + // can be removed later when we update the API + createVMAccount (newAccount) { + const { privateKey, balance } = newAccount + this.worker.postMessage({ cmd: 'addAccount', privateKey: privateKey, balance }) + const privKey = Buffer.from(privateKey, 'hex') + return bytesToHex(privateToAddress(privKey)) + } + + newAccount (_passwordPromptCb, cb) { + const stamp = Date.now() + this.newAccountCallback[stamp] = cb + this.worker.postMessage({ cmd: 'newAccount', stamp }) + } + + async getBalanceInEther (address) { + const balance = await this.web3.eth.getBalance(address, undefined, { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX }) + const balInString = toBigInt(balance).toString(10) + return balInString === '0' ? balInString : fromWei(balInString, 'ether') + } + + getGasPrice (cb) { + this.web3.eth.getGasPrice().then((result => cb(null, result))).catch((error) => cb(error)) + } + + signMessage (message, account, _passphrase, cb) { + const messageHash = hashPersonalMessage(Buffer.from(message)) + message = isHexString(message) ? message : Web3.utils.utf8ToHex(message) + this.web3.eth.sign(message, account) + .then(signedData => cb(null, bytesToHex(messageHash), signedData)) + .catch(error => cb(error)) + } +} From 42ad8fad3946f8d23c94e65f9bbd8e32a321dfcd Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Thu, 12 Dec 2024 21:56:12 +0530 Subject: [PATCH 10/26] fix linting --- libs/remix-ui/run-tab/src/lib/components/environment.tsx | 6 +++--- libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index 816d28cc45..785a5e3c7e 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -31,8 +31,8 @@ export function EnvironmentUI(props: EnvironmentProps) { return (
+ + { currentProvider && currentProvider.isVM && isSaveEvmStateChecked && }> - + }
diff --git a/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx b/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx index b3d9b28087..733c867205 100644 --- a/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx @@ -12,12 +12,12 @@ export function SettingsUI(props: SettingsProps) { return (
- From aa3e1d9fa315261897dd32bf3cbb3a549f3cf4df Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 16 Dec 2024 15:52:27 +0530 Subject: [PATCH 11/26] save and load state --- apps/remix-ide/src/blockchain/blockchain.tsx | 20 ++++++++++++++++--- .../blockchain/providers/saved-vm-state.ts | 1 - 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index 75c89405a1..c98f9c6351 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -958,8 +958,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('svs')) { + const stateName = provider.replace('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) } @@ -991,7 +1006,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 diff --git a/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts b/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts index 774c7fdca6..b23c2d93ca 100644 --- a/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts +++ b/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts @@ -93,7 +93,6 @@ export class SVSProvider { try { const blockchainState = JSON.parse(stringifiedState) const blockNumber = parseInt(blockchainState.latestBlockNumber, 16) - console.log('blockNumber-in resetEnvironment-->', blockNumber) const stateDb = blockchainState.db this.worker.postMessage({ From 28f4e03705b203241d37db9b6d8f8169382a5920 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 16 Dec 2024 16:27:30 +0530 Subject: [PATCH 12/26] fix provider loading --- apps/remix-ide/src/blockchain/blockchain.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index c98f9c6351..e034d18858 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -590,10 +590,8 @@ export class Blockchain extends Plugin { } web3() { - const isVM = this.executionContext.isVM() - if (isVM) { - return (this.providers.vm as VMProvider).web3 - } + if (this.executionContext.executionContext.startsWith('vm-')) return (this.providers.vm as VMProvider).web3 + else if (this.executionContext.executionContext.startsWith('svs-')) return (this.providers.svs as SVSProvider).web3 return this.executionContext.web3() } From a86296d8d1471bee592f6a1a05bb8f832f0ae0c9 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 16 Dec 2024 16:38:31 +0530 Subject: [PATCH 13/26] fix linting --- .../app/providers/environment-explorer.tsx | 2 +- apps/remix-ide/src/app/udapp/run-tab.tsx | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/remix-ide/src/app/providers/environment-explorer.tsx b/apps/remix-ide/src/app/providers/environment-explorer.tsx index c97436b928..1765aaf938 100644 --- a/apps/remix-ide/src/app/providers/environment-explorer.tsx +++ b/apps/remix-ide/src/app/providers/environment-explorer.tsx @@ -182,7 +182,7 @@ export class EnvironmentExplorer extends ViewPlugin { title='Deploy to an In-browser Saved VM State.' hScrollable={false} >{this.providers['Saved VM States'].map(provider => { - const {latestBlock, timestamp} = JSON.parse(provider.description) + const { latestBlock, timestamp } = JSON.parse(provider.description) return Date: Mon, 16 Dec 2024 17:23:29 +0530 Subject: [PATCH 14/26] improve svs details --- .../src/app/providers/environment-explorer.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/remix-ide/src/app/providers/environment-explorer.tsx b/apps/remix-ide/src/app/providers/environment-explorer.tsx index 1765aaf938..facc93e4d8 100644 --- a/apps/remix-ide/src/app/providers/environment-explorer.tsx +++ b/apps/remix-ide/src/app/providers/environment-explorer.tsx @@ -1,6 +1,6 @@ import React from 'react' // eslint-disable-line import { ViewPlugin } from '@remixproject/engine-web' -import { PluginViewWrapper } from '@remix-ui/helper' +import { CustomTooltip, 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' @@ -30,7 +30,6 @@ type ProvidersSection = `Injected` | 'Remix VMs' | 'Externals' | 'Remix forked V export class EnvironmentExplorer extends ViewPlugin { providers: { [key in ProvidersSection]: Provider[] } providersFlat: { [key: string]: Provider } - savedStates pinnedProviders: string[] dispatch: React.Dispatch = () => {} @@ -44,7 +43,6 @@ export class EnvironmentExplorer extends ViewPlugin { 'Remix forked VMs': [], 'Externals': [] } - this.savedStates = [] } async onActivation(): Promise { @@ -209,8 +207,14 @@ export class EnvironmentExplorer extends ViewPlugin { } }} > -
Latest Block: {latestBlock}
-
Saved at: {(new Date(timestamp)).toDateString()}
+
Latest Block: {parseInt(latestBlock)}
+ +
Saved at: {(new Date(timestamp)).toDateString()}
+
})} Date: Mon, 16 Dec 2024 18:03:53 +0530 Subject: [PATCH 15/26] extend vmp --- .../blockchain/providers/saved-vm-state.ts | 153 +----------------- 1 file changed, 2 insertions(+), 151 deletions(-) diff --git a/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts b/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts index b23c2d93ca..08be7e78a0 100644 --- a/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts +++ b/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts @@ -1,152 +1,3 @@ -import { Web3, FMT_BYTES, FMT_NUMBER, LegacySendAsyncProvider, LegacyRequestProvider } from 'web3' -import { fromWei, toBigInt } from 'web3-utils' -import { privateToAddress, hashPersonalMessage, isHexString, bytesToHex } from '@ethereumjs/util' -import { extend, JSONRPCRequestPayload, JSONRPCResponseCallback } from '@remix-project/remix-simulator' -import { ExecutionContext } from '../execution-context' +import { VMProvider } from './vm' -export class SVSProvider { - executionContext: ExecutionContext - web3: Web3 - worker: Worker - provider: { - sendAsync: (query: JSONRPCRequestPayload, callback: JSONRPCResponseCallback) => void - request: (query: JSONRPCRequestPayload) => Promise - } - newAccountCallback: {[stamp: number]: (error: Error, address: string) => void} - constructor (executionContext: ExecutionContext) { - this.executionContext = executionContext - this.worker = null - this.provider = null - this.newAccountCallback = {} - } - - getAccounts (cb) { - this.web3.eth.getAccounts() - .then(accounts => cb(null, accounts)) - .catch(err => { - cb('No accounts?') - }) - } - - async resetEnvironment (stringifiedState?: string) { - if (this.worker) this.worker.terminate() - this.worker = new Worker(new URL('./worker-vm', import.meta.url)) - const provider = this.executionContext.getProviderObject() - - let incr = 0 - const stamps = {} - - return new Promise((resolve, reject) => { - this.worker.addEventListener('message', (msg) => { - if (msg.data.cmd === 'requestResult' && stamps[msg.data.stamp]) { - if (msg.data.error) { - stamps[msg.data.stamp].reject(msg.data.error) - } else { - stamps[msg.data.stamp].resolve(msg.data.result) - } - } else if (msg.data.cmd === 'sendAsyncResult' && stamps[msg.data.stamp]) { - if (stamps[msg.data.stamp].callback) { - stamps[msg.data.stamp].callback(msg.data.error, msg.data.result) - return - } - if (msg.data.error) { - stamps[msg.data.stamp].reject(msg.data.error) - } else { - stamps[msg.data.stamp].resolve(msg.data.result) - } - } else if (msg.data.cmd === 'initiateResult') { - if (!msg.data.error) { - this.provider = { - sendAsync: (query, callback) => { - return new Promise((resolve, reject) => { - const stamp = Date.now() + incr - incr++ - stamps[stamp] = { callback, resolve, reject } - this.worker.postMessage({ cmd: 'sendAsync', query, stamp }) - }) - }, - request: (query) => { - return new Promise((resolve, reject) => { - const stamp = Date.now() + incr - incr++ - stamps[stamp] = { resolve, reject } - this.worker.postMessage({ cmd: 'request', query, stamp }) - }) - } - } - this.web3 = new Web3(this.provider as (LegacySendAsyncProvider | LegacyRequestProvider)) - this.web3.setConfig({ defaultTransactionType: '0x0' }) - extend(this.web3) - this.executionContext.setWeb3(this.executionContext.getProvider(), this.web3) - resolve({}) - } else { - reject(new Error(msg.data.error)) - } - } else if (msg.data.cmd === 'newAccountResult') { - if (this.newAccountCallback[msg.data.stamp]) { - this.newAccountCallback[msg.data.stamp](msg.data.error, msg.data.result) - delete this.newAccountCallback[msg.data.stamp] - } - } - }) - if (stringifiedState) { - try { - const blockchainState = JSON.parse(stringifiedState) - const blockNumber = parseInt(blockchainState.latestBlockNumber, 16) - const stateDb = blockchainState.db - - this.worker.postMessage({ - cmd: 'init', - fork: this.executionContext.getCurrentFork(), - nodeUrl: provider?.options['nodeUrl'], - blockNumber, - stateDb, - blocks: blockchainState.blocks - }) - } catch (e) { - console.error(e) - } - } else { - this.worker.postMessage({ - cmd: 'init', - fork: this.executionContext.getCurrentFork(), - nodeUrl: provider?.options['nodeUrl'], - blockNumber: provider?.options['blockNumber'] - }) - } - }) - } - - // TODO: is still here because of the plugin API - // can be removed later when we update the API - createVMAccount (newAccount) { - const { privateKey, balance } = newAccount - this.worker.postMessage({ cmd: 'addAccount', privateKey: privateKey, balance }) - const privKey = Buffer.from(privateKey, 'hex') - return bytesToHex(privateToAddress(privKey)) - } - - newAccount (_passwordPromptCb, cb) { - const stamp = Date.now() - this.newAccountCallback[stamp] = cb - this.worker.postMessage({ cmd: 'newAccount', stamp }) - } - - async getBalanceInEther (address) { - const balance = await this.web3.eth.getBalance(address, undefined, { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX }) - const balInString = toBigInt(balance).toString(10) - return balInString === '0' ? balInString : fromWei(balInString, 'ether') - } - - getGasPrice (cb) { - this.web3.eth.getGasPrice().then((result => cb(null, result))).catch((error) => cb(error)) - } - - signMessage (message, account, _passphrase, cb) { - const messageHash = hashPersonalMessage(Buffer.from(message)) - message = isHexString(message) ? message : Web3.utils.utf8ToHex(message) - this.web3.eth.sign(message, account) - .then(signedData => cb(null, bytesToHex(messageHash), signedData)) - .catch(error => cb(error)) - } -} +export class SVSProvider extends VMProvider {} From d83dd0a95b8f6cd199110c89c54c5c3e79b4d565 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 16 Dec 2024 18:54:05 +0530 Subject: [PATCH 16/26] add provider on saved state --- apps/remix-ide/src/app/udapp/run-tab.tsx | 27 ++++++++++++------- .../src/lib/components/environment.tsx | 1 + 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/apps/remix-ide/src/app/udapp/run-tab.tsx b/apps/remix-ide/src/app/udapp/run-tab.tsx index d2d557ab33..564d100a94 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.tsx +++ b/apps/remix-ide/src/app/udapp/run-tab.tsx @@ -258,14 +258,8 @@ export class RunTab extends ViewPlugin { await addProvider(4, 'vm-custom-fork', 'Remix VM - Custom fork', false, true, false, '', 'settingsVMCustomMode', titleVM, true) // Saved VM States - 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) - const pos = 10 - for (const filePath of savedStatesFiles) { - let stateDetail = await this.call('fileManager', 'readFile', filePath) + const addSVSProvider = async(stateFilePath, pos) => { + let stateDetail = await this.call('fileManager', 'readFile', stateFilePath) stateDetail = JSON.parse(stateDetail) const providerName = 'svs-' + stateDetail.stateName descriptions[providerName] = JSON.stringify({ @@ -282,11 +276,26 @@ export class RunTab extends ViewPlugin { version: packageJson.version }, this.blockchain, stateDetail.forkName) this.engine.register(svsProvider) - await addProvider(pos + 1, providerName, stateDetail.stateName, false, false, true, stateDetail.forkName) + 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, false) diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index 785a5e3c7e..aad3b65c01 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -60,6 +60,7 @@ export function EnvironmentUI(props: EnvironmentProps) { 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.`) } }, From 33df65b5daa765650e6f96f19681b67293b9f243 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 16 Dec 2024 19:11:57 +0530 Subject: [PATCH 17/26] remove SVSprovider --- apps/remix-ide/src/app/udapp/run-tab.tsx | 1 + apps/remix-ide/src/blockchain/blockchain.tsx | 7 +++---- apps/remix-ide/src/blockchain/providers/saved-vm-state.ts | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) delete mode 100644 apps/remix-ide/src/blockchain/providers/saved-vm-state.ts diff --git a/apps/remix-ide/src/app/udapp/run-tab.tsx b/apps/remix-ide/src/app/udapp/run-tab.tsx index 564d100a94..066825cbbd 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.tsx +++ b/apps/remix-ide/src/app/udapp/run-tab.tsx @@ -267,6 +267,7 @@ export class RunTab extends ViewPlugin { latestBlock: stateDetail.latestBlockNumber, timestamp: stateDetail.savingTimestamp }) + // Create and register provider plugin for saved states const svsProvider = new SavedVMStateProvider({ name: providerName, displayName: stateDetail.stateName, diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index e034d18858..9a8eca72d4 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -7,7 +7,6 @@ import { format } from 'util' import { ExecutionContext } from './execution-context' import Config from '../config' import { VMProvider } from './providers/vm' -import { SVSProvider } from './providers/saved-vm-state' import { InjectedProvider } from './providers/injected' import { NodeProvider } from './providers/node' import { execution, EventManager, helpers } from '@remix-project/remix-lib' @@ -80,7 +79,7 @@ export class Blockchain extends Plugin { } error?: string } - providers: {[key: string]: VMProvider | InjectedProvider | NodeProvider | SVSProvider} + providers: {[key: string]: VMProvider | InjectedProvider | NodeProvider } transactionContextAPI: TransactionContextAPI registeredPluginEvents: string[] defaultPinnedProviders: string[] @@ -208,7 +207,7 @@ export class Blockchain extends Plugin { setupProviders() { this.providers = {} this.providers['vm'] = new VMProvider(this.executionContext) - this.providers['svs'] = new SVSProvider(this.executionContext) + this.providers['svs'] = new VMProvider(this.executionContext) this.providers.injected = new InjectedProvider(this.executionContext) this.providers.web3 = new NodeProvider(this.executionContext, this.config) } @@ -591,7 +590,7 @@ export class Blockchain extends Plugin { web3() { if (this.executionContext.executionContext.startsWith('vm-')) return (this.providers.vm as VMProvider).web3 - else if (this.executionContext.executionContext.startsWith('svs-')) return (this.providers.svs as SVSProvider).web3 + else if (this.executionContext.executionContext.startsWith('svs-')) return (this.providers.svs as VMProvider).web3 return this.executionContext.web3() } diff --git a/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts b/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts deleted file mode 100644 index 08be7e78a0..0000000000 --- a/apps/remix-ide/src/blockchain/providers/saved-vm-state.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { VMProvider } from './vm' - -export class SVSProvider extends VMProvider {} From cbeb4ef158e4ad02c04636c153b0363b0707da9b Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 17 Dec 2024 13:13:02 +0530 Subject: [PATCH 18/26] remove SVS plugins from PM list --- apps/remix-ide/src/remixAppManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js index c514350909..40d64f8812 100644 --- a/apps/remix-ide/src/remixAppManager.js +++ b/apps/remix-ide/src/remixAppManager.js @@ -110,7 +110,7 @@ const isInjectedProvider = (name) => { } const isVM = (name) => { - return name.startsWith('vm') + return name.startsWith('vm') || name.startsWith('svs') } const isScriptRunner = (name) => { From 973105b85d4e334535b6ffe501013f49204a525d Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 17 Dec 2024 13:30:51 +0530 Subject: [PATCH 19/26] refactoring --- apps/remix-ide/src/app/udapp/run-tab.tsx | 2 +- apps/remix-ide/src/blockchain/blockchain.tsx | 15 ++++++++------- .../remix-ide/src/blockchain/execution-context.js | 2 +- apps/remix-ide/src/remixAppManager.js | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps/remix-ide/src/app/udapp/run-tab.tsx b/apps/remix-ide/src/app/udapp/run-tab.tsx index 066825cbbd..a4c315debe 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.tsx +++ b/apps/remix-ide/src/app/udapp/run-tab.tsx @@ -261,7 +261,7 @@ export class RunTab extends ViewPlugin { const addSVSProvider = async(stateFilePath, pos) => { let stateDetail = await this.call('fileManager', 'readFile', stateFilePath) stateDetail = JSON.parse(stateDetail) - const providerName = 'svs-' + stateDetail.stateName + const providerName = 'vm-svs-' + stateDetail.stateName descriptions[providerName] = JSON.stringify({ name: providerName, latestBlock: stateDetail.latestBlockNumber, diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index 9a8eca72d4..f0822370e2 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -207,7 +207,7 @@ export class Blockchain extends Plugin { setupProviders() { this.providers = {} this.providers['vm'] = new VMProvider(this.executionContext) - this.providers['svs'] = new VMProvider(this.executionContext) + this.providers['vm-svs'] = new VMProvider(this.executionContext) this.providers.injected = new InjectedProvider(this.executionContext) this.providers.web3 = new NodeProvider(this.executionContext, this.config) } @@ -215,7 +215,7 @@ export class Blockchain extends Plugin { getCurrentProvider() { const provider = this.getProvider() if (provider && provider.startsWith('vm')) return this.providers['vm'] - if (provider && provider.startsWith('svs')) return this.providers['svs'] + if (provider && provider.startsWith('vm-svs')) return this.providers['vm-svs'] if (provider && provider.startsWith('injected')) return this.providers['injected'] if (this.providers[provider]) return this.providers[provider] return this.providers.web3 // default to the common type of provider @@ -590,7 +590,7 @@ export class Blockchain extends Plugin { web3() { if (this.executionContext.executionContext.startsWith('vm-')) return (this.providers.vm as VMProvider).web3 - else if (this.executionContext.executionContext.startsWith('svs-')) return (this.providers.svs as VMProvider).web3 + else if (this.executionContext.executionContext.startsWith('vm-svs-')) return (this.providers['vm-svs'] as VMProvider).web3 return this.executionContext.web3() } @@ -697,9 +697,10 @@ export class Blockchain extends Plugin { await this.getCurrentProvider().resetEnvironment(stateDb) } else { // check if saved VM state is used as provider - const contextExists = await this.call('fileManager', 'exists', `.states/saved_states/${context.replace('svs-', '')}.json`) + 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/${context.replace('svs-', '')}.json`) + const stateDb = await this.call('fileManager', 'readFile', `.states/saved_states/${stateName}.json`) await this.getCurrentProvider().resetEnvironment(stateDb) } else await this.getCurrentProvider().resetEnvironment() } @@ -957,8 +958,8 @@ export class Blockchain extends Plugin { try { let state = await this.executionContext.getStateDetails() const provider = this.executionContext.getProvider() - if (provider.startsWith('svs')) { - const stateName = provider.replace('svs-', '') + 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`) diff --git a/apps/remix-ide/src/blockchain/execution-context.js b/apps/remix-ide/src/blockchain/execution-context.js index c291c71d0b..cf82b96ad8 100644 --- a/apps/remix-ide/src/blockchain/execution-context.js +++ b/apps/remix-ide/src/blockchain/execution-context.js @@ -58,7 +58,7 @@ export class ExecutionContext { } isVM () { - return this.executionContext.startsWith('vm') || this.executionContext.startsWith('svs') + return this.executionContext.startsWith('vm') } setWeb3 (context, web3) { diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js index 40d64f8812..c514350909 100644 --- a/apps/remix-ide/src/remixAppManager.js +++ b/apps/remix-ide/src/remixAppManager.js @@ -110,7 +110,7 @@ const isInjectedProvider = (name) => { } const isVM = (name) => { - return name.startsWith('vm') || name.startsWith('svs') + return name.startsWith('vm') } const isScriptRunner = (name) => { From 519e825dd6c59dc871cdc8f7d7c663a4f73af1b5 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 17 Dec 2024 13:46:16 +0530 Subject: [PATCH 20/26] more refactor --- apps/remix-ide/src/blockchain/blockchain.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index f0822370e2..d5832e9ff4 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -207,7 +207,6 @@ export class Blockchain extends Plugin { setupProviders() { this.providers = {} this.providers['vm'] = new VMProvider(this.executionContext) - this.providers['vm-svs'] = new VMProvider(this.executionContext) this.providers.injected = new InjectedProvider(this.executionContext) this.providers.web3 = new NodeProvider(this.executionContext, this.config) } @@ -215,7 +214,6 @@ export class Blockchain extends Plugin { getCurrentProvider() { const provider = this.getProvider() if (provider && provider.startsWith('vm')) return this.providers['vm'] - if (provider && provider.startsWith('vm-svs')) return this.providers['vm-svs'] if (provider && provider.startsWith('injected')) return this.providers['injected'] if (this.providers[provider]) return this.providers[provider] return this.providers.web3 // default to the common type of provider @@ -589,8 +587,10 @@ export class Blockchain extends Plugin { } web3() { - if (this.executionContext.executionContext.startsWith('vm-')) return (this.providers.vm as VMProvider).web3 - else if (this.executionContext.executionContext.startsWith('vm-svs-')) return (this.providers['vm-svs'] as VMProvider).web3 + const isVM = this.executionContext.isVM() + if (isVM) { + return (this.providers.vm as VMProvider).web3 + } return this.executionContext.web3() } From 3c844b531cd85fa81bd177a203fc6df78c8e2318 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 17 Dec 2024 14:03:37 +0530 Subject: [PATCH 21/26] add tip --- apps/remix-dapp/src/locales/en/udapp.json | 1 + apps/remix-ide/src/app/tabs/locales/en/udapp.json | 1 + libs/remix-ui/run-tab/src/lib/components/environment.tsx | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/apps/remix-dapp/src/locales/en/udapp.json b/apps/remix-dapp/src/locales/en/udapp.json index 431eb59ed4..26fd59aa95 100644 --- a/apps/remix-dapp/src/locales/en/udapp.json +++ b/apps/remix-dapp/src/locales/en/udapp.json @@ -51,6 +51,7 @@ "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.", diff --git a/apps/remix-ide/src/app/tabs/locales/en/udapp.json b/apps/remix-ide/src/app/tabs/locales/en/udapp.json index f9c88dc1e6..f54334db1e 100644 --- a/apps/remix-ide/src/app/tabs/locales/en/udapp.json +++ b/apps/remix-ide/src/app/tabs/locales/en/udapp.json @@ -51,6 +51,7 @@ "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.", diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index aad3b65c01..192bcaac6a 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -40,6 +40,10 @@ export function EnvironmentUI(props: EnvironmentProps) { className="form-control" onChange={(e) => vmStateName.current = e.target.value} /> +
+
+ Tip: +
) } From 0127280b00d307a24cd1e259307b40ea94c6bc05 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 17 Dec 2024 15:53:31 +0530 Subject: [PATCH 22/26] fix linting --- apps/remix-ide/src/app/udapp/run-tab.tsx | 36 ++++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/apps/remix-ide/src/app/udapp/run-tab.tsx b/apps/remix-ide/src/app/udapp/run-tab.tsx index a4c315debe..50493830bd 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.tsx +++ b/apps/remix-ide/src/app/udapp/run-tab.tsx @@ -260,24 +260,24 @@ export class RunTab extends ViewPlugin { // 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) + 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 () => { From 0d5a23f98d4567b7a1c30d05c689734bce6885e5 Mon Sep 17 00:00:00 2001 From: rebustron Date: Tue, 17 Dec 2024 09:57:27 +0100 Subject: [PATCH 23/26] fixed broken link constant.ts --- apps/circuit-compiler/src/app/actions/constant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circuit-compiler/src/app/actions/constant.ts b/apps/circuit-compiler/src/app/actions/constant.ts index 6dc9ffcff0..4b3dc07e0e 100644 --- a/apps/circuit-compiler/src/app/actions/constant.ts +++ b/apps/circuit-compiler/src/app/actions/constant.ts @@ -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) { From 796b4eaaa8096a77cb376874a4aa0384ad55f797 Mon Sep 17 00:00:00 2001 From: rebustron Date: Tue, 17 Dec 2024 09:58:39 +0100 Subject: [PATCH 24/26] fixed broken link plonk_verifier.sol.ejs --- .../src/templates/rln/templates/plonk_verifier.sol.ejs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ws-templates/src/templates/rln/templates/plonk_verifier.sol.ejs b/libs/remix-ws-templates/src/templates/rln/templates/plonk_verifier.sol.ejs index 8b3ed1d109..963bade7f1 100644 --- a/libs/remix-ws-templates/src/templates/rln/templates/plonk_verifier.sol.ejs +++ b/libs/remix-ws-templates/src/templates/rln/templates/plonk_verifier.sol.ejs @@ -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 { } } -} \ No newline at end of file +} From d9e244b3cb57e149d9c9323b9712bfd392031b9b Mon Sep 17 00:00:00 2001 From: rebustron Date: Tue, 17 Dec 2024 09:59:27 +0100 Subject: [PATCH 25/26] fixed broken link plonk_verifier.sol.ejs --- .../src/templates/semaphore/templates/plonk_verifier.sol.ejs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ws-templates/src/templates/semaphore/templates/plonk_verifier.sol.ejs b/libs/remix-ws-templates/src/templates/semaphore/templates/plonk_verifier.sol.ejs index 8b3ed1d109..963bade7f1 100644 --- a/libs/remix-ws-templates/src/templates/semaphore/templates/plonk_verifier.sol.ejs +++ b/libs/remix-ws-templates/src/templates/semaphore/templates/plonk_verifier.sol.ejs @@ -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 { } } -} \ No newline at end of file +} From a98f8360e233aa312b58a7cc5e3f2dd768946fe0 Mon Sep 17 00:00:00 2001 From: rebustron Date: Tue, 17 Dec 2024 10:00:08 +0100 Subject: [PATCH 26/26] fixed broken link plonk_verifier.sol.ejs --- .../templates/hashchecker/templates/plonk_verifier.sol.ejs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ws-templates/src/templates/hashchecker/templates/plonk_verifier.sol.ejs b/libs/remix-ws-templates/src/templates/hashchecker/templates/plonk_verifier.sol.ejs index 8b3ed1d109..963bade7f1 100644 --- a/libs/remix-ws-templates/src/templates/hashchecker/templates/plonk_verifier.sol.ejs +++ b/libs/remix-ws-templates/src/templates/hashchecker/templates/plonk_verifier.sol.ejs @@ -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 { } } -} \ No newline at end of file +}