Decode response

yann300-patch-36
David Disu 3 years ago committed by yann300
parent 3281126ca3
commit 737218a814
  1. 129
      libs/remix-ui/run-tab/src/lib/actions/index.ts
  2. 10
      libs/remix-ui/run-tab/src/lib/actions/payload.ts
  3. 43
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  4. 13
      libs/remix-ui/run-tab/src/lib/components/instanceContainerUI.tsx
  5. 136
      libs/remix-ui/run-tab/src/lib/components/universalDappUI.tsx
  6. 19
      libs/remix-ui/run-tab/src/lib/reducers/runTab.ts
  7. 70
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  8. 4
      libs/remix-ui/run-tab/src/lib/types/blockchain.d.ts
  9. 76
      libs/remix-ui/run-tab/src/lib/types/index.ts

@ -3,11 +3,13 @@ import React from 'react'
import * as ethJSUtil from 'ethereumjs-util' import * as ethJSUtil from 'ethereumjs-util'
import Web3 from 'web3' import Web3 from 'web3'
import { addressToString, shortenAddress } from '@remix-ui/helper' import { addressToString, shortenAddress } from '@remix-ui/helper'
import { addNewInstance, addProvider, clearAllInstances, displayNotification, displayPopUp, fetchAccountsListFailed, fetchAccountsListRequest, fetchAccountsListSuccess, fetchContractListSuccess, hidePopUp, removeExistingInstance, removeProvider, setBaseFeePerGas, setConfirmSettings, setCurrentFile, setExecutionEnvironment, setExternalEndpoint, setGasLimit, setGasPrice, setGasPriceStatus, setIpfsCheckedState, setLoadType, setMatchPassphrase, setMaxFee, setMaxPriorityFee, setNetworkName, setPassphrase, setSelectedAccount, setSendUnit, setSendValue, setTxFeeContent } from './payload' import { addNewInstance, addProvider, clearAllInstances, displayNotification, displayPopUp, fetchAccountsListFailed, fetchAccountsListRequest, fetchAccountsListSuccess, fetchContractListSuccess, hidePopUp, removeExistingInstance, removeProvider, setBaseFeePerGas, setConfirmSettings, setCurrentFile, setDecodedResponse, 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 { 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, Network, Tx } from '../types' import { ContractData, FuncABI, MainnetPrompt, Network, Tx } from '../types'
const txFormat = remixLib.execution.txFormat
declare global { declare global {
interface Window { interface Window {
_paq: any _paq: any
@ -374,15 +376,7 @@ const terminalLogger = (view: JSX.Element) => {
plugin.call('terminal', 'logHtml', view) plugin.call('terminal', 'logHtml', view)
} }
const getConfirmationCb = (confirmDialogContent: ( const confirmationHandler = (confirmDialogContent: MainnetPrompt, network, tx, gasEstimation, continueTxExecution, cancelCb) => {
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) => {
// 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') { if (network.name !== 'Main') {
return continueTxExecution(null) return continueTxExecution(null)
} }
@ -402,26 +396,14 @@ const getConfirmationCb = (confirmDialogContent: (
})) }))
} }
return confirmationCb const getConfirmationCb = (confirmDialogContent: MainnetPrompt) => {
// this code is the same as in recorder.js. TODO need to be refactored out
return (network, tx, gasEstimation, continueTxExecution, cancelCb) => {
confirmationHandler(confirmDialogContent, network, tx, gasEstimation, continueTxExecution, cancelCb)
}
} }
export const createInstance = async ( const continueHandler = (gasEstimationPrompt: (msg: string) => JSX.Element, error, continueTxExecution, cancelCb) => {
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: (
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,
isOverSizePrompt: () => JSX.Element,
args) => {
const continueCb = (error, continueTxExecution, cancelCb) => {
if (error) { if (error) {
const msg = typeof error !== 'string' ? error.message : error const msg = typeof error !== 'string' ? error.message : error
@ -435,10 +417,20 @@ export const createInstance = async (
} }
} }
const promptCb = (okCb, cancelCb) => { const promptHandler = (passphrasePrompt, okCb, cancelCb) => {
dispatch(displayNotification('Passphrase requested', passphrasePrompt('Personal mode is enabled. Please provide passphrase of account'), 'OK', 'Cancel', okCb, cancelCb)) dispatch(displayNotification('Passphrase requested', passphrasePrompt('Personal mode is enabled. Please provide passphrase of account'), 'OK', 'Cancel', okCb, cancelCb))
} }
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,
mainnetPrompt: MainnetPrompt,
isOverSizePrompt: () => JSX.Element,
args) => {
const statusCb = (msg: string) => { const statusCb = (msg: string) => {
const log = logBuilder(msg) const log = logBuilder(msg)
@ -476,14 +468,32 @@ export const createInstance = async (
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', () => {
deployContract(selectedContract, args, contractMetadata, compilerContracts, { continueCb, promptCb, statusCb, finalCb }, confirmationCb) deployContract(selectedContract, args, contractMetadata, compilerContracts, {
continueCb: (error, continueTxExecution, cancelCb) => {
continueHandler(gasEstimationPrompt, error, continueTxExecution, cancelCb)
},
promptCb: (okCb, cancelCb) => {
promptHandler(passphrasePrompt, okCb, cancelCb)
},
statusCb,
finalCb
}, confirmationCb)
}, () => { }, () => {
const log = logBuilder(`creation of ${selectedContract.name} canceled by user.`) const log = logBuilder(`creation of ${selectedContract.name} canceled by user.`)
return terminalLogger(log) return terminalLogger(log)
})) }))
} }
deployContract(selectedContract, args, contractMetadata, compilerContracts, { continueCb, promptCb, statusCb, finalCb }, confirmationCb) deployContract(selectedContract, args, contractMetadata, compilerContracts, {
continueCb: (error, continueTxExecution, cancelCb) => {
continueHandler(gasEstimationPrompt, error, continueTxExecution, cancelCb)
},
promptCb: (okCb, cancelCb) => {
promptHandler(passphrasePrompt, okCb, cancelCb)
},
statusCb,
finalCb
}, confirmationCb)
} }
const deployContract = (selectedContract, args, contractMetadata, compilerContracts, callbacks, confirmationCb) => { const deployContract = (selectedContract, args, contractMetadata, compilerContracts, callbacks, confirmationCb) => {
@ -574,3 +584,58 @@ const loadAddress = () => {
export const getContext = () => { export const getContext = () => {
return plugin.blockchain.context() return plugin.blockchain.context()
} }
export const runTransactions = (
index: 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) => {
let callinfo = ''
if (lookupOnly) callinfo = 'call'
else if (funcABI.type === 'fallback' || funcABI.type === 'receive') callinfo = 'lowLevelInteracions'
else callinfo = 'transact'
_paq.push(['trackEvent', 'udapp', callinfo, plugin.blockchain.getCurrentNetworkStatus().network.name])
const params = funcABI.type !== 'fallback' ? inputsValues : ''
plugin.blockchain.runOrCallContractMethod(
contractName,
contractABI,
funcABI,
contract,
inputsValues,
address,
params,
lookupOnly,
logMsg,
(msg) => {
const log = logBuilder(msg)
return terminalLogger(log)
},
(returnValue) => {
const decodedResponse = txFormat.decodeResponse(returnValue, funcABI)
console.log('decodedResponse: ', decodedResponse)
dispatch(setDecodedResponse(index, decodedResponse))
},
(network, tx, gasEstimation, continueTxExecution, cancelCb) => {
confirmationHandler(mainnetPrompt, network, tx, gasEstimation, continueTxExecution, cancelCb)
},
(error, continueTxExecution, cancelCb) => {
continueHandler(gasEstimationPrompt, error, continueTxExecution, cancelCb)
},
(okCb, cancelCb) => {
promptHandler(passphrasePrompt, okCb, cancelCb)
}
)
}

@ -239,3 +239,13 @@ export const clearAllInstances = () => {
type: 'CLEAR_INSTANCES' type: 'CLEAR_INSTANCES'
} }
} }
export const setDecodedResponse = (index: number, decodedResponse) => {
return {
type: 'SET_DECODED_RESPONSE',
payload: {
index,
decodedResponse
}
}
}

