Deploy ERC1967Proxy and update Udapp

pull/2260/head
David Disu 3 years ago
parent beba1ba95d
commit c88c5fe908
  1. 10
      apps/remix-ide/src/app/udapp/run-tab.js
  2. 140
      apps/remix-ide/src/blockchain/blockchain.js
  3. 22
      libs/remix-core-plugin/src/lib/openzeppelin-proxy.ts
  4. 18
      libs/remix-lib/src/execution/txFormat.ts
  5. 4
      libs/remix-ui/helper/src/lib/helper-components.tsx
  6. 11
      libs/remix-ui/run-tab/src/lib/actions/deploy.ts
  7. 4
      libs/remix-ui/run-tab/src/lib/actions/events.ts
  8. 6
      libs/remix-ui/run-tab/src/lib/actions/index.ts
  9. 8
      libs/remix-ui/run-tab/src/lib/actions/recorder.ts
  10. 2
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  11. 27
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  12. 1
      libs/remix-ui/run-tab/src/lib/components/instanceContainerUI.tsx
  13. 2
      libs/remix-ui/run-tab/src/lib/components/recorderCardUI.tsx
  14. 1
      libs/remix-ui/run-tab/src/lib/components/universalDappUI.tsx
  15. 7
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  16. 9
      libs/remix-ui/run-tab/src/lib/types/index.ts

