diff --git a/apps/remix-ide/src/blockchain/blockchain.js b/apps/remix-ide/src/blockchain/blockchain.js index 6399cff181..733b07899d 100644 --- a/apps/remix-ide/src/blockchain/blockchain.js +++ b/apps/remix-ide/src/blockchain/blockchain.js @@ -180,9 +180,7 @@ export class Blockchain extends Plugin { _paq.push(['trackEvent', 'blockchain', 'Deploy With Proxy', 'Proxy deployment failed: ' + error]) return this.call('terminal', 'logHtml', log) } - if (networkInfo.name === 'VM') this.config.set('vm/proxy', address) - else this.config.set(`${networkInfo.name}/${networkInfo.currentFork}/${networkInfo.id}/proxy`, address) - await this.saveDeployedContractStorageLayout(implementationContractObject, address, networkInfo) + if (networkInfo.name !== 'VM') await this.saveDeployedContractStorageLayout(implementationContractObject, address, networkInfo) _paq.push(['trackEvent', 'blockchain', 'Deploy With Proxy', 'Proxy deployment successful']) this.call('udapp', 'addInstance', addressToString(address), implementationContractObject.abi, implementationContractObject.name) } @@ -228,7 +226,7 @@ export class Blockchain extends Plugin { _paq.push(['trackEvent', 'blockchain', 'Upgrade With Proxy', 'Upgrade failed']) return this.call('terminal', 'logHtml', log) } - await this.saveDeployedContractStorageLayout(newImplementationContractObject, proxyAddress, networkInfo) + if (networkInfo.name !== 'VM') await this.saveDeployedContractStorageLayout(newImplementationContractObject, proxyAddress, networkInfo) _paq.push(['trackEvent', 'blockchain', 'Upgrade With Proxy', 'Upgrade Successful']) this.call('udapp', 'addInstance', addressToString(proxyAddress), newImplementationContractObject.abi, newImplementationContractObject.name) } diff --git a/libs/remix-ui/run-tab/src/lib/actions/deploy.ts b/libs/remix-ui/run-tab/src/lib/actions/deploy.ts index 1f90827da1..6c86901bf9 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/deploy.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/deploy.ts @@ -3,7 +3,7 @@ import { RunTab } from "../types/run-tab" import { CompilerAbstract as CompilerAbstractType } from '@remix-project/remix-solidity' import * as remixLib from '@remix-project/remix-lib' import { DeployMode, MainnetPrompt } from "../types" -import { displayNotification, displayPopUp, setDecodedResponse } from "./payload" +import { displayNotification, displayPopUp, fetchProxyDeploymentsSuccess, setDecodedResponse } from "./payload" import { addInstance } from "./actions" import { addressToString, logBuilder } from "@remix-ui/helper" import Web3 from "web3" @@ -335,4 +335,25 @@ export const isValidContractAddress = async (plugin: RunTab, address: string) => return false } } +} + +export const getNetworkProxyAddresses = async (plugin: RunTab) => { + const identifier = plugin.blockchain.networkStatus.name === 'custom' ? plugin.blockchain.networkStatus.name + '-' + plugin.blockchain.networkStatus.id : plugin.REACT_API.networkName + const networkFile: { + id: string, + network: string, + deployments: { + [proxyAddress: string]: { + date: Date, + contractName: string, + fork: string, + implementationAddress: string, + layout: any + } + }[]} = await plugin.call('fileManager', 'readdir', `.deploys/upgradeable-contracts/${identifier}/UUPS.json`) + const deployments = Object.keys(networkFile.deployments).map(proxyAddress => { + return { address: proxyAddress, date: networkFile.deployments[proxyAddress].date } + }) + + fetchProxyDeploymentsSuccess(deployments) } \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/actions/index.ts b/libs/remix-ui/run-tab/src/lib/actions/index.ts index 6fd0182d8e..48f3c7bbdd 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/index.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/index.ts @@ -6,7 +6,7 @@ import { createNewBlockchainAccount, fillAccountsList, setExecutionContext, sign import { clearInstances, clearPopUp, removeInstance, setAccount, setGasFee, setMatchPassphrasePrompt, setNetworkNameFromProvider, setPassphrasePrompt, setSelectedContract, setSendTransactionValue, setUnit, updateBaseFeePerGas, updateConfirmSettings, updateGasPrice, updateGasPriceStatus, updateMaxFee, updateMaxPriorityFee, updateScenarioPath } from './actions' -import { createInstance, getContext, getFuncABIInputs, getSelectedContract, loadAddress, runTransactions, updateInstanceBalance, syncContractsInternal, isValidContractAddress } from './deploy' +import { createInstance, getContext, getFuncABIInputs, getSelectedContract, loadAddress, runTransactions, updateInstanceBalance, syncContractsInternal, isValidContractAddress, getNetworkProxyAddresses } from './deploy' import { CompilerAbstract as CompilerAbstractType } from '@remix-project/remix-solidity' import { ContractData, FuncABI } from "@remix-project/core-plugin" import { DeployMode, MainnetPrompt } from '../types' @@ -62,4 +62,5 @@ export const getFuncABIValues = (funcABI: FuncABI) => getFuncABIInputs(plugin, f export const setNetworkName = (networkName: string) => setNetworkNameFromProvider(dispatch, networkName) export const updateSelectedContract = (contractName) => setSelectedContract(dispatch, contractName) export const syncContracts = () => syncContractsInternal(plugin) -export const isValidProxyAddress = (address: string) => isValidContractAddress(plugin, address) \ No newline at end of file +export const isValidProxyAddress = (address: string) => isValidContractAddress(plugin, address) +export const fetchProxyAddresses = () => getNetworkProxyAddresses(plugin) \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/actions/payload.ts b/libs/remix-ui/run-tab/src/lib/actions/payload.ts index 5ec29d9fb2..6ac98aef41 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/payload.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/payload.ts @@ -1,7 +1,6 @@ -import { ContractList } from '../reducers/runTab' import { ContractData } from '@remix-project/core-plugin' -import { ADD_DEPLOY_OPTION, ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_DEPLOY_OPTION, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_PROXY_ENV_ADDRESS, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE, SET_REMIXD_ACTIVATED } from '../constants' -import { DeployMode, DeployOptions } from '../types' +import { ADD_DEPLOY_OPTION, ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_DEPLOY_OPTION, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_PROXY_ENV_ADDRESS, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE, SET_REMIXD_ACTIVATED, FETCH_PROXY_DEPLOYMENTS, NEW_PROXY_DEPLOYMENT, RESET_PROXY_DEPLOYMENTS } from '../constants' +import { ContractList, DeployOptions } from '../types' export const fetchAccountsListRequest = () => { return { @@ -315,3 +314,23 @@ export const setRemixDActivated = (activated: boolean) => { type: SET_REMIXD_ACTIVATED } } + +export const fetchProxyDeploymentsSuccess = (deployments: { address: string, date: Date }[]) => { + return { + type: FETCH_PROXY_DEPLOYMENTS, + payload: deployments + } +} + +export const newProxyDeployment = (deployment: { address: string, date: Date }) => { + return { + type: NEW_PROXY_DEPLOYMENT, + payload: deployment + } +} + +export const resetProxyDeployments = () => { + return { + type: RESET_PROXY_DEPLOYMENTS, + } +} diff --git a/libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx b/libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx index 137ce28add..1af2272da5 100644 --- a/libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx @@ -23,6 +23,7 @@ export function ContractGUI (props: ContractGUIProps) { const [deployState, setDeployState] = useState<{ deploy: boolean, upgrade: boolean }>({ deploy: false, upgrade: false }) const [useLastProxy, setUseLastProxy] = useState(false) const [proxyAddress, setProxyAddress] = useState('') + const [selectedProxyAddress, setSelectedProxyAddress] = useState('') const [proxyAddressError, setProxyAddressError] = useState('') const multiFields = useRef>([]) const initializeFields = useRef>([]) @@ -555,7 +556,11 @@ export function ContractGUI (props: ContractGUIProps) { { proxyAddressError && { proxyAddressError } } : - { proxyAddress || proxyAddressError } + } diff --git a/libs/remix-ui/run-tab/src/lib/constants/index.ts b/libs/remix-ui/run-tab/src/lib/constants/index.ts index bfe5a76715..cfd5518e6e 100644 --- a/libs/remix-ui/run-tab/src/lib/constants/index.ts +++ b/libs/remix-ui/run-tab/src/lib/constants/index.ts @@ -46,3 +46,6 @@ export const SET_DEPLOY_OPTIONS = 'SET_DEPLOY_OPTIONS' export const SET_CURRENT_CONTRACT = 'SET_CURRENT_CONTRACT' export const SET_PROXY_ENV_ADDRESS = 'SET_PROXY_ENV_ADDRESS' export const SET_REMIXD_ACTIVATED = 'SET_REMIXD_ACTIVATED' +export const FETCH_PROXY_DEPLOYMENTS = 'FETCH_PROXY_DEPLOYMENTS' +export const NEW_PROXY_DEPLOYMENT = 'NEW_PROXY_DEPLOYMENT' +export const RESET_PROXY_DEPLOYMENTS = 'RESET_PROXY_DEPLOYMENTS' diff --git a/libs/remix-ui/run-tab/src/lib/reducers/runTab.ts b/libs/remix-ui/run-tab/src/lib/reducers/runTab.ts index 3dfa5a921b..13c5faf3ce 100644 --- a/libs/remix-ui/run-tab/src/lib/reducers/runTab.ts +++ b/libs/remix-ui/run-tab/src/lib/reducers/runTab.ts @@ -1,108 +1,12 @@ -import { CompilerAbstract } from '@remix-project/remix-solidity' import { ContractData } from '@remix-project/core-plugin' -import { DeployOptions } from '../types' -import { ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, FETCH_PROVIDER_LIST_FAILED, FETCH_PROVIDER_LIST_REQUEST, FETCH_PROVIDER_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE, SET_PROXY_ENV_ADDRESS, ADD_DEPLOY_OPTION, REMOVE_DEPLOY_OPTION, SET_REMIXD_ACTIVATED } from '../constants' +import { ContractList, DeployOptions, RunTabState } from '../types' +import { ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, FETCH_PROVIDER_LIST_FAILED, FETCH_PROVIDER_LIST_REQUEST, FETCH_PROVIDER_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE, SET_PROXY_ENV_ADDRESS, ADD_DEPLOY_OPTION, REMOVE_DEPLOY_OPTION, SET_REMIXD_ACTIVATED, FETCH_PROXY_DEPLOYMENTS, NEW_PROXY_DEPLOYMENT, RESET_PROXY_DEPLOYMENTS } from '../constants' declare const window: any interface Action { type: string payload: any } -export interface Contract { - name: string, - alias: string, - file: string, - compiler: CompilerAbstract, - compilerName: string -} - -export interface ContractList { - [file: string]: Contract[] -} -export interface RunTabState { - accounts: { - loadedAccounts: Record, - isRequesting: boolean, - isSuccessful: boolean, - error: string, - selectedAccount: string - }, - sendValue: string, - sendUnit: 'ether' | 'finney' | 'gwei' | 'wei', - gasLimit: number, - selectExEnv: string, - personalMode: boolean, - networkName: string, - providers: { - providerList: { - id?: string, - dataId?: string, - title?: string, - value: string, - fork?: string - content: string - }[], - isRequesting: boolean, - isSuccessful: boolean, - error: string - }, - notification: { - title: string, - message: string, - actionOk: () => void, - actionCancel: (() => void) | null, - labelOk: string, - labelCancel: string - }, - externalEndpoint: string, - popup: string, - passphrase: string, - matchPassphrase: string, - contracts: { - contractList: { - [file: string]: { - name: string, - alias: string, - file: string, - compiler: CompilerAbstract - compilerName: string - }[] - }, - deployOptions: { [file: string]: { [name: string]: DeployOptions } }, - proxyKey: string, - loadType: 'abi' | 'sol' | 'other' - currentFile: string, - compilationSource: string, - currentContract: string, - compilationCount: number, - isRequesting: boolean, - isSuccessful: boolean, - error: string - }, - ipfsChecked: boolean, - gasPriceStatus: boolean, - confirmSettings: boolean, - maxFee: string, - maxPriorityFee: string, - baseFeePerGas: string, - gasPrice: string, - instances: { - instanceList: { - contractData?: ContractData, - address: string, - balance?: number, - name: string, - decodedResponse?: Record, - abi?: any - }[], - error: string - }, - recorder: { - pathToScenario: string, - transactionCount: number - } - remixdActivated: boolean -} export const runTabInitialState: RunTabState = { accounts: { @@ -164,7 +68,10 @@ export const runTabInitialState: RunTabState = { pathToScenario: 'scenario.json', transactionCount: 0 }, - remixdActivated: false + remixdActivated: false, + proxy: { + deployments: [] + } } type AddProvider = { @@ -717,6 +624,40 @@ export const runTabReducer = (state: RunTabState = runTabInitialState, action: A } } + case FETCH_PROXY_DEPLOYMENTS: { + const payload: { address: string, date: Date }[] = action.payload + + return { + ...state, + proxy: { + ...state.proxy, + deployments: payload + } + } + } + + case NEW_PROXY_DEPLOYMENT: { + const payload: { address: string, date: Date } = action.payload + + return { + ...state, + proxy: { + ...state.proxy, + deployments: [...state.proxy.deployments, payload] + } + } + } + + case RESET_PROXY_DEPLOYMENTS: { + return { + ...state, + proxy: { + ...state.proxy, + deployments: [] + } + } + } + default: return state } diff --git a/libs/remix-ui/run-tab/src/lib/types/index.ts b/libs/remix-ui/run-tab/src/lib/types/index.ts index 86b328a61a..cc2ca3cc99 100644 --- a/libs/remix-ui/run-tab/src/lib/types/index.ts +++ b/libs/remix-ui/run-tab/src/lib/types/index.ts @@ -1,12 +1,110 @@ import { Ref } from 'react' import { CompilerAbstract } from '@remix-project/remix-solidity' import { ContractData, FuncABI } from '@remix-project/core-plugin' -import { ContractList } from '../reducers/runTab' import { RunTab } from './run-tab' export interface RunTabProps { plugin: RunTab } +export interface Contract { + name: string, + alias: string, + file: string, + compiler: CompilerAbstract, + compilerName: string +} + +export interface ContractList { + [file: string]: Contract[] +} +export interface RunTabState { + accounts: { + loadedAccounts: Record, + isRequesting: boolean, + isSuccessful: boolean, + error: string, + selectedAccount: string + }, + sendValue: string, + sendUnit: 'ether' | 'finney' | 'gwei' | 'wei', + gasLimit: number, + selectExEnv: string, + personalMode: boolean, + networkName: string, + providers: { + providerList: { + id?: string, + dataId?: string, + title?: string, + value: string, + fork?: string + content: string + }[], + isRequesting: boolean, + isSuccessful: boolean, + error: string + }, + notification: { + title: string, + message: string, + actionOk: () => void, + actionCancel: (() => void) | null, + labelOk: string, + labelCancel: string + }, + externalEndpoint: string, + popup: string, + passphrase: string, + matchPassphrase: string, + contracts: { + contractList: { + [file: string]: { + name: string, + alias: string, + file: string, + compiler: CompilerAbstract + compilerName: string + }[] + }, + deployOptions: { [file: string]: { [name: string]: DeployOptions } }, + proxyKey: string, + loadType: 'abi' | 'sol' | 'other' + currentFile: string, + compilationSource: string, + currentContract: string, + compilationCount: number, + isRequesting: boolean, + isSuccessful: boolean, + error: string + }, + ipfsChecked: boolean, + gasPriceStatus: boolean, + confirmSettings: boolean, + maxFee: string, + maxPriorityFee: string, + baseFeePerGas: string, + gasPrice: string, + instances: { + instanceList: { + contractData?: ContractData, + address: string, + balance?: number, + name: string, + decodedResponse?: Record, + abi?: any + }[], + error: string + }, + recorder: { + pathToScenario: string, + transactionCount: number + } + remixdActivated: boolean, + proxy: { + deployments: { address: string, date: Date }[] + } +} + export interface SettingsProps { selectExEnv: string, accounts: {