From a1e9e748de42077e725dcfb4c3eb6c9a96438f67 Mon Sep 17 00:00:00 2001 From: David Disu Date: Tue, 14 Dec 2021 16:57:55 +0100 Subject: [PATCH] create instance setup --- apps/remix-ide/src/app/udapp/run-tab.js | 1 - apps/remix-ide/src/blockchain/blockchain.js | 1 - .../helper/src/lib/remix-ui-helper.ts | 13 +++ .../remix-ui/run-tab/src/lib/actions/index.ts | 82 +++++++++++++++- .../run-tab/src/lib/actions/payload.ts | 6 ++ .../run-tab/src/lib/components/account.tsx | 33 +++---- .../src/lib/components/contractDropdownUI.tsx | 97 ++++--------------- .../run-tab/src/lib/components/passphrase.tsx | 22 +++++ .../run-tab/src/lib/components/settingsUI.tsx | 2 +- .../run-tab/src/lib/reducers/runTab.ts | 13 ++- libs/remix-ui/run-tab/src/lib/run-tab.tsx | 6 +- libs/remix-ui/run-tab/src/lib/types/index.ts | 11 ++- 12 files changed, 179 insertions(+), 108 deletions(-) create mode 100644 libs/remix-ui/run-tab/src/lib/components/passphrase.tsx diff --git a/apps/remix-ide/src/app/udapp/run-tab.js b/apps/remix-ide/src/app/udapp/run-tab.js index 2173e2d8ee..73d5fd6c2f 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.js +++ b/apps/remix-ide/src/app/udapp/run-tab.js @@ -41,7 +41,6 @@ export class RunTab extends ViewPlugin { this.blockchain = blockchain this.fileManager = fileManager this.editor = editor - this.logCallback = (msg) => { this.call('terminal', 'logHtml', yo`
${msg}
`) } this.filePanel = filePanel this.compilersArtefacts = compilersArtefacts this.networkModule = networkModule diff --git a/apps/remix-ide/src/blockchain/blockchain.js b/apps/remix-ide/src/blockchain/blockchain.js index b041000be9..f280e47d8b 100644 --- a/apps/remix-ide/src/blockchain/blockchain.js +++ b/apps/remix-ide/src/blockchain/blockchain.js @@ -414,7 +414,6 @@ class Blockchain extends Plugin { const self = this waterfall([ function getGasLimit (next) { - console.log('called: ', self.transactionContextAPI.gasLimit()) if (self.transactionContextAPI.getGasLimit) { return self.transactionContextAPI.getGasLimit(next) } diff --git a/libs/remix-ui/helper/src/lib/remix-ui-helper.ts b/libs/remix-ui/helper/src/lib/remix-ui-helper.ts index 8d16ecc734..818cf3bc31 100644 --- a/libs/remix-ui/helper/src/lib/remix-ui-helper.ts +++ b/libs/remix-ui/helper/src/lib/remix-ui-helper.ts @@ -1,3 +1,5 @@ +import * as ethJSUtil from 'ethereumjs-util' + export const extractNameFromKey = (key: string): string => { if (!key) return const keyPath = key.split('/') @@ -73,3 +75,14 @@ export const shortenAddress = (address, etherBalance) => { return address.slice(0, 5) + '...' + address.slice(len - 5, len) + (etherBalance ? ' (' + etherBalance.toString() + ' ether)' : '') } + +export const addressToString = (address) => { + if (!address) return null + if (typeof address !== 'string') { + address = address.toString('hex') + } + if (address.indexOf('0x') === -1) { + address = '0x' + address + } + return ethJSUtil.toChecksumAddress(address) +} 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 a64dc80992..76a03d15d6 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/index.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/index.ts @@ -2,7 +2,7 @@ import React from 'react' import * as ethJSUtil from 'ethereumjs-util' import Web3 from 'web3' -import { shortenAddress } from '@remix-ui/helper' +import { addressToString, shortenAddress } from '@remix-ui/helper' import { addProvider, displayNotification, displayPopUp, fetchAccountsListFailed, fetchAccountsListRequest, fetchAccountsListSuccess, fetchContractListSuccess, hidePopUp, removeProvider, setCurrentFile, setExecutionEnvironment, setExternalEndpoint, setGasLimit, setLoadType, setMatchPassphrase, setNetworkName, setPassphrase, setSelectedAccount, setSendUnit, setSendValue } from './payload' import { RunTab } from '../types/run-tab' import { CompilerAbstract } from '@remix-project/remix-solidity' @@ -380,3 +380,83 @@ export const getSelectedContract = (contractName: string, compilerAtributeName: const getCompilerContracts = () => { return plugin.compilersArtefacts.__last.getData().contracts } + +// eslint-disable-next-line no-undef +const terminalLogger = (view: JSX.Element) => { + plugin.call('terminal', 'logHtml', view) +} + +// eslint-disable-next-line no-undef +export const createInstance = (gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, logBuilder: (msg: string) => JSX.Element) => { + const continueCb = (error, continueTxExecution, cancelCb) => { + if (error) { + const msg = typeof error !== 'string' ? error.message : error + + dispatch(displayNotification('Gas estimation failed', gasEstimationPrompt(msg), 'Send Transaction', 'Cancel Transaction', () => { + continueTxExecution() + }, () => { + cancelCb() + })) + } else { + continueTxExecution() + } + } + + const promptCb = (okCb, cancelCb) => { + dispatch(displayNotification('Passphrase requested', passphrasePrompt('Personal mode is enabled. Please provide passphrase of account'), 'OK', 'Cancel', okCb, cancelCb)) + } + + const statusCb = (msg: string) => { + const log = logBuilder(msg) + + return terminalLogger(log) + } + + const finalCb = (error, contractObject, address) => { + plugin.event.trigger('clearInstance') + if (error) { + const log = logBuilder(error) + + return terminalLogger(log) + } + plugin.event.trigger('newContractInstanceAdded', [contractObject, address, contractObject.name]) + + const data = plugin.compilersArtefacts.getCompilerAbstract(contractObject.contract.file) + + plugin.compilersArtefacts.addResolvedContract(addressToString(address), data) + if (self.ipfsCheckedState) { + _paq.push(['trackEvent', 'udapp', 'DeployAndPublish', this.networkName]) + publishToStorage('ipfs', self.runView.fileProvider, self.runView.fileManager, selectedContract) + } else { + _paq.push(['trackEvent', 'udapp', 'DeployOnly', plugin.REACT_API.networkName]) + } + } + + // let contractMetadata + // try { + // contractMetadata = await this.runView.call('compilerMetadata', 'deployMetadataOf', selectedContract.name, selectedContract.contract.file) + // } catch (error) { + // return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`) + // } + + // const compilerContracts = this.dropdownLogic.getCompilerContracts() + // const confirmationCb = this.getConfirmationCb(modalDialog, confirmDialog) + + // if (selectedContract.isOverSizeLimit()) { + // return modalDialog('Contract code size over limit', yo`
Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fails.
+ // More info: eip-170 + //
`, + // { + // label: 'Force Send', + // fn: () => { + // this.deployContract(selectedContract, args, contractMetadata, compilerContracts, { continueCb, promptCb, statusCb, finalCb }, confirmationCb) + // } + // }, { + // label: 'Cancel', + // fn: () => { + // this.logCallback(`creation of ${selectedContract.name} canceled by user.`) + // } + // }) + // } + // this.deployContract(selectedContract, args, contractMetadata, compilerContracts, { continueCb, promptCb, statusCb, finalCb }, confirmationCb) +} 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 2bfcb3f350..302cbdebcf 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/payload.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/payload.ts @@ -163,3 +163,9 @@ export const setCurrentFile = (file: string) => { payload: file } } +export const setIpfsCheckedState = (state: boolean) => { + return { + type: 'SET_IPFS_CHECKED_STATE', + payload: state + } +} diff --git a/libs/remix-ui/run-tab/src/lib/components/account.tsx b/libs/remix-ui/run-tab/src/lib/components/account.tsx index a03ec87aaf..d0683c3711 100644 --- a/libs/remix-ui/run-tab/src/lib/components/account.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/account.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react' import { CopyToClipboard } from '@remix-ui/clipboard' import { AccountProps } from '../types' +import { PassphrasePrompt } from './passphrase' export function AccountUI (props: AccountProps) { const { selectedAccount, loadedAccounts } = props.accounts @@ -11,7 +12,6 @@ export function AccountUI (props: AccountProps) { title: '' }) const [message, setMessage] = useState('') - const [signPassphrase, setSignPassphrase] = useState('') useEffect(() => { if (!selectedAccount && accounts.length > 0) props.setAccount(accounts[0]) @@ -73,11 +73,18 @@ export function AccountUI (props: AccountProps) { } if (props.selectExEnv !== 'vm-london' && props.selectExEnv !== 'vm-berlin' && props.selectExEnv !== 'injected') { - return props.modal('Passphrase to sign a message', passphrasePrompt(), 'OK', () => { - props.modal('Sign a message', signMessagePrompt(), 'OK', () => { - props.signMessageWithAddress(selectedAccount, message, signedMessagePrompt, signPassphrase) - }, 'Cancel', null) - }, 'Cancel', null) + return props.modal('Passphrase to sign a message', + , 'OK', () => { + props.modal('Sign a message', signMessagePrompt(), 'OK', () => { + props.signMessageWithAddress(selectedAccount, message, signedMessagePrompt, props.passphrase) + props.setPassphrase('') + }, 'Cancel', null) + }, 'Cancel', () => { + props.setPassphrase('') + }) } props.modal('Sign a message', signMessagePrompt(), 'OK', () => { @@ -97,10 +104,6 @@ export function AccountUI (props: AccountProps) { setMessage(e.target.value) } - const handleSignPassphrase = (e) => { - setSignPassphrase(e.target.value) - } - const passphraseCreationPrompt = () => { return (
Please provide a Passphrase for the account creation @@ -114,16 +117,6 @@ export function AccountUI (props: AccountProps) { ) } - const passphrasePrompt = () => { - return ( -
Enter your passphrase for this account to sign the message -
- -
-
- ) - } - const signMessagePrompt = () => { return (
Enter a message to sign diff --git a/libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx b/libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx index d45e9f02fd..867c298802 100644 --- a/libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react' import { ContractDropdownProps } from '../types' import * as ethJSUtil from 'ethereumjs-util' import { ContractGUI } from './contractGUI' +import { PassphrasePrompt } from './passphrase' export function ContractDropdownUI (props: ContractDropdownProps) { const [networkName, setNetworkName] = useState('') @@ -133,85 +134,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) { if (selectedContract.bytecodeObject.length === 0) { return props.modal('Alert', 'This contract may be abstract, not implement an abstract parent\'s methods completely or not invoke an inherited contract\'s constructor correctly.', 'OK', () => {}) } - - // var continueCb = (error, continueTxExecution, cancelCb) => { - // if (error) { - // var msg = typeof error !== 'string' ? error.message : error - // modalDialog('Gas estimation failed', yo`
Gas estimation errored with the following message (see below). - // The transaction execution will likely fail. Do you want to force sending?
- // ${msg} - //
`, - // { - // label: 'Send Transaction', - // fn: () => { - // continueTxExecution() - // } - // }, { - // label: 'Cancel Transaction', - // fn: () => { - // cancelCb() - // } - // }) - // } else { - // continueTxExecution() - // } - // } - - // const self = this - - // var promptCb = (okCb, cancelCb) => { - // modalDialogCustom.promptPassphrase('Passphrase requested', 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb) - // } - - // var statusCb = (msg) => { - // return this.logCallback(msg) - // } - - // var finalCb = (error, contractObject, address) => { - // self.event.trigger('clearInstance') - - // if (error) { - // return this.logCallback(error) - // } - // self.event.trigger('newContractInstanceAdded', [contractObject, address, contractObject.name]) - - // const data = self.runView.compilersArtefacts.getCompilerAbstract(contractObject.contract.file) - // self.runView.compilersArtefacts.addResolvedContract(helper.addressToString(address), data) - // if (self.ipfsCheckedState) { - // _paq.push(['trackEvent', 'udapp', 'DeployAndPublish', this.networkName + '_' + this.networkId]) - // publishToStorage('ipfs', self.runView.fileProvider, self.runView.fileManager, selectedContract) - // } else { - // _paq.push(['trackEvent', 'udapp', 'DeployOnly', this.networkName + '_' + this.networkId]) - // } - // } - - // let contractMetadata - // try { - // contractMetadata = await this.runView.call('compilerMetadata', 'deployMetadataOf', selectedContract.name, selectedContract.contract.file) - // } catch (error) { - // return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`) - // } - - // const compilerContracts = this.dropdownLogic.getCompilerContracts() - // const confirmationCb = this.getConfirmationCb(modalDialog, confirmDialog) - - // if (selectedContract.isOverSizeLimit()) { - // return modalDialog('Contract code size over limit', yo`
Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fails.
- // More info: eip-170 - //
`, - // { - // label: 'Force Send', - // fn: () => { - // this.deployContract(selectedContract, args, contractMetadata, compilerContracts, { continueCb, promptCb, statusCb, finalCb }, confirmationCb) - // } - // }, { - // label: 'Cancel', - // fn: () => { - // this.logCallback(`creation of ${selectedContract.name} canceled by user.`) - // } - // }) - // } - // this.deployContract(selectedContract, args, contractMetadata, compilerContracts, { continueCb, promptCb, statusCb, finalCb }, confirmationCb) + props.createInstance(gasEstimationPrompt, passphrasePrompt, logBuilder) } // listenToContextChange () { @@ -362,6 +285,22 @@ export function ContractDropdownUI (props: ContractDropdownProps) { // return confirmationCb // } + const gasEstimationPrompt = (msg: string) => { + return ( +
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
+ ${msg} +
+ ) + } + + const logBuilder = (msg: string) => { + return
{msg}
+ } + + const passphrasePrompt = (message: string) => { + return + } + const atAddressChanged = (event) => { const value = event.target.value diff --git a/libs/remix-ui/run-tab/src/lib/components/passphrase.tsx b/libs/remix-ui/run-tab/src/lib/components/passphrase.tsx new file mode 100644 index 0000000000..c118ede4a0 --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/components/passphrase.tsx @@ -0,0 +1,22 @@ +// eslint-disable-next-line no-use-before-define +import React from 'react' + +interface PromptProps { + message: string, + setPassphrase: (passphrase: string) => void, + defaultValue?: string +} + +export function PassphrasePrompt (props: PromptProps) { + const handleSignPassphrase = (e) => { + props.setPassphrase(e.target.value) + } + + return ( +
{ props.message } +
+ +
+
+ ) +} 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 8ed940ae9b..bbd2f7840c 100644 --- a/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx @@ -38,7 +38,7 @@ export function SettingsUI (props: SettingsProps) {
- +
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 b05a57a31d..cf057bc0ec 100644 --- a/libs/remix-ui/run-tab/src/lib/reducers/runTab.ts +++ b/libs/remix-ui/run-tab/src/lib/reducers/runTab.ts @@ -54,6 +54,7 @@ export interface RunTabState { isSuccessful: boolean, error: string }, + ipfsChecked: boolean } export const runTabInitialState: RunTabState = { @@ -122,7 +123,8 @@ export const runTabInitialState: RunTabState = { isRequesting: false, isSuccessful: false, error: null - } + }, + ipfsChecked: false } export const runTabReducer = (state: RunTabState = runTabInitialState, action: Action) => { @@ -430,6 +432,15 @@ export const runTabReducer = (state: RunTabState = runTabInitialState, action: A } } + case 'SET_IPFS_CHECKED_STATE': { + const payload: boolean = action.payload + + return { + ...state, + ipfsChecked: payload + } + } + default: return state } diff --git a/libs/remix-ui/run-tab/src/lib/run-tab.tsx b/libs/remix-ui/run-tab/src/lib/run-tab.tsx index 00cc462573..42501a8483 100644 --- a/libs/remix-ui/run-tab/src/lib/run-tab.tsx +++ b/libs/remix-ui/run-tab/src/lib/run-tab.tsx @@ -9,7 +9,7 @@ import { RecorderUI } from './components/recorderCardUI' import { SettingsUI } from './components/settingsUI' import { Modal, RunTabProps } from './types' import { runTabInitialState, runTabReducer } from './reducers/runTab' -import { initRunTab, setAccount, setUnit, setGasFee, setExecutionContext, setWeb3Endpoint, clearPopUp, createNewBlockchainAccount, setPassphrasePrompt, setMatchPassphrasePrompt, signMessageWithAddress, getSelectedContract } from './actions' +import { initRunTab, setAccount, setUnit, setGasFee, setExecutionContext, setWeb3Endpoint, clearPopUp, createNewBlockchainAccount, setPassphrasePrompt, setMatchPassphrasePrompt, signMessageWithAddress, getSelectedContract, createInstance } from './actions' import './css/run-tab.css' export function RunTabUI (props: RunTabProps) { @@ -133,12 +133,16 @@ export function RunTabUI (props: RunTabProps) { modal={modal} tooltip={toast} signMessageWithAddress={signMessageWithAddress} + passphrase={runTab.passphrase} /> 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 99778ced10..9675f0be4f 100644 --- a/libs/remix-ui/run-tab/src/lib/types/index.ts +++ b/libs/remix-ui/run-tab/src/lib/types/index.ts @@ -42,7 +42,8 @@ export interface SettingsProps { setMatchPassphrase: (passphrase: string) => void, modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void, tooltip: (toasterMsg: string) => void, - signMessageWithAddress: (account: string, message: string, modalContent: (hash: string, data: string) => JSX.Element, passphrase?: string) => void + signMessageWithAddress: (account: string, message: string, modalContent: (hash: string, data: string) => JSX.Element, passphrase?: string) => void, + passphrase: string } export interface EnvironmentProps { @@ -85,7 +86,8 @@ export interface AccountProps { setMatchPassphrase: (passphrase: string) => void, tooltip: (toasterMsg: string) => void, modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void, - signMessageWithAddress: (account: string, message: string, modalContent: (hash: string, data: string) => JSX.Element, passphrase?: string) => void + signMessageWithAddress: (account: string, message: string, modalContent: (hash: string, data: string) => JSX.Element, passphrase?: string) => void, + passphrase: string } export interface GasPriceProps { @@ -127,7 +129,10 @@ export interface ContractDropdownProps { isOverSizeLimit: () => boolean, metadata: any }, - modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void + modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void, + passphrase: string, + setPassphrase: (passphrase: string) => void, + createInstance: (gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, logBuilder: (msg: string) => JSX.Element) => void } export interface RecorderProps {