@ -1,6 +1,7 @@
import React from 'react' // eslint-disable-line import React from 'react' // eslint-disable-line
import { RunTabUI } from '@remix-ui/run-tab' import { RunTabUI } from '@remix-ui/run-tab'
import { ViewPlugin } from '@remixproject/engine-web' import { ViewPlugin } from '@remixproject/engine-web'
import { addressToString } from '@remix-ui/helper'
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
const EventManager = require('../../lib/events') const EventManager = require('../../lib/events')
@ -18,7 +19,7 @@ const profile = {
version: packageJson.version, version: packageJson.version,
permission: true, permission: true,
events: ['newTransaction'], events: ['newTransaction'],
methods: ['createVMAccount', 'sendTransaction', 'getAccounts', 'pendingTransactionsCount', 'getSettings', 'setEnvironmentMode', 'clearAllInstances', 'addInstance'] methods: ['createVMAccount', 'sendTransaction', 'getAccounts', 'pendingTransactionsCount', 'getSettings', 'setEnvironmentMode', 'clearAllInstances', 'addInstance', 'resolveContract']
} }
export class RunTab extends ViewPlugin { export class RunTab extends ViewPlugin {
@ -163,4 +164,11 @@ export class RunTab extends ViewPlugin {
readFile (fileName) { readFile (fileName) {
return this.call('fileManager', 'readFile', fileName) return this.call('fileManager', 'readFile', fileName)
} }
resolveContract (contractObject, address) {
const data = this.compilersArtefacts.getCompilerAbstract(contractObject.contract.file)
this.compilersArtefacts.addResolvedContract(addressToString(address), data)
this.addInstance(address, contractObject.abi, contractObject.name)
}
} }

@ -3,7 +3,6 @@ import React from 'react' // eslint-disable-line
import Web3 from 'web3' import Web3 from 'web3'
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import { toBuffer, addHexPrefix } from 'ethereumjs-util' import { toBuffer, addHexPrefix } from 'ethereumjs-util'
import { waterfall } from 'async'
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import { format } from 'util' import { format } from 'util'
import { ExecutionContext } from './execution-context' import { ExecutionContext } from './execution-context'
@ -12,6 +11,7 @@ import InjectedProvider from './providers/injected.js'
import NodeProvider from './providers/node.js' import NodeProvider from './providers/node.js'
import { execution, EventManager, helpers } from '@remix-project/remix-lib' import { execution, EventManager, helpers } from '@remix-project/remix-lib'
import { etherScanLink } from './helper' import { etherScanLink } from './helper'
import { logBuilder } from "@remix-ui/helper"
const { txFormat, txExecution, typeConversion, txListener: Txlistener, TxRunner, TxRunnerWeb3, txHelper } = execution const { txFormat, txExecution, typeConversion, txListener: Txlistener, TxRunner, TxRunnerWeb3, txHelper } = execution
const { txResultHelper: resultToRemixTx } = helpers const { txResultHelper: resultToRemixTx } = helpers
const packageJson = require('../../../../package.json') const packageJson = require('../../../../package.json')
@ -113,7 +113,9 @@ export class Blockchain extends Plugin {
const { continueCb, promptCb, statusCb, finalCb } = callbacks const { continueCb, promptCb, statusCb, finalCb } = callbacks
const constructor = selectedContract.getConstructorInterface() const constructor = selectedContract.getConstructorInterface()
txFormat.buildData(selectedContract.name, selectedContract.object, compilerContracts, true, constructor, args, (error, data) => { txFormat.buildData(selectedContract.name, selectedContract.object, compilerContracts, true, constructor, args, (error, data) => {
if (error) return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`) if (error) {
return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`)
}
statusCb(`creation of ${selectedContract.name} pending...`) statusCb(`creation of ${selectedContract.name} pending...`)
this.createContract(selectedContract, data, continueCb, promptCb, confirmationCb, finalCb) this.createContract(selectedContract, data, continueCb, promptCb, confirmationCb, finalCb)
@ -127,20 +129,51 @@ export class Blockchain extends Plugin {
const { continueCb, promptCb, statusCb, finalCb } = callbacks const { continueCb, promptCb, statusCb, finalCb } = callbacks
const constructor = selectedContract.getConstructorInterface() const constructor = selectedContract.getConstructorInterface()
txFormat.encodeConstructorCallAndLinkLibraries(selectedContract.object, args, constructor, contractMetadata.linkReferences, selectedContract.bytecodeLinkReferences, (error, data) => { txFormat.encodeConstructorCallAndLinkLibraries(selectedContract.object, args, constructor, contractMetadata.linkReferences, selectedContract.bytecodeLinkReferences, (error, data) => {
if (error) return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`) if (error) {
return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`)
}
statusCb(`creation of ${selectedContract.name} pending...`) statusCb(`creation of ${selectedContract.name} pending...`)
this.createContract(selectedContract, data, continueCb, promptCb, confirmationCb, finalCb) this.createContract(selectedContract, data, continueCb, promptCb, confirmationCb, finalCb)
}) })
} }
async deployProxy (proxyData) { async deployProxy (proxyData, implementationContractObject) {
const args = { const args = { useCall: false, data: proxyData }
useCall: false, const confirmationCb = (network, tx, gasEstimation, continueTxExecution, cancelCb) => {
data: proxyData // continue using original authorization given by user
continueTxExecution(null)
}
const continueCb = (error, continueTxExecution, cancelCb) => { continueTxExecution() }
const promptCb = (okCb, cancelCb) => { okCb() }
const finalCb = (error, txResult, address, returnValue) => {
if (error) {
const log = logBuilder(error)
return this.call('terminal', 'logHtml', log)
}
return this.call('udapp', 'resolveContract', implementationContractObject, address)
} }
this.runTx(args) this.runTx(args, confirmationCb, continueCb, promptCb, finalCb)
}
async getEncodedFunctionHex (args, funABI) {
return new Promise((resolve, reject) => {
txFormat.encodeFunctionCall(args, funABI, (error, data) => {
if (error) return reject(error)
resolve(data.dataHex)
})
})
}
async getEncodedParams (args, funABI) {
return new Promise((resolve, reject) => {
txFormat.encodeParams(args, funABI, (error, encodedParams) => {
if (error) return reject(error)
return resolve(encodedParams.dataHex)
})
})
} }
createContract (selectedContract, data, continueCb, promptCb, confirmationCb, finalCb) { createContract (selectedContract, data, continueCb, promptCb, confirmationCb, finalCb) {
@ -442,55 +475,71 @@ export class Blockchain extends Plugin {
}) })
} }
runTx (args, confirmationCb, continueCb, promptCb, cb) { async runTx (args, confirmationCb, continueCb, promptCb, cb) {
waterfall([ const getGasLimit = () => {
(next) => { // getGasLimit return new Promise((resolve, reject) => {
if (this.transactionContextAPI.getGasLimit) { if (this.transactionContextAPI.getGasLimit) {
return this.transactionContextAPI.getGasLimit(next) return this.transactionContextAPI.getGasLimit((err, value) => {
if (err) return reject(err)
return resolve(value)
})
} }
next(null, 3000000) return resolve(3000000)
}, })
(gasLimit, next) => { // queryValue }
const queryValue = () => {
return new Promise((resolve, reject) => {
if (args.value) { if (args.value) {
return next(null, args.value, gasLimit) return resolve(args.value)
} }
if (args.useCall || !this.transactionContextAPI.getValue) { if (args.useCall || !this.transactionContextAPI.getValue) {
return next(null, 0, gasLimit) return resolve(0)
} }
this.transactionContextAPI.getValue(function (err, value) { this.transactionContextAPI.getValue((err, value) => {
next(err, value, gasLimit) if (err) return reject(err)
return resolve(value)
}) })
}, })
(value, gasLimit, next) => { // getAccount }
const getAccount = () => {
return new Promise((resolve, reject) => {
if (args.from) { if (args.from) {
return next(null, args.from, value, gasLimit) return resolve(args.from)
} }
if (this.transactionContextAPI.getAddress) { if (this.transactionContextAPI.getAddress) {
return this.transactionContextAPI.getAddress(function (err, address) { return this.transactionContextAPI.getAddress(function (err, address) {
next(err, address, value, gasLimit) if (err) return reject(err)
return resolve(address)
}) })
} }
this.getAccounts(function (err, accounts) { this.getAccounts(function (err, accounts) {
if (err) return reject(err)
const address = accounts[0] const address = accounts[0]
if (err) return next(err) if (!address) return reject('No accounts available')
if (!address) return next('No accounts available')
if (this.executionContext.isVM() && !this.providers.vm.RemixSimulatorProvider.Accounts.accounts[address]) { if (this.executionContext.isVM() && !this.providers.vm.RemixSimulatorProvider.Accounts.accounts[address]) {
return next('Invalid account selected') return reject('Invalid account selected')
} }
next(null, address, value, gasLimit) return resolve(address)
}) })
}, })
(fromAddress, value, gasLimit, next) => { // runTransaction }
const runTransaction = async () => {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve, reject) => {
const fromAddress = await getAccount()
const value = await queryValue()
const gasLimit = await getGasLimit()
const tx = { to: args.to, data: args.data.dataHex, useCall: args.useCall, from: fromAddress, value: value, gasLimit: gasLimit, timestamp: args.data.timestamp } const tx = { to: args.to, data: args.data.dataHex, useCall: args.useCall, from: fromAddress, value: value, gasLimit: gasLimit, timestamp: args.data.timestamp }
const payLoad = { funAbi: args.data.funAbi, funArgs: args.data.funArgs, contractBytecode: args.data.contractBytecode, contractName: args.data.contractName, contractABI: args.data.contractABI, linkReferences: args.data.linkReferences } const payLoad = { funAbi: args.data.funAbi, funArgs: args.data.funArgs, contractBytecode: args.data.contractBytecode, contractName: args.data.contractName, contractABI: args.data.contractABI, linkReferences: args.data.linkReferences }
if (!tx.timestamp) tx.timestamp = Date.now()
if (!tx.timestamp) tx.timestamp = Date.now()
const timestamp = tx.timestamp const timestamp = tx.timestamp
this.event.trigger('initiatingTransaction', [timestamp, tx, payLoad]) this.event.trigger('initiatingTransaction', [timestamp, tx, payLoad])
this.txRunner.rawRun(tx, confirmationCb, continueCb, promptCb, this.txRunner.rawRun(tx, confirmationCb, continueCb, promptCb,
async (error, result) => { async (error, result) => {
if (error) return next(error) if (error) return reject(error)
const isVM = this.executionContext.isVM() const isVM = this.executionContext.isVM()
if (isVM && tx.useCall) { if (isVM && tx.useCall) {
@ -509,16 +558,15 @@ export class Blockchain extends Plugin {
try { error = 'error: ' + JSON.stringify(error) } catch (e) { console.log(e) } try { error = 'error: ' + JSON.stringify(error) } catch (e) { console.log(e) }
} }
} }
next(error, result, tx) return resolve({ result, tx })
} }
) )
} })
], }
async (error, txResult, tx) => { try {
if (error) { const transaction = await runTransaction()
return cb(error) const txResult = transaction.result
} const tx = transaction.tx
/* /*
value of txResult is inconsistent: value of txResult is inconsistent:
- transact to contract: - transact to contract:
@ -526,12 +574,12 @@ export class Blockchain extends Plugin {
- call to contract: - call to contract:
{"result":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionHash":"0x5236a76152054a8aad0c7135bcc151f03bccb773be88fbf4823184e47fc76247"} {"result":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionHash":"0x5236a76152054a8aad0c7135bcc151f03bccb773be88fbf4823184e47fc76247"}
*/ */
const isVM = this.executionContext.isVM() const isVM = this.executionContext.isVM()
let execResult let execResult
let returnValue = null let returnValue = null
if (isVM) { if (isVM) {
const hhlogs = await this.web3().eth.getHHLogsForTx(txResult.transactionHash) const hhlogs = await this.web3().eth.getHHLogsForTx(txResult.transactionHash)
if (hhlogs && hhlogs.length) { if (hhlogs && hhlogs.length) {
let finalLogs = '<b>console.log:</b>\n' let finalLogs = '<b>console.log:</b>\n'
for (const log of hhlogs) { for (const log of hhlogs) {
@ -561,17 +609,19 @@ export class Blockchain extends Plugin {
} }
} }
} }
if (!isVM && tx && tx.useCall) { if (!isVM && tx && tx.useCall) {
returnValue = toBuffer(addHexPrefix(txResult.result)) returnValue = toBuffer(addHexPrefix(txResult.result))
} }
let address = null let address = null
if (txResult && txResult.receipt) { if (txResult && txResult.receipt) {
address = txResult.receipt.contractAddress address = txResult.receipt.contractAddress
} }
cb(error, txResult, address, returnValue) cb(null, txResult, address, returnValue)
}) } catch (error) {
cb(error)
}
} }
} }

