diff --git a/apps/remix-ide/src/app/udapp/run-tab.js b/apps/remix-ide/src/app/udapp/run-tab.js
index 73d5fd6c2f..297f2996c5 100644
--- a/apps/remix-ide/src/app/udapp/run-tab.js
+++ b/apps/remix-ide/src/app/udapp/run-tab.js
@@ -234,4 +234,12 @@ export class RunTab extends ViewPlugin {
onReady (api) {
this.REACT_API = api
}
+
+ writeFile (fileName, content) {
+ return this.call('fileManager', 'writeFile', fileName, content)
+ }
+
+ readFile (fileName) {
+ return this.call('fileManager', 'readFile', fileName)
+ }
}
diff --git a/libs/remix-ui/publish-to-storage/src/lib/types/index.ts b/libs/remix-ui/publish-to-storage/src/lib/types/index.ts
index 53a351baee..7995d5a538 100644
--- a/libs/remix-ui/publish-to-storage/src/lib/types/index.ts
+++ b/libs/remix-ui/publish-to-storage/src/lib/types/index.ts
@@ -1,6 +1,6 @@
export interface RemixUiPublishToStorageProps {
api: any,
- storage: string,
+ storage: 'swarm' | 'ipfs',
contract: any,
resetStorage: () => void
}
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 76a03d15d6..af87629b30 100644
--- a/libs/remix-ui/run-tab/src/lib/actions/index.ts
+++ b/libs/remix-ui/run-tab/src/lib/actions/index.ts
@@ -3,10 +3,11 @@ import React from 'react'
import * as ethJSUtil from 'ethereumjs-util'
import Web3 from 'web3'
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 { addProvider, displayNotification, displayPopUp, fetchAccountsListFailed, fetchAccountsListRequest, fetchAccountsListSuccess, fetchContractListSuccess, hidePopUp, removeProvider, setBaseFeePerGas, setConfirmSettings, setCurrentFile, setExecutionEnvironment, setExternalEndpoint, setGasLimit, setGasPrice, setGasPriceStatus, setIpfsCheckedState, setLoadType, setMatchPassphrase, setMaxFee, setMaxPriorityFee, setNetworkName, setPassphrase, setSelectedAccount, setSendUnit, setSendValue, setTxFeeContent } from './payload'
import { RunTab } from '../types/run-tab'
import { CompilerAbstract } from '@remix-project/remix-solidity'
import * as remixLib from '@remix-project/remix-lib'
+import { ContractData } from '../types'
declare global {
interface Window {
_paq: any
@@ -386,8 +387,33 @@ const terminalLogger = (view: JSX.Element) => {
plugin.call('terminal', 'logHtml', view)
}
+const getConfirmationCb = () => {
+ // this code is the same as in recorder.js. TODO need to be refactored out
+ const confirmationCb = (network, tx, gasEstimation, continueTxExecution, cancelCb) => {
+ if (network.name !== 'Main') {
+ return continueTxExecution(null)
+ }
+ const amount = plugin.blockchain.fromWei(tx.value, true, 'ether')
+ const content = confirmDialog(tx, network, amount, gasEstimation, plugin.blockchain.determineGasFees(tx), plugin.blockchain.determineGasPrice.bind(plugin.blockchain))
+
+ dispatch(displayNotification('Confirm transaction', content, 'Confirm', 'Cancel', () => {
+ plugin.blockchain.config.setUnpersistedProperty('doNotShowTransactionConfirmationAgain', content.querySelector('input#confirmsetting').checked)
+ // TODO: check if this is check is still valid given the refactor
+ if (!content.gasPriceStatus) {
+ cancelCb('Given transaction fee is not correct')
+ } else {
+ continueTxExecution(content.txFee)
+ }
+ }, () => {
+ return cancelCb('Transaction canceled by user.')
+ }))
+ }
+
+ return confirmationCb
+}
+
// eslint-disable-next-line no-undef
-export const createInstance = (gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, logBuilder: (msg: string) => JSX.Element) => {
+export const createInstance = async (selectedContract: ContractData, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, logBuilder: (msg: string) => JSX.Element, publishToStorage: (storage: 'ipfs' | 'swarm', contract: ContractData) => void) => {
const continueCb = (error, continueTxExecution, cancelCb) => {
if (error) {
const msg = typeof error !== 'string' ? error.message : error
@@ -424,23 +450,23 @@ export const createInstance = (gasEstimationPrompt: (msg: string) => JSX.Element
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)
+ if (plugin.REACT_API.ipfsChecked) {
+ _paq.push(['trackEvent', 'udapp', 'DeployAndPublish', plugin.REACT_API.networkName])
+ publishToStorage('ipfs', 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}`)
- // }
+ let contractMetadata
+ try {
+ contractMetadata = await plugin.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)
+ const compilerContracts = getCompilerContracts()
+ const confirmationCb = getConfirmationCb(mainnetPrompt)
// 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.
@@ -460,3 +486,45 @@ export const createInstance = (gasEstimationPrompt: (msg: string) => JSX.Element
// }
// this.deployContract(selectedContract, args, contractMetadata, compilerContracts, { continueCb, promptCb, statusCb, finalCb }, confirmationCb)
}
+
+const deployContract = (selectedContract, args, contractMetadata, compilerContracts, callbacks, confirmationCb) => {
+ _paq.push(['trackEvent', 'udapp', 'DeployContractTo', this.networkName + '_' + this.networkId])
+ const { statusCb } = callbacks
+ if (!contractMetadata || (contractMetadata && contractMetadata.autoDeployLib)) {
+ return this.blockchain.deployContractAndLibraries(selectedContract, args, contractMetadata, compilerContracts, callbacks, confirmationCb)
+ }
+ if (Object.keys(selectedContract.bytecodeLinkReferences).length) statusCb(`linking ${JSON.stringify(selectedContract.bytecodeLinkReferences, null, '\t')} using ${JSON.stringify(contractMetadata.linkReferences, null, '\t')}`)
+ this.blockchain.deployContractWithLibrary(selectedContract, args, contractMetadata, compilerContracts, callbacks, confirmationCb)
+}
+
+export const setCheckIpfs = (value: boolean) => {
+ dispatch(setIpfsCheckedState(value))
+}
+
+export const updateGasPriceStatus = (status: boolean) => {
+ dispatch(setGasPriceStatus(status))
+}
+
+export const updateConfirmSettings = (confirmation: boolean) => {
+ dispatch(setConfirmSettings(confirmation))
+}
+
+export const updateMaxFee = (fee: string) => {
+ dispatch(setMaxFee(fee))
+}
+
+export const updateMaxPriorityFee = (fee: string) => {
+ dispatch(setMaxPriorityFee(fee))
+}
+
+export const updateBaseFeePerGas = (baseFee: string) => {
+ dispatch(setBaseFeePerGas(baseFee))
+}
+
+export const updateGasPrice = (price: string) => {
+ dispatch(setGasPrice(price))
+}
+
+export const updateTxFeeContent = (content: string) => {
+ dispatch(setTxFeeContent(content))
+}
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 302cbdebcf..56cfd0d022 100644
--- a/libs/remix-ui/run-tab/src/lib/actions/payload.ts
+++ b/libs/remix-ui/run-tab/src/lib/actions/payload.ts
@@ -169,3 +169,52 @@ export const setIpfsCheckedState = (state: boolean) => {
payload: state
}
}
+
+export const setGasPriceStatus = (status: boolean) => {
+ return {
+ type: 'SET_GAS_PRICE_STATUS',
+ payload: status
+ }
+}
+
+export const setConfirmSettings = (confirmation: boolean) => {
+ return {
+ type: 'SET_CONFIRM_SETTINGS',
+ payload: confirmation
+ }
+}
+
+export const setMaxFee = (fee: string) => {
+ return {
+ type: 'SET_MAX_FEE',
+ payload: fee
+ }
+}
+
+export const setMaxPriorityFee = (fee: string) => {
+ return {
+ type: 'SET_MAX_PRIORITY_FEE',
+ payload: fee
+ }
+}
+
+export const setBaseFeePerGas = (baseFee: string) => {
+ return {
+ type: 'SET_BASE_FEE_PER_GAS',
+ payload: baseFee
+ }
+}
+
+export const setGasPrice = (price: string) => {
+ return {
+ type: 'SET_GAS_PRICE',
+ payload: price
+ }
+}
+
+export const setTxFeeContent = (content: string) => {
+ return {
+ type: 'SET_TX_FEE_CONTENT',
+ payload: content
+ }
+}
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 867c298802..d55b94c180 100644
--- a/libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
+++ b/libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
@@ -1,6 +1,6 @@
// eslint-disable-next-line no-use-before-define
import React, { useEffect, useState } from 'react'
-import { ContractDropdownProps } from '../types'
+import { ContractData, ContractDropdownProps } from '../types'
import * as ethJSUtil from 'ethereumjs-util'
import { ContractGUI } from './contractGUI'
import { PassphrasePrompt } from './passphrase'
@@ -14,7 +14,6 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
display: '',
content: ''
})
- const [ipfsCheckedState, setIpfsCheckedState] = useState
(false)
const [atAddressOptions, setAtAddressOptions] = useState<{title: string, disabled: boolean}>({
title: 'address of contract',
disabled: true
@@ -26,19 +25,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
})
const [selectedContract, setSelectedContract] = useState('')
const [compFails, setCompFails] = useState<'none' | 'block'>('none')
- const [loadedContractData, setLoadedContractData] = useState<{
- name: string,
- contract: string,
- compiler: any,
- abi: any,
- bytecodeObject: any,
- bytecodeLinkReferences: any,
- object: any,
- deployedBytecode: any,
- getConstructorInterface: () => any,
- getConstructorInputs: () => any,
- isOverSizeLimit: () => boolean,
- metadata: any}>(null)
+ const [loadedContractData, setLoadedContractData] = useState(null)
const { contractList, loadType, currentFile } = props.contracts
useEffect(() => {
@@ -46,7 +33,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
const savedConfig = window.localStorage.getItem(`ipfs/${props.exEnvironment}/${networkName}`)
const isCheckedIPFS = savedConfig === 'true' ? true : false // eslint-disable-line
- if (isCheckedIPFS) setIpfsCheckedState(true)
+ if (isCheckedIPFS) props.setIpfsCheckedState(true)
setAbiLabel({
display: 'none',
content: 'ABI file selected'
@@ -134,7 +121,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', () => {})
}
- props.createInstance(gasEstimationPrompt, passphrasePrompt, logBuilder)
+ props.createInstance(loadedContractData, gasEstimationPrompt, passphrasePrompt, logBuilder, props.publishToStorage)
}
// listenToContextChange () {
@@ -285,22 +272,6 @@ 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
@@ -349,8 +320,8 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
}
const handleCheckedIPFS = () => {
- setIpfsCheckedState(!ipfsCheckedState)
- window.localStorage.setItem(`ipfs/${props.exEnvironment}/${networkName}`, ipfsCheckedState.toString())
+ props.setIpfsCheckedState(!props.ipfsCheckedState)
+ window.localStorage.setItem(`ipfs/${props.exEnvironment}/${networkName}`, props.ipfsCheckedState.toString())
}
const handleContractChange = (e) => {
@@ -359,6 +330,26 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
setSelectedContract(value)
}
+ 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 mainnetPrompt = () => {
+
+ }
+
return (
@@ -383,7 +374,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
className="form-check-input custom-control-input"
type="checkbox"
onChange={handleCheckedIPFS}
- checked={ipfsCheckedState}
+ checked={props.ipfsCheckedState}
/>