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 9c0570c127..26b7c29cf0 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/index.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/index.ts @@ -7,7 +7,7 @@ import { addNewInstance, addProvider, clearAllInstances, displayNotification, di import { RunTab } from '../types/run-tab' import { CompilerAbstract } from '@remix-project/remix-solidity' import * as remixLib from '@remix-project/remix-lib' -import { ContractData, FuncABI, MainnetPrompt, Network, Tx } from '../types' +import { ContractData, FuncABI, MainnetPrompt } from '../types' const txFormat = remixLib.execution.txFormat declare global { @@ -314,7 +314,8 @@ const loadContractFromAddress = (address, confirmCb, cb) => { try { abi = JSON.parse(plugin.editor.currentContent()) } catch (e) { - // return cb('Failed to parse the current file as JSON ABI.') + // eslint-disable-next-line standard/no-callback-literal + return cb('Failed to parse the current file as JSON ABI.') } _paq.push(['trackEvent', 'udapp', 'AtAddressLoadWithABI']) cb(null, 'abi', abi) @@ -551,34 +552,26 @@ export const clearInstances = () => { dispatch(clearAllInstances()) } -const loadAddress = () => { +export const loadAddress = (contract: ContractData, address: string) => { + if (!contract) return dispatch(displayPopUp('No compiled contracts found.')) clearInstances() + loadContractFromAddress(address, + (cb) => { + dispatch(displayNotification('At Address', `Do you really want to interact with ${address} using the current ABI definition?`, 'OK', 'Cancel', cb, null)) + }, + (error, loadType, abi) => { + if (error) { + return dispatch(displayNotification('Alert', error, 'OK', null)) + } + const compiler = plugin.REACT_API.contracts.contractList.find(item => item.alias === contract.name) + const contractData = getSelectedContract(contract.name, compiler.name) - // let address = this.atAddressButtonInput.value - // if (!ethJSUtil.isValidChecksumAddress(address)) { - // addTooltip(yo` - // - // It seems you are not using a checksumed address. - //
A checksummed address is an address that contains uppercase letters, as specified in EIP-55. - //
Checksummed addresses are meant to help prevent users from sending transactions to the wrong address. - //
`) - // address = ethJSUtil.toChecksumAddress(address) - // } - // this.dropdownLogic.loadContractFromAddress(address, - // (cb) => { - // modalDialogCustom.confirm('At Address', `Do you really want to interact with ${address} using the current ABI definition?`, cb) - // }, - // (error, loadType, abi) => { - // if (error) { - // return modalDialogCustom.alert(error) - // } - // if (loadType === 'abi') { - // return this.event.trigger('newContractABIAdded', [abi, address]) - // } - // var selectedContract = this.getSelectedContract() - // addInstance({ contractData: selectedContract.object, address, name: contractObject.name }) - // } - // ) + if (loadType === 'abi') { + return addInstance({ contractData, address, name: '' }) + } + addInstance({ contractData, address, name: contract.name }) + } + ) } export const getContext = () => { 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 3cd2f549ba..c4a7f04190 100644 --- a/libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx @@ -17,7 +17,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) { title: 'address of contract', disabled: true }) - const [address, setAddress] = useState('') + const [loadedAddress, setLoadedAddress] = useState('') const [contractOptions, setContractOptions] = useState<{title: string, disabled: boolean}>({ title: 'Please compile *.sol file to deploy or access a contract', disabled: true @@ -44,8 +44,8 @@ export function ContractDropdownUI (props: ContractDropdownProps) { }, [props.exEnvironment]) useEffect(() => { - if (!address || !ethJSUtil.isValidAddress(address)) enableAtAddress(false) - }, [address]) + if (!loadFromAddress || !ethJSUtil.isValidAddress(loadedAddress)) enableAtAddress(false) + }, [loadedAddress]) useEffect(() => { if (/.(.abi)$/.exec(currentFile)) { @@ -78,6 +78,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) { useEffect(() => { if (selectedContract) { + console.log('contractList: ', contractList) const contract = contractList.find(contract => contract.alias === selectedContract) setLoadedContractData(props.getSelectedContract(selectedContract, contract.name)) @@ -93,7 +94,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) { } else { setAtAddressOptions({ disabled: true, - title: address ? '⚠ Compile *.sol file or select *.abi file.' : '⚠ Compile *.sol file or select *.abi file & then enter the address of deployed contract.' + title: loadedAddress ? '⚠ Compile *.sol file or select *.abi file.' : '⚠ Compile *.sol file or select *.abi file & then enter the address of deployed contract.' }) } } @@ -149,18 +150,23 @@ export function ContractDropdownUI (props: ContractDropdownProps) { if (!value) { enableAtAddress(false) } else { - if ((!contractOptions.disabled && loadType === 'sol') || - loadType === 'abi') { + if (atAddressOptions.disabled && (loadType === 'sol' || loadType === 'abi')) { enableAtAddress(true) } else { enableAtAddress(false) } } - setAddress(value) + setLoadedAddress(value) } const loadFromAddress = () => { - // trigger dispatchLoadAddress + let address = loadedAddress + + if (!ethJSUtil.isValidChecksumAddress(address)) { + props.tooltip(checkSumWarning()) + address = ethJSUtil.toChecksumAddress(address) + } + props.loadAddress(loadedContractData, address) } const handleCheckedIPFS = () => { @@ -174,6 +180,16 @@ export function ContractDropdownUI (props: ContractDropdownProps) { setSelectedContract(value) } + const checkSumWarning = () => { + return ( + + It seems you are not using a checksumed address. +
A checksummed address is an address that contains uppercase letters, as specified in EIP-55. +
Checksummed addresses are meant to help prevent users from sending transactions to the wrong address. +
+ ) + } + const isOverSizePrompt = () => { return (
Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fails.
@@ -228,7 +244,6 @@ export function ContractDropdownUI (props: ContractDropdownProps) { placeholder="Load contract from Address" title="address of contract" onChange={atAddressChanged} - disabled={atAddressOptions.disabled} />
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 1b78f6f863..c24efb2dd2 100644 --- a/libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx @@ -15,8 +15,28 @@ export function ContractGUI (props: ContractGUIProps) { classList: string, dataId: string }>({ title: '', content: '', classList: '', dataId: '' }) + const [clipboardContent, setClipboardContent] = useState('') const multiFields = useRef>([]) + useEffect(() => { + const multiString = getMultiValsString() + const multiJSON = JSON.parse('[' + multiString + ']') + let encodeObj + + if (props.evmBC) { + encodeObj = txFormat.encodeData(props.funcABI, multiJSON, props.evmBC) + } else { + encodeObj = txFormat.encodeData(props.funcABI, multiJSON, null) + } + if (encodeObj.error) { + console.error(encodeObj.error) + // throw new Error(encodeObj.error) + setClipboardContent(encodeObj.error) + } else { + setClipboardContent(encodeObj.data) + } + }, []) + useEffect(() => { if (props.title) { setTitle(props.title) @@ -79,10 +99,12 @@ export function ContractGUI (props: ContractGUIProps) { valArrayTest.push(elVal) elVal = elVal.replace(/(^|,\s+|,)(\d+)(\s+,|,|$)/g, '$1"$2"$3') // replace non quoted number by quoted number elVal = elVal.replace(/(^|,\s+|,)(0[xX][0-9a-fA-F]+)(\s+,|,|$)/g, '$1"$2"$3') // replace non quoted hex string by quoted hex string - try { - JSON.parse(elVal) - } catch (e) { - elVal = '"' + elVal + '"' + if (elVal) { + try { + JSON.parse(elVal) + } catch (e) { + elVal = '"' + elVal + '"' + } } ret += elVal } @@ -112,25 +134,6 @@ export function ContractGUI (props: ContractGUIProps) { } } - const clipboardContent = () => { - const multiString = getMultiValsString() - const multiJSON = JSON.parse('[' + multiString + ']') - let encodeObj - - if (props.evmBC) { - encodeObj = txFormat.encodeData(props.funcABI, multiJSON, props.evmBC) - } else { - encodeObj = txFormat.encodeData(props.funcABI, multiJSON, null) - } - if (encodeObj.error) { - console.error(encodeObj.error) - // throw new Error(encodeObj.error) - return encodeObj.error - } else { - return encodeObj.data - } - } - const handleActionClick = () => { props.clickCallBack(props.funcABI.inputs, basicInput) } @@ -185,7 +188,7 @@ export function ContractGUI (props: ContractGUIProps) { })}
- +
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 68f837858b..c0505a202f 100644 --- a/libs/remix-ui/run-tab/src/lib/run-tab.tsx +++ b/libs/remix-ui/run-tab/src/lib/run-tab.tsx @@ -22,7 +22,7 @@ import { updateMaxFee, updateMaxPriorityFee, updateTxFeeContent, clearInstances, removeInstance, getContext, - runTransactions + runTransactions, loadAddress } from './actions' import './css/run-tab.css' import { PublishToStorage } from '@remix-ui/publish-to-storage' @@ -224,6 +224,8 @@ export function RunTabUI (props: RunTabProps) { logBuilder={logBuilder} passphrasePrompt={passphrasePrompt} mainnetPrompt={mainnetPrompt} + tooltip={toast} + loadAddress={loadAddress} /> JSX.Element, logBuilder: (msg: string) => JSX.Element, passphrasePrompt: (message: string) => JSX.Element, - mainnetPrompt: (tx: Tx, network: Network, amount: string, gasEstimation: string, gasFees: (maxFee: string, cb: (txFeeText: string, priceStatus: boolean) => void) => void, determineGasPrice: (cb: (txFeeText: string, gasPriceValue: string, gasPriceStatus: boolean) => void) => void) => JSX.Element + mainnetPrompt: (tx: Tx, network: Network, amount: string, gasEstimation: string, gasFees: (maxFee: string, cb: (txFeeText: string, priceStatus: boolean) => void) => void, determineGasPrice: (cb: (txFeeText: string, gasPriceValue: string, gasPriceStatus: boolean) => void) => void) => JSX.Element, + tooltip: (toasterMsg: string | JSX.Element) => void, + loadAddress: (contract: ContractData, address: string) => void } export interface RecorderProps {