@ -141,21 +141,29 @@ export class OpenZeppelinProxy extends Plugin {
} }
} }
async execute(implAddress: string, _data: string = '') { async execute(implAddress: string, args: string = '', initializeABI, implementationContractObject) {
// deploy the proxy, or use an existing one // deploy the proxy, or use an existing one
if (this.kind === 'UUPS') this.deployUUPSProxy(implAddress, _data) const _data = await this.blockchain.getEncodedFunctionHex(args, initializeABI)
if (this.kind === 'UUPS') this.deployUUPSProxy(implAddress, _data, implementationContractObject)
} }
async deployUUPSProxy (implAddress: string, _data: string) { async deployUUPSProxy (implAddress: string, _data: string, implementationContractObject) {
const args = [implAddress, _data]
const constructorData = await this.blockchain.getEncodedParams(args, UUPSfunAbi)
const proxyName = 'ERC1967Proxy'
const data = { const data = {
contractABI: UUPSABI, contractABI: UUPSABI,
contractByteCode: UUPSBytecode, contractByteCode: UUPSBytecode,
contractName: 'ERC1967Proxy', contractName: proxyName,
funAbi: UUPSfunAbi, funAbi: UUPSfunAbi,
funArgs: [implAddress, _data], funArgs: args,
linkReferences: {} linkReferences: {},
dataHex: UUPSBytecode + constructorData.replace('0x', '')
} }
this.blockchain.deployProxy(data) // re-use implementation contract's ABI for UI display in udapp and change name to proxy name.
implementationContractObject.name = proxyName
this.blockchain.deployProxy(data, implementationContractObject)
} }
} }

