Enable atAddress

pull/5370/head
David Disu 3 years ago committed by yann300
parent 7d9384b71c
commit 74e47426cb
  1. 49
      libs/remix-ui/run-tab/src/lib/actions/index.ts
  2. 33
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  3. 51
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  4. 4
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  5. 4
      libs/remix-ui/run-tab/src/lib/types/index.ts

@ -7,7 +7,7 @@ import { addNewInstance, addProvider, clearAllInstances, displayNotification, di
import { RunTab } from '../types/run-tab' import { RunTab } from '../types/run-tab'
import { CompilerAbstract } from '@remix-project/remix-solidity' import { CompilerAbstract } from '@remix-project/remix-solidity'
import * as remixLib from '@remix-project/remix-lib' 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 const txFormat = remixLib.execution.txFormat
declare global { declare global {
@ -314,7 +314,8 @@ const loadContractFromAddress = (address, confirmCb, cb) => {
try { try {
abi = JSON.parse(plugin.editor.currentContent()) abi = JSON.parse(plugin.editor.currentContent())
} catch (e) { } 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']) _paq.push(['trackEvent', 'udapp', 'AtAddressLoadWithABI'])
cb(null, 'abi', abi) cb(null, 'abi', abi)
@ -551,34 +552,26 @@ export const clearInstances = () => {
dispatch(clearAllInstances()) dispatch(clearAllInstances())
} }
const loadAddress = () => { export const loadAddress = (contract: ContractData, address: string) => {
if (!contract) return dispatch(displayPopUp('No compiled contracts found.'))
clearInstances() 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 (loadType === 'abi') {
// if (!ethJSUtil.isValidChecksumAddress(address)) { return addInstance({ contractData, address, name: '<at address>' })
// addTooltip(yo` }
// <span> addInstance({ contractData, address, name: contract.name })
// It seems you are not using a checksumed address. }
// <br>A checksummed address is an address that contains uppercase letters, as specified in <a href="https://eips.ethereum.org/EIPS/eip-55" target="_blank">EIP-55</a>. )
// <br>Checksummed addresses are meant to help prevent users from sending transactions to the wrong address.
// </span>`)
// 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 })
// }
// )
} }
export const getContext = () => { export const getContext = () => {

@ -17,7 +17,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
title: 'address of contract', title: 'address of contract',
disabled: true disabled: true
}) })
const [address, setAddress] = useState<string>('') const [loadedAddress, setLoadedAddress] = useState<string>('')
const [contractOptions, setContractOptions] = useState<{title: string, disabled: boolean}>({ const [contractOptions, setContractOptions] = useState<{title: string, disabled: boolean}>({
title: 'Please compile *.sol file to deploy or access a contract', title: 'Please compile *.sol file to deploy or access a contract',
disabled: true disabled: true
@ -44,8 +44,8 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
}, [props.exEnvironment]) }, [props.exEnvironment])
useEffect(() => { useEffect(() => {
if (!address || !ethJSUtil.isValidAddress(address)) enableAtAddress(false) if (!loadFromAddress || !ethJSUtil.isValidAddress(loadedAddress)) enableAtAddress(false)
}, [address]) }, [loadedAddress])
useEffect(() => { useEffect(() => {
if (/.(.abi)$/.exec(currentFile)) { if (/.(.abi)$/.exec(currentFile)) {
@ -78,6 +78,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
useEffect(() => { useEffect(() => {
if (selectedContract) { if (selectedContract) {
console.log('contractList: ', contractList)
const contract = contractList.find(contract => contract.alias === selectedContract) const contract = contractList.find(contract => contract.alias === selectedContract)
setLoadedContractData(props.getSelectedContract(selectedContract, contract.name)) setLoadedContractData(props.getSelectedContract(selectedContract, contract.name))
@ -93,7 +94,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
} else { } else {
setAtAddressOptions({ setAtAddressOptions({
disabled: true, 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) { if (!value) {
enableAtAddress(false) enableAtAddress(false)
} else { } else {
if ((!contractOptions.disabled && loadType === 'sol') || if (atAddressOptions.disabled && (loadType === 'sol' || loadType === 'abi')) {
loadType === 'abi') {
enableAtAddress(true) enableAtAddress(true)
} else { } else {
enableAtAddress(false) enableAtAddress(false)
} }
} }
setAddress(value) setLoadedAddress(value)
} }
const loadFromAddress = () => { const loadFromAddress = () => {
// trigger dispatchLoadAddress let address = loadedAddress
if (!ethJSUtil.isValidChecksumAddress(address)) {
props.tooltip(checkSumWarning())
address = ethJSUtil.toChecksumAddress(address)
}
props.loadAddress(loadedContractData, address)
} }
const handleCheckedIPFS = () => { const handleCheckedIPFS = () => {
@ -174,6 +180,16 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
setSelectedContract(value) setSelectedContract(value)
} }
const checkSumWarning = () => {
return (
<span>
It seems you are not using a checksumed address.
<br />A checksummed address is an address that contains uppercase letters, as specified in <a href="https://eips.ethereum.org/EIPS/eip-55" target="_blank">EIP-55</a>.
<br />Checksummed addresses are meant to help prevent users from sending transactions to the wrong address.
</span>
)
}
const isOverSizePrompt = () => { const isOverSizePrompt = () => {
return ( return (
<div>Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fails. <br /> <div>Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fails. <br />
@ -228,7 +244,6 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
placeholder="Load contract from Address" placeholder="Load contract from Address"
title="address of contract" title="address of contract"
onChange={atAddressChanged} onChange={atAddressChanged}
disabled={atAddressOptions.disabled}
/> />
</div> </div>
</div> </div>

@ -15,8 +15,28 @@ export function ContractGUI (props: ContractGUIProps) {
classList: string, classList: string,
dataId: string dataId: string
}>({ title: '', content: '', classList: '', dataId: '' }) }>({ title: '', content: '', classList: '', dataId: '' })
const [clipboardContent, setClipboardContent] = useState<string>('')
const multiFields = useRef<Array<HTMLInputElement | null>>([]) const multiFields = useRef<Array<HTMLInputElement | null>>([])
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(() => { useEffect(() => {
if (props.title) { if (props.title) {
setTitle(props.title) setTitle(props.title)
@ -79,10 +99,12 @@ export function ContractGUI (props: ContractGUIProps) {
valArrayTest.push(elVal) valArrayTest.push(elVal)
elVal = elVal.replace(/(^|,\s+|,)(\d+)(\s+,|,|$)/g, '$1"$2"$3') // replace non quoted number by quoted number 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 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 { if (elVal) {
JSON.parse(elVal) try {
} catch (e) { JSON.parse(elVal)
elVal = '"' + elVal + '"' } catch (e) {
elVal = '"' + elVal + '"'
}
} }
ret += 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 = () => { const handleActionClick = () => {
props.clickCallBack(props.funcABI.inputs, basicInput) props.clickCallBack(props.funcABI.inputs, basicInput)
} }
@ -185,7 +188,7 @@ export function ContractGUI (props: ContractGUIProps) {
})} })}
</div> </div>
<div className="udapp_group udapp_multiArg"> <div className="udapp_group udapp_multiArg">
<CopyToClipboard content={clipboardContent()} tip='Encode values of input fields & copy to clipboard' icon='fa-clipboard' direction={'left'} /> <CopyToClipboard content={clipboardContent} tip='Encode values of input fields & copy to clipboard' icon='fa-clipboard' direction={'left'} />
<button onClick={handleExpandMultiClick} title={buttonOptions.title} data-id={buttonOptions.dataId} className={`udapp_instanceButton ${buttonOptions.classList}`}>{ buttonOptions.content }</button> <button onClick={handleExpandMultiClick} title={buttonOptions.title} data-id={buttonOptions.dataId} className={`udapp_instanceButton ${buttonOptions.classList}`}>{ buttonOptions.content }</button>
</div> </div>
</div> </div>

@ -22,7 +22,7 @@ import {
updateMaxFee, updateMaxPriorityFee, updateMaxFee, updateMaxPriorityFee,
updateTxFeeContent, clearInstances, updateTxFeeContent, clearInstances,
removeInstance, getContext, removeInstance, getContext,
runTransactions runTransactions, loadAddress
} from './actions' } from './actions'
import './css/run-tab.css' import './css/run-tab.css'
import { PublishToStorage } from '@remix-ui/publish-to-storage' import { PublishToStorage } from '@remix-ui/publish-to-storage'
@ -224,6 +224,8 @@ export function RunTabUI (props: RunTabProps) {
logBuilder={logBuilder} logBuilder={logBuilder}
passphrasePrompt={passphrasePrompt} passphrasePrompt={passphrasePrompt}
mainnetPrompt={mainnetPrompt} mainnetPrompt={mainnetPrompt}
tooltip={toast}
loadAddress={loadAddress}
/> />
<RecorderUI /> <RecorderUI />
<InstanceContainerUI <InstanceContainerUI

@ -180,7 +180,9 @@ export interface ContractDropdownProps {
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (msg: string) => JSX.Element,
logBuilder: (msg: string) => JSX.Element, logBuilder: (msg: string) => JSX.Element,
passphrasePrompt: (message: 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 { export interface RecorderProps {

Loading…
Cancel
Save