@ -1,10 +1,8 @@
// eslint-disable-next-line no-use-before-define // eslint-disable-next-line no-use-before-define
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { ContractData, ContractDropdownProps, Network, Tx } from '../types' import { ContractData, ContractDropdownProps } from '../types'
import * as ethJSUtil from 'ethereumjs-util' import * as ethJSUtil from 'ethereumjs-util'
import { ContractGUI } from './contractGUI' import { ContractGUI } from './contractGUI'
import { PassphrasePrompt } from './passphrase'
import { MainnetPrompt } from './mainnet'
export function ContractDropdownUI (props: ContractDropdownProps) { export function ContractDropdownUI (props: ContractDropdownProps) {
const [networkName, setNetworkName] = useState<string>('') const [networkName, setNetworkName] = useState<string>('')
@ -122,7 +120,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, not implement an abstract parent\'s methods completely or not invoke an inherited contract\'s constructor correctly.', 'OK', () => {}) 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(loadedContractData, gasEstimationPrompt, passphrasePrompt, logBuilder, props.publishToStorage, mainnetPrompt, isOverSizePrompt, args) props.createInstance(loadedContractData, props.gasEstimationPrompt, props.passphrasePrompt, props.logBuilder, props.publishToStorage, props.mainnetPrompt, isOverSizePrompt, args)
} }
// listenToContextChange () { // listenToContextChange () {
@ -176,43 +174,6 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
setSelectedContract(value) setSelectedContract(value)
} }
const gasEstimationPrompt = (msg: string) => {
return (
<div>Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? <br />
${msg}
</div>
)
}
const logBuilder = (msg: string) => {
return <pre>{msg}</pre>
}
const passphrasePrompt = (message: string) => {
return <PassphrasePrompt message={message} setPassphrase={props.setPassphrase} defaultValue={props.passphrase} />
}
const 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) => {
return <MainnetPrompt
init={determineGasPrice}
network={network}
tx={tx}
amount={amount}
gasEstimation={gasEstimation}
setNewGasPrice={gasFees}
updateBaseFeePerGas={props.updateBaseFeePerGas}
updateConfirmSettings={props.updateConfirmSettings}
updateGasPrice={props.updateGasPrice}
updateGasPriceStatus={props.updateGasPriceStatus}
updateMaxFee={props.updateMaxFee}
updateMaxPriorityFee={props.updateMaxPriorityFee}
setTxFeeContent={props.updateTxFeeContent}
txFeeContent={props.txFeeContent}
maxFee={props.maxFee}
maxPriorityFee={props.maxPriorityFee}
/>
}
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 />