@ -39,7 +39,23 @@ export function encodeParams (params, funAbi, callback) {
let data: Buffer | string = '' let data: Buffer | string = ''
let dataHex = '' let dataHex = ''
let funArgs let funArgs
if (params.indexOf('raw:0x') === 0) { if (Array.isArray(params)) {
funArgs = params
if (funArgs.length > 0) {
try {
data = encodeParamsHelper(funAbi, funArgs)
dataHex = data.toString()
} catch (e) {
return callback('Error encoding arguments: ' + e)
}
}
if (data.slice(0, 9) === 'undefined') {
dataHex = data.slice(9)
}
if (data.slice(0, 2) === '0x') {
dataHex = data.slice(2)
}
} else if (params.indexOf('raw:0x') === 0) {
// in that case we consider that the input is already encoded and *does not* contain the method signature // in that case we consider that the input is already encoded and *does not* contain the method signature
dataHex = params.replace('raw:0x', '') dataHex = params.replace('raw:0x', '')
data = Buffer.from(dataHex, 'hex') data = Buffer.from(dataHex, 'hex')

@ -84,3 +84,7 @@ export const recursivePasteToastMsg = () => (
File(s) to paste is an ancestor of the destination folder File(s) to paste is an ancestor of the destination folder
</div> </div>
) )
export const logBuilder = (msg: string) => {
return <pre>{msg}</pre>
}

@ -5,7 +5,7 @@ import * as remixLib from '@remix-project/remix-lib'
import { DeployMode, MainnetPrompt } from "../types" import { DeployMode, MainnetPrompt } from "../types"
import { displayNotification, displayPopUp, setDecodedResponse } from "./payload" import { displayNotification, displayPopUp, setDecodedResponse } from "./payload"
import { addInstance } from "./actions" import { addInstance } from "./actions"
import { addressToString } from "@remix-ui/helper" import { addressToString, logBuilder } from "@remix-ui/helper"
declare global { declare global {
interface Window { interface Window {
@ -128,13 +128,13 @@ export const createInstance = async (
selectedContract: ContractData, selectedContract: ContractData,
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (msg: string) => JSX.Element,
passphrasePrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element,
logBuilder: (msg: string) => JSX.Element,
publishToStorage: (storage: 'ipfs' | 'swarm', publishToStorage: (storage: 'ipfs' | 'swarm',
contract: ContractData) => void, contract: ContractData) => void,
mainnetPrompt: MainnetPrompt, mainnetPrompt: MainnetPrompt,
isOverSizePrompt: () => JSX.Element, isOverSizePrompt: () => JSX.Element,
args, args,
deployMode: DeployMode[]) => { deployMode: DeployMode[]) => {
const isProxyDeployment = (deployMode || []).find(mode => mode === 'Deploy with Proxy')
const statusCb = (msg: string) => { const statusCb = (msg: string) => {
const log = logBuilder(msg) const log = logBuilder(msg)
@ -157,6 +157,11 @@ export const createInstance = async (
} else { } else {
_paq.push(['trackEvent', 'udapp', 'DeployOnly', plugin.REACT_API.networkName]) _paq.push(['trackEvent', 'udapp', 'DeployOnly', plugin.REACT_API.networkName])
} }
if (isProxyDeployment) {
const initABI = contractObject.abi.find(abi => abi.name === 'initialize')
plugin.call('openzeppelin-proxy', 'execute', addressToString(address), args, initABI, contractObject)
}
} }
let contractMetadata let contractMetadata
@ -168,7 +173,6 @@ export const createInstance = async (
const compilerContracts = getCompilerContracts(plugin) const compilerContracts = getCompilerContracts(plugin)
const confirmationCb = getConfirmationCb(plugin, dispatch, mainnetPrompt) const confirmationCb = getConfirmationCb(plugin, dispatch, mainnetPrompt)
const isProxyDeployment = (deployMode || []).find(mode => mode === 'Deploy with Proxy')
if (selectedContract.isOverSizeLimit()) { if (selectedContract.isOverSizeLimit()) {
return dispatch(displayNotification('Contract code size over limit', isOverSizePrompt(), 'Force Send', 'Cancel', () => { return dispatch(displayNotification('Contract code size over limit', isOverSizePrompt(), 'Force Send', 'Cancel', () => {
@ -248,7 +252,6 @@ export const runTransactions = (
contractABI, contract, contractABI, contract,
address, address,
logMsg:string, logMsg:string,
logBuilder: (msg: string) => JSX.Element,
mainnetPrompt: MainnetPrompt, mainnetPrompt: MainnetPrompt,
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (msg: string) => JSX.Element,
passphrasePrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element,

@ -142,7 +142,9 @@ export const resetAndInit = (plugin: RunTab) => {
}, },
getGasLimit: (cb) => { getGasLimit: (cb) => {
try { try {
cb(null, '0x' + new ethJSUtil.BN(plugin.REACT_API.gasLimit, 10).toString(16)) const gasLimit = '0x' + new ethJSUtil.BN(plugin.REACT_API.gasLimit, 10).toString(16)
cb(null, gasLimit)
} catch (e) { } catch (e) {
cb(e.message) cb(e.message)
} }

@ -39,7 +39,7 @@ export const setPassphraseModal = (passphrase: string) => setPassphrasePrompt(di
export const setMatchPassphraseModal = (passphrase: string) => setMatchPassphrasePrompt(dispatch, passphrase) export const setMatchPassphraseModal = (passphrase: string) => setMatchPassphrasePrompt(dispatch, passphrase)
export const signMessage = (account: string, message: string, modalContent: (hash: string, data: string) => JSX.Element, passphrase?: string) => signMessageWithAddress(plugin, dispatch, account, message, modalContent, passphrase) export const signMessage = (account: string, message: string, modalContent: (hash: string, data: string) => JSX.Element, passphrase?: string) => signMessageWithAddress(plugin, dispatch, account, message, modalContent, passphrase)
export const fetchSelectedContract = (contractName: string, compiler: CompilerAbstractType) => getSelectedContract(contractName, compiler) export const fetchSelectedContract = (contractName: string, compiler: CompilerAbstractType) => getSelectedContract(contractName, compiler)
export const createNewInstance = 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, mainnetPrompt: MainnetPrompt, isOverSizePrompt: () => JSX.Element, args, deployMode: DeployMode[]) => createInstance(plugin, dispatch, selectedContract, gasEstimationPrompt, passphrasePrompt, logBuilder, publishToStorage, mainnetPrompt, isOverSizePrompt, args, deployMode) export const createNewInstance = async (selectedContract: ContractData, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, publishToStorage: (storage: 'ipfs' | 'swarm', contract: ContractData) => void, mainnetPrompt: MainnetPrompt, isOverSizePrompt: () => JSX.Element, args, deployMode: DeployMode[]) => createInstance(plugin, dispatch, selectedContract, gasEstimationPrompt, passphrasePrompt, publishToStorage, mainnetPrompt, isOverSizePrompt, args, deployMode)
export const setSendValue = (value: string) => setSendTransactionValue(dispatch, value) export const setSendValue = (value: string) => setSendTransactionValue(dispatch, value)
export const setBaseFeePerGas = (baseFee: string) => updateBaseFeePerGas(dispatch, baseFee) export const setBaseFeePerGas = (baseFee: string) => updateBaseFeePerGas(dispatch, baseFee)
export const setConfirmSettings = (confirmation: boolean) => updateConfirmSettings(dispatch, confirmation) export const setConfirmSettings = (confirmation: boolean) => updateConfirmSettings(dispatch, confirmation)
@ -51,10 +51,10 @@ export const setTxFeeContent = (content: string) => updateTxFeeContent(dispatch,
export const removeInstances = () => clearInstances(dispatch) export const removeInstances = () => clearInstances(dispatch)
export const removeSingleInstance = (index: number) => removeInstance(dispatch, index) export const removeSingleInstance = (index: number) => removeInstance(dispatch, index)
export const getExecutionContext = () => getContext(plugin) export const getExecutionContext = () => getContext(plugin)
export const executeTransactions = (instanceIndex: number, lookupOnly: boolean, funcABI: FuncABI, inputsValues: string, contractName: string, contractABI, contract, address, logMsg:string, logBuilder: (msg: string) => JSX.Element, mainnetPrompt: MainnetPrompt, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, funcIndex?: number) => runTransactions(plugin, dispatch, instanceIndex, lookupOnly, funcABI, inputsValues, contractName, contractABI, contract, address, logMsg, logBuilder, mainnetPrompt, gasEstimationPrompt, passphrasePrompt, funcIndex) export const executeTransactions = (instanceIndex: number, lookupOnly: boolean, funcABI: FuncABI, inputsValues: string, contractName: string, contractABI, contract, address, logMsg:string, mainnetPrompt: MainnetPrompt, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, funcIndex?: number) => runTransactions(plugin, dispatch, instanceIndex, lookupOnly, funcABI, inputsValues, contractName, contractABI, contract, address, logMsg, mainnetPrompt, gasEstimationPrompt, passphrasePrompt, funcIndex)
export const loadFromAddress = (contract: ContractData, address: string) => loadAddress(plugin, dispatch, contract, address) export const loadFromAddress = (contract: ContractData, address: string) => loadAddress(plugin, dispatch, contract, address)
export const storeNewScenario = async (prompt: (msg: string, defaultValue: string) => JSX.Element) => storeScenario(plugin, dispatch, prompt) export const storeNewScenario = async (prompt: (msg: string, defaultValue: string) => JSX.Element) => storeScenario(plugin, dispatch, prompt)
export const runScenario = (gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt, logBuilder: (msg: string) => JSX.Element) => runCurrentScenario(plugin, dispatch, gasEstimationPrompt, passphrasePrompt, confirmDialogContent, logBuilder) export const runScenario = (gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => runCurrentScenario(plugin, dispatch, gasEstimationPrompt, passphrasePrompt, confirmDialogContent)
export const setScenarioPath = (path: string) => updateScenarioPath(dispatch, path) export const setScenarioPath = (path: string) => updateScenarioPath(dispatch, path)
export const getFuncABIValues = (funcABI: FuncABI) => getFuncABIInputs(plugin, funcABI) export const getFuncABIValues = (funcABI: FuncABI) => getFuncABIInputs(plugin, funcABI)
export const setNetworkName = (networkName: string) => setNetworkNameFromProvider(dispatch, networkName) export const setNetworkName = (networkName: string) => setNetworkNameFromProvider(dispatch, networkName)

@ -1,4 +1,4 @@
import { createNonClashingNameAsync, extractNameFromKey } from "@remix-ui/helper" import { createNonClashingNameAsync, extractNameFromKey, logBuilder } from "@remix-ui/helper"
import { MainnetPrompt } from "../types" import { MainnetPrompt } from "../types"
import { RunTab } from "../types/run-tab" import { RunTab } from "../types/run-tab"
import { addInstance } from "./actions" import { addInstance } from "./actions"
@ -36,7 +36,7 @@ export const storeScenario = async (plugin: RunTab, dispatch: React.Dispatch<any
) )
} }
const runScenario = (plugin: RunTab, dispatch: React.Dispatch<any>, file: string, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt, logBuilder: (msg: string) => JSX.Element) => { const runScenario = (plugin: RunTab, dispatch: React.Dispatch<any>, file: string, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => {
if (!file) return dispatch(displayNotification('Alert', 'Unable to run scenerio, no specified scenario file', 'OK', null)) if (!file) return dispatch(displayNotification('Alert', 'Unable to run scenerio, no specified scenario file', 'OK', null))
plugin.fileManager.readFile(file).then((json) => { plugin.fileManager.readFile(file).then((json) => {
@ -64,9 +64,9 @@ const runScenario = (plugin: RunTab, dispatch: React.Dispatch<any>, file: string
}).catch((error) => dispatch(displayNotification('Alert', error, 'OK', null))) }).catch((error) => dispatch(displayNotification('Alert', error, 'OK', null)))
} }
export const runCurrentScenario = (plugin: RunTab, dispatch: React.Dispatch<any>, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt, logBuilder: (msg: string) => JSX.Element) => { export const runCurrentScenario = (plugin: RunTab, dispatch: React.Dispatch<any>, gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => {
const file = plugin.config.get('currentFile') const file = plugin.config.get('currentFile')
if (!file) return dispatch(displayNotification('Alert', 'A scenario file has to be selected', 'Ok', null)) if (!file) return dispatch(displayNotification('Alert', 'A scenario file has to be selected', 'Ok', null))
runScenario(plugin, dispatch, file, gasEstimationPrompt, passphrasePrompt, confirmDialogContent, logBuilder) runScenario(plugin, dispatch, file, gasEstimationPrompt, passphrasePrompt, confirmDialogContent)
} }

@ -151,7 +151,7 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
if (selectedContract.bytecodeObject.length === 0) { if (selectedContract.bytecodeObject.length === 0) {
return props.modal('Alert', 'This contract may be abstract, it may not implement an abstract parent\'s methods completely or it may not invoke an inherited contract\'s constructor correctly.', 'OK', () => {}) return props.modal('Alert', 'This contract may be abstract, it may not implement an abstract parent\'s methods completely or it may not invoke an inherited contract\'s constructor correctly.', 'OK', () => {})
} }
props.createInstance(loadedContractData, props.gasEstimationPrompt, props.passphrasePrompt, props.logBuilder, props.publishToStorage, props.mainnetPrompt, isOverSizePrompt, args, deployMode) props.createInstance(loadedContractData, props.gasEstimationPrompt, props.passphrasePrompt, props.publishToStorage, props.mainnetPrompt, isOverSizePrompt, args, deployMode)
} }
const atAddressChanged = (event) => { const atAddressChanged = (event) => {

@ -169,7 +169,7 @@ export function ContractGUI (props: ContractGUIProps) {
const handleActionClick = () => { const handleActionClick = () => {
const deployMode = selectedDeployIndex.map(index => props.deployOption[index].title) const deployMode = selectedDeployIndex.map(index => props.deployOption[index].title)
props.clickCallBack(props.funcABI.inputs, basicInput, props.isDeploy ? deployMode : null) props.clickCallBack(props.funcABI.inputs, basicInput, deployMode)
} }
const handleBasicInput = (e) => { const handleBasicInput = (e) => {
@ -180,11 +180,12 @@ export function ContractGUI (props: ContractGUIProps) {
const handleMultiValsSubmit = () => { const handleMultiValsSubmit = () => {
const valsString = getMultiValsString() const valsString = getMultiValsString()
const deployMode = selectedDeployIndex.map(index => props.deployOption[index].title)
if (valsString) { if (valsString) {
props.clickCallBack(props.funcABI.inputs, valsString) props.clickCallBack(props.funcABI.inputs, valsString, deployMode)
} else { } else {
props.clickCallBack(props.funcABI.inputs, '') props.clickCallBack(props.funcABI.inputs, '', deployMode)
} }
} }
@ -259,14 +260,12 @@ export function ContractGUI (props: ContractGUIProps) {
</> </>
} }
</div> </div>
{ isMultiField ? { isMultiField && props.isDeploy && props.initializerOptions &&
props.isDeploy && props.initializerOptions ?
<div className="udapp_contractActionsContainerMulti" style={{ display: 'flex' }}> <div className="udapp_contractActionsContainerMulti" style={{ display: 'flex' }}>
<div className="udapp_contractActionsContainerMultiInner text-dark"> <div className="udapp_contractActionsContainerMultiInner text-dark">
{/* <div onClick={switchMethodViewOff} className="udapp_multiHeader"> <div className="udapp_multiHeader">
<div className="udapp_multiTitle run-instance-multi-title">{title}</div> <div className="udapp_multiTitle run-instance-multi-title">{title}</div>
<i className='fas fa-angle-up udapp_methCaret'></i> </div>
</div> */}
<div> <div>
{props.initializerOptions.inputs.inputs.map((inp, index) => { {props.initializerOptions.inputs.inputs.map((inp, index) => {
return ( return (
@ -293,13 +292,13 @@ export function ContractGUI (props: ContractGUIProps) {
} }
</div> </div>
</div> </div>
</div> : </div>
<div className="udapp_contractActionsContainerMulti" style={{ display: 'flex' }}> }
<div className="udapp_contractActionsContainerMulti" style={{ display: 'flex' }}>
<div className="udapp_contractActionsContainerMultiInner text-dark"> <div className="udapp_contractActionsContainerMultiInner text-dark">
{/* <div onClick={switchMethodViewOff} className="udapp_multiHeader"> <div className="udapp_multiHeader">
<div className="udapp_multiTitle run-instance-multi-title">{title}</div> <div className="udapp_multiTitle run-instance-multi-title">{title}</div>
<i className='fas fa-angle-up udapp_methCaret'></i> </div>
</div> */}
<div> <div>
{props.funcABI.inputs.map((inp, index) => { {props.funcABI.inputs.map((inp, index) => {
return ( return (
@ -315,8 +314,6 @@ export function ContractGUI (props: ContractGUIProps) {
</div> </div>
</div> </div>
</div> </div>
: null
}
</div> </div>
) )
} }

@ -30,7 +30,6 @@ export function InstanceContainerUI (props: InstanceContainerProps) {
removeInstance={props.removeInstance} removeInstance={props.removeInstance}
index={index} index={index}
gasEstimationPrompt={props.gasEstimationPrompt} gasEstimationPrompt={props.gasEstimationPrompt}
logBuilder={props.logBuilder}
passphrasePrompt={props.passphrasePrompt} passphrasePrompt={props.passphrasePrompt}
mainnetPrompt={props.mainnetPrompt} mainnetPrompt={props.mainnetPrompt}
runTransactions={props.runTransactions} runTransactions={props.runTransactions}

@ -9,7 +9,7 @@ export function RecorderUI (props: RecorderProps) {
} }
const handleClickRunButton = () => { const handleClickRunButton = () => {
props.runCurrentScenario(props.gasEstimationPrompt, props.passphrasePrompt, props.mainnetPrompt, props.logBuilder) props.runCurrentScenario(props.gasEstimationPrompt, props.passphrasePrompt, props.mainnetPrompt)
} }
const toggleClass = () => { const toggleClass = () => {

@ -119,7 +119,6 @@ export function UniversalDappUI (props: UdappProps) {
props.instance.contractData, props.instance.contractData,
address, address,
logMsg, logMsg,
props.logBuilder,
props.mainnetPrompt, props.mainnetPrompt,
props.gasEstimationPrompt, props.gasEstimationPrompt,
props.passphrasePrompt, props.passphrasePrompt,

@ -166,10 +166,6 @@ export function RunTabUI (props: RunTabProps) {
) )
} }
const logBuilder = (msg: string) => {
return <pre>{msg}</pre>
}
const passphrasePrompt = (message: string) => { const passphrasePrompt = (message: string) => {
return <PassphrasePrompt message={message} setPassphrase={setPassphraseModal} defaultValue={runTab.passphrase} /> return <PassphrasePrompt message={message} setPassphrase={setPassphraseModal} defaultValue={runTab.passphrase} />
} }
@ -237,7 +233,6 @@ export function RunTabUI (props: RunTabProps) {
setIpfsCheckedState={setCheckIpfs} setIpfsCheckedState={setCheckIpfs}
publishToStorage={publishToStorage} publishToStorage={publishToStorage}
gasEstimationPrompt={gasEstimationPrompt} gasEstimationPrompt={gasEstimationPrompt}
logBuilder={logBuilder}
passphrasePrompt={passphrasePrompt} passphrasePrompt={passphrasePrompt}
mainnetPrompt={mainnetPrompt} mainnetPrompt={mainnetPrompt}
tooltip={toast} tooltip={toast}
@ -248,7 +243,6 @@ export function RunTabUI (props: RunTabProps) {
/> />
<RecorderUI <RecorderUI
gasEstimationPrompt={gasEstimationPrompt} gasEstimationPrompt={gasEstimationPrompt}
logBuilder={logBuilder}
passphrasePrompt={passphrasePrompt} passphrasePrompt={passphrasePrompt}
mainnetPrompt={mainnetPrompt} mainnetPrompt={mainnetPrompt}
storeScenario={storeNewScenario} storeScenario={storeNewScenario}
@ -262,7 +256,6 @@ export function RunTabUI (props: RunTabProps) {
removeInstance={removeSingleInstance} removeInstance={removeSingleInstance}
getContext={getExecutionContext} getContext={getExecutionContext}
gasEstimationPrompt={gasEstimationPrompt} gasEstimationPrompt={gasEstimationPrompt}
logBuilder={logBuilder}
passphrasePrompt={passphrasePrompt} passphrasePrompt={passphrasePrompt}
mainnetPrompt={mainnetPrompt} mainnetPrompt={mainnetPrompt}
runTransactions={executeTransactions} runTransactions={executeTransactions}

@ -144,7 +144,6 @@ export interface ContractDropdownProps {
selectedContract: ContractData, selectedContract: ContractData,
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (msg: string) => JSX.Element,
passphrasePrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element,
logBuilder: (msg: string) => JSX.Element,
publishToStorage: (storage: 'ipfs' | 'swarm', publishToStorage: (storage: 'ipfs' | 'swarm',
contract: ContractData) => void, contract: ContractData) => void,
mainnetPrompt: MainnetPrompt, mainnetPrompt: MainnetPrompt,
@ -155,7 +154,6 @@ export interface ContractDropdownProps {
setIpfsCheckedState: (value: boolean) => void, setIpfsCheckedState: (value: boolean) => void,
publishToStorage: (storage: 'ipfs' | 'swarm', contract: ContractData) => void, publishToStorage: (storage: 'ipfs' | 'swarm', contract: ContractData) => void,
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (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, tooltip: (toasterMsg: string | JSX.Element) => void,
@ -167,8 +165,7 @@ export interface ContractDropdownProps {
export interface RecorderProps { export interface RecorderProps {
storeScenario: (prompt: (msg: string, defaultValue: string) => JSX.Element) => void, storeScenario: (prompt: (msg: string, defaultValue: string) => JSX.Element) => void,
runCurrentScenario: (gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt, logBuilder: (msg: string) => JSX.Element) => void, runCurrentScenario: (gasEstimationPrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element, confirmDialogContent: MainnetPrompt) => void,
logBuilder: (msg: string) => JSX.Element,
mainnetPrompt: MainnetPrompt, mainnetPrompt: MainnetPrompt,
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (msg: string) => JSX.Element,
passphrasePrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element,
@ -199,13 +196,11 @@ export interface InstanceContainerProps {
contractABI, contract, contractABI, contract,
address, address,
logMsg:string, logMsg:string,
logBuilder: (msg: string) => JSX.Element,
mainnetPrompt: MainnetPrompt, mainnetPrompt: MainnetPrompt,
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (msg: string) => JSX.Element,
passphrasePrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element,
funcIndex?: number) => void, funcIndex?: number) => void,
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (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,
sendValue: string, sendValue: string,
@ -292,7 +287,6 @@ export interface UdappProps {
removeInstance: (index: number) => void, removeInstance: (index: number) => void,
index: number, index: number,
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (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,
runTransactions: ( runTransactions: (
@ -304,7 +298,6 @@ export interface UdappProps {
contractABI, contract, contractABI, contract,
address, address,
logMsg:string, logMsg:string,
logBuilder: (msg: string) => JSX.Element,
mainnetPrompt: MainnetPrompt, mainnetPrompt: MainnetPrompt,
gasEstimationPrompt: (msg: string) => JSX.Element, gasEstimationPrompt: (msg: string) => JSX.Element,
passphrasePrompt: (msg: string) => JSX.Element, passphrasePrompt: (msg: string) => JSX.Element,

Loading…
Cancel
Save