@ -23,7 +23,18 @@ export function InstanceContainerUI (props: InstanceContainerProps) {
</div> </div>
{ instanceList.length > 0 { instanceList.length > 0
? <div> { props.instances.instanceList.map((instance, index) => { ? <div> { props.instances.instanceList.map((instance, index) => {
return <UniversalDappUI instance={instance} context={props.getContext()} removeInstance={props.removeInstance} index={index} /> return <UniversalDappUI
instance={instance}
context={props.getContext()}
removeInstance={props.removeInstance}
index={index}
gasEstimationPrompt={props.gasEstimationPrompt}
logBuilder={props.logBuilder}
passphrasePrompt={props.passphrasePrompt}
mainnetPrompt={props.mainnetPrompt}
runTransactions={props.runTransactions}
decodedResponse={instance.decodedResponse || {}}
/>
}) } }) }
</div> </div>
: <span className="mx-2 mt-3 alert alert-warning" data-id="deployAndRunNoInstanceText" role="alert"> : <span className="mx-2 mt-3 alert alert-warning" data-id="deployAndRunNoInstanceText" role="alert">

@ -6,6 +6,8 @@ import { CopyToClipboard } from '@remix-ui/clipboard'
import * as remixLib from '@remix-project/remix-lib' import * as remixLib from '@remix-project/remix-lib'
import * as ethJSUtil from 'ethereumjs-util' import * as ethJSUtil from 'ethereumjs-util'
import { ContractGUI } from './contractGUI' import { ContractGUI } from './contractGUI'
import { TreeView, TreeViewItem } from '@remix-ui/tree-view'
import { BN } from 'ethereumjs-util'
const txHelper = remixLib.execution.txHelper const txHelper = remixLib.execution.txHelper
@ -13,6 +15,7 @@ export function UniversalDappUI (props: UdappProps) {
const [toggleExpander, setToggleExpander] = useState<boolean>(true) const [toggleExpander, setToggleExpander] = useState<boolean>(true)
const [contractABI, setContractABI] = useState<FuncABI[]>(null) const [contractABI, setContractABI] = useState<FuncABI[]>(null)
const [address, setAddress] = useState<string>('') const [address, setAddress] = useState<string>('')
const [expandPath, setExpandPath] = useState<string[]>([])
useEffect(() => { useEffect(() => {
if (!props.abi) { if (!props.abi) {
@ -135,41 +138,95 @@ export function UniversalDappUI (props: UdappProps) {
const functionName = funcABI.type === 'function' ? funcABI.name : `(${funcABI.type})` const functionName = funcABI.type === 'function' ? funcABI.name : `(${funcABI.type})`
const logMsg = `${lookupOnly ? 'call' : 'transact'} to ${props.instance.name}.${functionName}` const logMsg = `${lookupOnly ? 'call' : 'transact'} to ${props.instance.name}.${functionName}`
// const callbacksInContext = txCallBacks.getCallBacksWithContext(this, this.blockchain) props.runTransactions(
props.index,
lookupOnly,
funcABI,
inputsValues,
props.instance.name,
contractABI,
props.instance.contractData,
props.instance.address,
logMsg,
props.logBuilder,
props.mainnetPrompt,
props.gasEstimationPrompt,
props.passphrasePrompt)
}
// const outputCb = (returnValue) => { const extractDataDefault = (item, parent?) => {
// if (outputOverride) { const ret: any = {}
// const decoded = decodeResponseToTreeView(returnValue, args.funABI)
// outputOverride.innerHTML = '' if (BN.isBN(item)) {
// outputOverride.appendChild(decoded) ret.self = item.toString(10)
// } ret.children = []
// } } else {
// let callinfo = '' if (item instanceof Array) {
// if (lookupOnly) callinfo = 'call' ret.children = item.map((item, index) => {
// else if (args.funABI.type === 'fallback' || args.funABI.type === 'receive') callinfo = 'lowLevelInteracions' return { key: index, value: item }
// else callinfo = 'transact' })
ret.self = 'Array'
// _paq.push(['trackEvent', 'udapp', callinfo, this.blockchain.getCurrentNetworkStatus().network.name]) ret.isNode = true
// const params = args.funABI.type !== 'fallback' ? inputsValues : '' ret.isLeaf = false
// this.blockchain.runOrCallContractMethod( } else if (item instanceof Object) {
// args.contractName, ret.children = Object.keys(item).map((key) => {
// args.contractABI, return { key: key, value: item[key] }
// args.funABI, })
// args.contract, ret.self = 'Object'
// inputsValues, ret.isNode = true
// args.address, ret.isLeaf = false
// params, } else {
// lookupOnly, ret.self = item
// logMsg, ret.children = null
// this.logCallback, ret.isNode = false
// outputCb, ret.isLeaf = true
// callbacksInContext.confirmationCb.bind(callbacksInContext), }
// callbacksInContext.continueCb.bind(callbacksInContext),
// callbacksInContext.promptCb.bind(callbacksInContext))
} }
return ret
}
const handleExpand = (path: string) => {
if (expandPath.includes(path)) {
const filteredPath = expandPath.filter(value => value !== path)
setExpandPath(filteredPath)
} else {
setExpandPath([...expandPath, path])
}
}
const label = (key: string | number, value: string) => {
return ( return (
<div className={`udapp_instance udapp_run-instance border-dark ${toggleExpander ? 'udapp_hidesub' : ''}`} id={`instance${address}`} data-shared="universalDappUiInstance"> <div className="d-flex mr-1 flex-row label_item">
<label className="small font-weight-bold mb-0 pr-1 label_key">{key}:</label>
<label className="m-0 label_value">{value}</label>
</div>
)
}
const renderData = (item, parent, key: string | number, keyPath: string) => {
const data = extractDataDefault(item, parent)
const children = (data.children || []).map((child) => {
return (
renderData(child.value, data, child.key, keyPath + '/' + child.key)
)
})
if (children && children.length > 0) {
return (
<TreeViewItem id={`treeViewItem${key}`} key={keyPath} label={label(key, data.self)} onClick={() => handleExpand(keyPath)} expand={expandPath.includes(keyPath)}>
<TreeView id={`treeView${key}`} key={keyPath}>
{children}
</TreeView>
</TreeViewItem>
)
} else {
return <TreeViewItem id={key.toString()} key={keyPath} label={label(key, data.self)} onClick={() => handleExpand(keyPath)} expand={expandPath.includes(keyPath)} />
}
}
return (
<div className={`udapp_instance udapp_run-instance border-dark ${toggleExpander ? 'udapp_hidesub' : 'bg-light'}`} id={`instance${address}`} data-shared="universalDappUiInstance">
<div className="udapp_title alert alert-secondary"> <div className="udapp_title alert alert-secondary">
<button data-id="universalDappUiTitleExpander" className="btn udapp_titleExpander" onClick={toggleClass}> <button data-id="universalDappUiTitleExpander" className="btn udapp_titleExpander" onClick={toggleClass}>
<i className={`fas ${toggleExpander ? 'fa-angle-right' : 'fa-angle-down'}`} aria-hidden="true"></i> <i className={`fas ${toggleExpander ? 'fa-angle-right' : 'fa-angle-down'}`} aria-hidden="true"></i>
@ -181,7 +238,7 @@ export function UniversalDappUI (props: UdappProps) {
</span> </span>
</div> </div>
<div className="btn-group"> <div className="btn-group">
<button className="btn p-1 btn-secondary"><CopyToClipboard content={address} /></button> <button className="btn p-1 btn-secondary"><CopyToClipboard content={address} direction={'top'} /></button>
</div> </div>
</div> </div>
<button <button
@ -195,16 +252,23 @@ export function UniversalDappUI (props: UdappProps) {
</div> </div>
<div className="udapp_cActionsWrapper" data-id="universalDappUiContractActionWrapper"> <div className="udapp_cActionsWrapper" data-id="universalDappUiContractActionWrapper">
{ {
contractABI && contractABI.map((funcABI) => { contractABI && contractABI.map((funcABI, index) => {
if (funcABI.type !== 'function') return null if (funcABI.type !== 'function') return null
const isConstant = funcABI.constant !== undefined ? funcABI.constant : false const isConstant = funcABI.constant !== undefined ? funcABI.constant : false
const lookupOnly = funcABI.stateMutability === 'view' || funcABI.stateMutability === 'pure' || isConstant const lookupOnly = funcABI.stateMutability === 'view' || funcABI.stateMutability === 'pure' || isConstant
return <div className="udapp_value"> return <ContractGUI funcABI={funcABI} clickCallBack={(valArray: { name: string, type: string }[], inputsValues: string) => runTransaction(lookupOnly, funcABI, valArray, inputsValues)} inputs={props.instance.contractData.getConstructorInputs()} evmBC={props.instance.contractData.bytecodeObject} lookupOnly={lookupOnly} />
<ContractGUI funcABI={funcABI} clickCallBack={(valArray: { name: string, type: string }[], inputsValues: string) => runTransaction(lookupOnly, funcABI, valArray, inputsValues)} inputs={props.instance.contractData.getConstructorInputs()} evmBC={props.instance.contractData.bytecodeObject} lookupOnly={lookupOnly} />
</div>
}) })
} }
<div className="udapp_value">
<TreeView id="treeView">
{
Object.keys(props.decodedResponse).map((innerkey) => {
return renderData(props.decodedResponse[innerkey], props.decodedResponse, innerkey, innerkey)
})
}
</TreeView>
</div>
</div> </div>
</div> </div>
) )

@ -68,7 +68,8 @@ export interface RunTabState {
instanceList: { instanceList: {
contractData: ContractData, contractData: ContractData,
address: string, address: string,
name: string name: string,
decodedResponse?: any
}[], }[],
error: string error: string
} }
@ -566,6 +567,22 @@ export const runTabReducer = (state: RunTabState = runTabInitialState, action: A
} }
} }
case 'SET_DECODED_RESPONSE': {
const payload: any = action.payload
return {
...state,
instances: {
...state.instances,
instanceList: state.instances.instanceList.map((instance, index) => {
console.log('payload: ', payload)
if (payload.index === index) instance.decodedResponse = payload.decodedResponse
return instance
})
}
}
}
default: default:
return state return state
} }

@ -7,7 +7,7 @@ import { ContractDropdownUI } from './components/contractDropdownUI'
import { InstanceContainerUI } from './components/instanceContainerUI' import { InstanceContainerUI } from './components/instanceContainerUI'
import { RecorderUI } from './components/recorderCardUI' import { RecorderUI } from './components/recorderCardUI'
import { SettingsUI } from './components/settingsUI' import { SettingsUI } from './components/settingsUI'
import { ContractData, Modal, RunTabProps } from './types' import { ContractData, Modal, Network, RunTabProps, Tx } from './types'
import { runTabInitialState, runTabReducer } from './reducers/runTab' import { runTabInitialState, runTabReducer } from './reducers/runTab'
import { import {
initRunTab, setAccount, initRunTab, setAccount,
@ -21,10 +21,13 @@ import {
updateGasPrice, updateGasPriceStatus, updateGasPrice, updateGasPriceStatus,
updateMaxFee, updateMaxPriorityFee, updateMaxFee, updateMaxPriorityFee,
updateTxFeeContent, clearInstances, updateTxFeeContent, clearInstances,
removeInstance, getContext removeInstance, getContext,
runTransactions
} 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'
import { PassphrasePrompt } from './components/passphrase'
import { MainnetPrompt } from './components/mainnet'
export function RunTabUI (props: RunTabProps) { export function RunTabUI (props: RunTabProps) {
const { plugin } = props const { plugin } = props
@ -142,6 +145,43 @@ export function RunTabUI (props: RunTabProps) {
}) })
} }
const gasEstimationPrompt = (msg: string) => {
return (
<div>Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? <br />
{msg}
</div>
)
}
const logBuilder = (msg: string) => {
return <pre>{msg}</pre>
}
const passphrasePrompt = (message: string) => {
return <PassphrasePrompt message={message} setPassphrase={setPassphrasePrompt} defaultValue={runTab.passphrase} />
}
const 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) => {
return <MainnetPrompt
init={determineGasPrice}
network={network}
tx={tx}
amount={amount}
gasEstimation={gasEstimation}
setNewGasPrice={gasFees}
updateBaseFeePerGas={updateBaseFeePerGas}
updateConfirmSettings={updateConfirmSettings}
updateGasPrice={updateGasPrice}
updateGasPriceStatus={updateGasPriceStatus}
updateMaxFee={updateMaxFee}
updateMaxPriorityFee={updateMaxPriorityFee}
setTxFeeContent={updateTxFeeContent}
txFeeContent={runTab.txFeeContent}
maxFee={runTab.maxFee}
maxPriorityFee={runTab.maxPriorityFee}
/>
}
return ( return (
<Fragment> <Fragment>
<div className="udapp_runTabView run-tab" id="runTabView" data-id="runTabView"> <div className="udapp_runTabView run-tab" id="runTabView" data-id="runTabView">
@ -180,19 +220,23 @@ export function RunTabUI (props: RunTabProps) {
ipfsCheckedState={runTab.ipfsChecked} ipfsCheckedState={runTab.ipfsChecked}
setIpfsCheckedState={setCheckIpfs} setIpfsCheckedState={setCheckIpfs}
publishToStorage={publishToStorage} publishToStorage={publishToStorage}
updateBaseFeePerGas={updateBaseFeePerGas} gasEstimationPrompt={gasEstimationPrompt}
updateConfirmSettings={updateConfirmSettings} logBuilder={logBuilder}
updateGasPrice={updateGasPrice} passphrasePrompt={passphrasePrompt}
updateGasPriceStatus={updateGasPriceStatus} mainnetPrompt={mainnetPrompt}
updateMaxFee={updateMaxFee}
updateMaxPriorityFee={updateMaxPriorityFee}
updateTxFeeContent={updateTxFeeContent}
txFeeContent={runTab.txFeeContent}
maxFee={runTab.maxFee}
maxPriorityFee={runTab.maxPriorityFee}
/> />
<RecorderUI /> <RecorderUI />
<InstanceContainerUI instances={runTab.instances} clearInstances={clearInstances} removeInstance={removeInstance} getContext={getContext} /> <InstanceContainerUI
instances={runTab.instances}
clearInstances={clearInstances}
removeInstance={removeInstance}
getContext={getContext}
gasEstimationPrompt={gasEstimationPrompt}
logBuilder={logBuilder}
passphrasePrompt={passphrasePrompt}
mainnetPrompt={mainnetPrompt}
runTransactions={runTransactions}
/>
</div> </div>
</div> </div>
<ModalDialog id='fileSystem' { ...focusModal } handleHide={ handleHideModal } /> <ModalDialog id='fileSystem' { ...focusModal } handleHide={ handleHideModal } />

@ -14,6 +14,10 @@ export class Blockchain extends Plugin<any, any> {
getCurrentNetworkStatus(): { getCurrentNetworkStatus(): {
name: string; name: string;
id: string; id: string;
network?: {
name: string;
id: string;
};
}; };
setupProviders(): void; setupProviders(): void;
providers: {}; providers: {};

@ -1,3 +1,4 @@
import { type } from 'os'
import { RunTab } from './run-tab' import { RunTab } from './run-tab'
export interface RunTabProps { export interface RunTabProps {
plugin: RunTab plugin: RunTab
@ -137,6 +138,14 @@ export interface Network {
} }
} }
export type 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
export interface ContractDropdownProps { export interface ContractDropdownProps {
exEnvironment: string, exEnvironment: string,
contracts: { contracts: {
@ -155,34 +164,23 @@ export interface ContractDropdownProps {
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, passphrase: string,
setPassphrase: (passphrase: string) => void, setPassphrase: (passphrase: string) => void,
createInstance: (selectedContract: ContractData, createInstance: (
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, logBuilder: (msg: string) => JSX.Element,
publishToStorage: (storage: 'ipfs' | 'swarm', publishToStorage: (storage: 'ipfs' | 'swarm',
contract: ContractData) => void, contract: ContractData) => void,
mainnetPrompt: ( mainnetPrompt: 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,
isOverSizePrompt: () => JSX.Element, isOverSizePrompt: () => JSX.Element,
args) => void, args) => void,
ipfsCheckedState: boolean, ipfsCheckedState: boolean,
setIpfsCheckedState: (value: boolean) => void, setIpfsCheckedState: (value: boolean) => void,
publishToStorage: (storage: 'ipfs' | 'swarm', contract: ContractData) => void, publishToStorage: (storage: 'ipfs' | 'swarm', contract: ContractData) => void,
updateBaseFeePerGas: (baseFee: string) => void, gasEstimationPrompt: (msg: string) => JSX.Element,
updateGasPriceStatus: (status: boolean) => void, logBuilder: (msg: string) => JSX.Element,
updateConfirmSettings: (confirmation: boolean) => void, passphrasePrompt: (message: string) => JSX.Element,
updateMaxFee: (fee: string) => void, 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
updateMaxPriorityFee: (fee: string) => void,
updateGasPrice: (price: string) => void,
updateTxFeeContent: (content: string) => void,
txFeeContent: string,
maxFee: string,
maxPriorityFee: string
} }
export interface RecorderProps { export interface RecorderProps {
@ -194,13 +192,31 @@ export interface InstanceContainerProps {
instanceList: { instanceList: {
contractData: ContractData, contractData: ContractData,
address: string, address: string,
name: string name: string,
decodedResponse?: any
}[], }[],
error: string error: string
}, },
clearInstances: () => void, clearInstances: () => void,
removeInstance: (index: number) => void, removeInstance: (index: number) => void,
getContext: () => 'memory' | 'blockchain' getContext: () => 'memory' | 'blockchain',
runTransactions: (
index: 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) => void,
gasEstimationPrompt: (msg: string) => 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
} }
export interface Modal { export interface Modal {
@ -251,5 +267,23 @@ export interface UdappProps {
context: 'memory' | 'blockchain', context: 'memory' | 'blockchain',
abi?: FuncABI[], abi?: FuncABI[],
removeInstance: (index: number) => void, removeInstance: (index: number) => void,
index: number index: number,
gasEstimationPrompt: (msg: string) => 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,
runTransactions: (
index: 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) => void,
decodedResponse: any
} }

Loading…
Cancel
Save