|
|
@ -120,19 +120,16 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address |
|
|
|
contractActionsWrapper.appendChild(this.getCallButton({ |
|
|
|
contractActionsWrapper.appendChild(this.getCallButton({ |
|
|
|
funABI: funABI, |
|
|
|
funABI: funABI, |
|
|
|
address: address, |
|
|
|
address: address, |
|
|
|
contractAbi: contractABI, |
|
|
|
contractABI: contractABI, |
|
|
|
contractName: contractName |
|
|
|
contractName: contractName |
|
|
|
})) |
|
|
|
})) |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
this.calldataInput = yo` |
|
|
|
const calldataInput = yo` |
|
|
|
<input class="m-0" title="Input the amount of Ether to send to receive function."> |
|
|
|
<input class="w-100 m-0" title="The Calldata to send to fallback function of the contract."> |
|
|
|
` |
|
|
|
` |
|
|
|
this.amountInput = yo` |
|
|
|
const llIError = yo` |
|
|
|
<input class="m-0" title="Input calldata to send to fallback function."> |
|
|
|
<label id="deployAndRunLLTxError" class="text-danger"></label> |
|
|
|
` |
|
|
|
|
|
|
|
this.llIError = yo` |
|
|
|
|
|
|
|
<label class="text-danger"></label> |
|
|
|
|
|
|
|
` |
|
|
|
` |
|
|
|
// constract LLInteractions elements
|
|
|
|
// constract LLInteractions elements
|
|
|
|
const lowLevelInteracions = yo` |
|
|
|
const lowLevelInteracions = yo` |
|
|
@ -149,119 +146,71 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address |
|
|
|
class="fas fa-info text-info my-3 mx-1"></i> |
|
|
|
class="fas fa-info text-info my-3 mx-1"></i> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="d-flex flex-column"> |
|
|
|
<div class="d-flex flex-column"> |
|
|
|
<div class="d-flex justify-content-end m-2 align-items-center"> |
|
|
|
|
|
|
|
<label class="mr-2 m-0">Amount</label> |
|
|
|
|
|
|
|
${this.amountInput} |
|
|
|
|
|
|
|
<button class="btn btn-sm btn-secondary" title="Send ether to contract." onclick=${() => sendEther()}>Send</button> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="d-flex justify-content-end m-2 align-items-center"> |
|
|
|
<div class="d-flex justify-content-end m-2 align-items-center"> |
|
|
|
<label class="mr-2 m-0">Calldata</label> |
|
|
|
<label class="mr-2 m-0">Calldata</label> |
|
|
|
${this.calldataInput} |
|
|
|
${calldataInput} |
|
|
|
<button class="btn btn-sm btn-secondary" title="Send data to contract." onclick=${() => sendCalldata()}>Send</button> |
|
|
|
<button id="deployAndRunLLTxSendTransaction" class="btn btn-sm btn-secondary" title="Send data to contract." onclick=${() => sendData()}>Transact</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
<div> |
|
|
|
${this.llIError} |
|
|
|
${llIError} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
` |
|
|
|
` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function sendData () { |
|
|
|
|
|
|
|
let error = false |
|
|
|
function setLLIError (text) { |
|
|
|
function setLLIError (text) { |
|
|
|
self.llIError.innerText = text |
|
|
|
llIError.innerText = text |
|
|
|
|
|
|
|
if (text !== '') error = true |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function sendCalldata () { |
|
|
|
|
|
|
|
setLLIError('') |
|
|
|
setLLIError('') |
|
|
|
const fallback = self.udapp.getFallbackInterface(contractABI) |
|
|
|
const fallback = self.udapp.getFallbackInterface(contractABI) |
|
|
|
|
|
|
|
const receive = self.udapp.getReceiveInterface(contractABI) |
|
|
|
const args = { |
|
|
|
const args = { |
|
|
|
funABI: fallback, |
|
|
|
funABI: fallback, |
|
|
|
address: address, |
|
|
|
address: address, |
|
|
|
contractAbi: contractABI, |
|
|
|
contractName: contractName, |
|
|
|
contractName: contractName |
|
|
|
contractABI: contractABI |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
let calldata = calldataInput.value |
|
|
|
|
|
|
|
const amount = document.querySelector('#value').value |
|
|
|
|
|
|
|
if (amount !== '0') { |
|
|
|
|
|
|
|
// check for numeric and receive/fallback
|
|
|
|
|
|
|
|
if (!isNumeric(amount)) { |
|
|
|
|
|
|
|
setLLIError('Value to send should be a number') |
|
|
|
|
|
|
|
} else if (!receive && !(fallback && fallback.stateMutability === 'payable')) { |
|
|
|
|
|
|
|
setLLIError("In order to receive Ether transfer the contract should have either 'receive' or payable 'fallback' function") |
|
|
|
} |
|
|
|
} |
|
|
|
if (!self.calldataInput.value) { |
|
|
|
|
|
|
|
// show error:
|
|
|
|
|
|
|
|
setLLIError('Calldata field is empty') |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (fallback) { |
|
|
|
|
|
|
|
// fallback is defined. call the fallback function
|
|
|
|
|
|
|
|
self.clickButton(args) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// show error
|
|
|
|
|
|
|
|
setLLIError("'fallback' function is not defined") |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (calldata) { |
|
|
|
|
|
|
|
if (calldata.length > 3 && calldata.substr(0, 2) === '0x') { |
|
|
|
|
|
|
|
if (!isHexadecimal(calldata.substr(2, calldata.length))) { |
|
|
|
|
|
|
|
setLLIError('the calldata should be a valid hexadecimal value.') |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!fallback) { |
|
|
|
function sendEther () { |
|
|
|
setLLIError("'fallback' function is not defined") |
|
|
|
setLLIError('') |
|
|
|
|
|
|
|
const fallback = self.udapp.getFallbackInterface(contractABI) |
|
|
|
|
|
|
|
const receive = self.udapp.getReceiveInterface(contractABI) |
|
|
|
|
|
|
|
const argsR = { |
|
|
|
|
|
|
|
funABI: receive, |
|
|
|
|
|
|
|
address: address, |
|
|
|
|
|
|
|
contractAbi: contractABI, |
|
|
|
|
|
|
|
contractName: contractName |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
const argsF = { |
|
|
|
|
|
|
|
funABI: receive, |
|
|
|
|
|
|
|
address: address, |
|
|
|
|
|
|
|
contractAbi: contractABI, |
|
|
|
|
|
|
|
contractName: contractName |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
if (!self.amountInput.value) { |
|
|
|
if ((calldata || amount !== '0') && !error) self.runTransaction(false, args, null, calldata, null) |
|
|
|
// show error:
|
|
|
|
|
|
|
|
setLLIError('Ether amount field is empty') |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (receive) { |
|
|
|
|
|
|
|
self.clickButton(argsR) |
|
|
|
|
|
|
|
// receive is defined. call the fallback function
|
|
|
|
|
|
|
|
} else if (fallback && fallback.stateMutability === 'payable') { |
|
|
|
|
|
|
|
// receive is not defined but there is payable fallback function, call it
|
|
|
|
|
|
|
|
self.clickButton(argsF) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// show error
|
|
|
|
|
|
|
|
setLLIError("In order to receive Ether transfer the contract should have either 'receive' or payable 'fallback' function") |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function isHexadecimal (value) { |
|
|
|
|
|
|
|
return /^[0-9a-fA-F]+$/.test(value) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function isNumeric (value) { |
|
|
|
|
|
|
|
return /^\+?(0|[1-9]\d*)$/.test(value) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
contractActionsWrapper.appendChild(lowLevelInteracions) |
|
|
|
contractActionsWrapper.appendChild(lowLevelInteracions) |
|
|
|
return instance |
|
|
|
return instance |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO this is used by renderInstance when a new instance is displayed.
|
|
|
|
UniversalDAppUI.prototype.confirmationCb = function (network, tx, gasEstimation, continueTxExecution, cancelCb) { |
|
|
|
// this returns a DOM element.
|
|
|
|
|
|
|
|
UniversalDAppUI.prototype.getCallButton = function (args) { |
|
|
|
|
|
|
|
let self = this |
|
|
|
let self = this |
|
|
|
// args.funABI, args.address [fun only]
|
|
|
|
|
|
|
|
// args.contractName [constr only]
|
|
|
|
|
|
|
|
const lookupOnly = args.funABI.stateMutability === 'view' || args.funABI.stateMutability === 'pure' || !!args.funABI.constant |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var outputOverride = yo`<div class=${css.value}></div>` // show return value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const multiParamManager = new MultiParamManager(lookupOnly, args.funABI, (valArray, inputsValue) => { |
|
|
|
|
|
|
|
this.clickButton(args, valArray, inputsValue) |
|
|
|
|
|
|
|
}, self.udapp.getInputs(args.funABI)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const contractActionsContainer = yo`<div class="${css.contractActionsContainer}" >${multiParamManager.render()}</div>` |
|
|
|
|
|
|
|
contractActionsContainer.appendChild(outputOverride) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return contractActionsContainer |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UniversalDAppUI.prototype.clickButton = function (args, valArr, inputsValue) { |
|
|
|
|
|
|
|
let self = this |
|
|
|
|
|
|
|
// check if it's a special function and add a name in case it is
|
|
|
|
|
|
|
|
const fuctionName = args.contractName + |
|
|
|
|
|
|
|
(args.funABI.name ? args.funABI.name : args.funABI.type === 'receive' ? '(receive)' : '(fallback)') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const lookupOnly = args.funABI.stateMutability === 'view' || args.funABI.stateMutability === 'pure' || !!args.funABI.constant |
|
|
|
|
|
|
|
const logMsg = lookupOnly ? `transact to ${fuctionName}` : `call to ${fuctionName}` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var value = inputsValue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const confirmationCb = (network, tx, gasEstimation, continueTxExecution, cancelCb) => { |
|
|
|
|
|
|
|
if (network.name !== 'Main') { |
|
|
|
if (network.name !== 'Main') { |
|
|
|
return continueTxExecution(null) |
|
|
|
return continueTxExecution(null) |
|
|
|
} |
|
|
|
} |
|
|
@ -312,16 +261,18 @@ UniversalDAppUI.prototype.clickButton = function (args, valArr, inputsValue) { |
|
|
|
var gasPrice = Web3.utils.toWei(content.querySelector('#gasprice').value, 'gwei') |
|
|
|
var gasPrice = Web3.utils.toWei(content.querySelector('#gasprice').value, 'gwei') |
|
|
|
continueTxExecution(gasPrice) |
|
|
|
continueTxExecution(gasPrice) |
|
|
|
} |
|
|
|
} |
|
|
|
}}, { |
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
label: 'Cancel', |
|
|
|
label: 'Cancel', |
|
|
|
fn: () => { |
|
|
|
fn: () => { |
|
|
|
return cancelCb('Transaction canceled by user.') |
|
|
|
return cancelCb('Transaction canceled by user.') |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const continueCb = (error, continueTxExecution, cancelCb) => { |
|
|
|
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 |
|
|
|
modalDialog( |
|
|
|
modalDialog( |
|
|
@ -342,36 +293,58 @@ UniversalDAppUI.prototype.clickButton = function (args, valArr, inputsValue) { |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
continueTxExecution() |
|
|
|
continueTxExecution() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const promptCb = (okCb, cancelCb) => { |
|
|
|
|
|
|
|
modalCustom.promptPassphrase('Passphrase requested', 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO this is used by renderInstance when a new instance is displayed.
|
|
|
|
|
|
|
|
// this returns a DOM element.
|
|
|
|
|
|
|
|
UniversalDAppUI.prototype.getCallButton = function (args) { |
|
|
|
|
|
|
|
let self = this |
|
|
|
|
|
|
|
var outputOverride = yo`<div class=${css.value}></div>` // show return value
|
|
|
|
|
|
|
|
const lookupOnly = args.funABI.stateMutability === 'view' || args.funABI.stateMutability === 'pure' || args.funABI.constant |
|
|
|
|
|
|
|
const multiParamManager = new MultiParamManager( |
|
|
|
|
|
|
|
lookupOnly, |
|
|
|
|
|
|
|
args.funABI, |
|
|
|
|
|
|
|
(valArray, inputsValues) => self.runTransaction(lookupOnly, args, valArray, inputsValues, outputOverride), |
|
|
|
|
|
|
|
self.udapp.getInputs(args.funABI) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const contractActionsContainer = yo`<div class="${css.contractActionsContainer}" >${multiParamManager.render()}</div>` |
|
|
|
|
|
|
|
contractActionsContainer.appendChild(outputOverride) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return contractActionsContainer |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UniversalDAppUI.prototype.runTransaction = function (lookupOnly, args, valArr, inputsValues, outputOverride) { |
|
|
|
|
|
|
|
let self = this |
|
|
|
|
|
|
|
let logMsg |
|
|
|
|
|
|
|
if (!lookupOnly) { |
|
|
|
|
|
|
|
logMsg = `call to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'}` |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
logMsg = `transact to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'}` |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var value = inputsValues |
|
|
|
|
|
|
|
|
|
|
|
const outputCb = (decoded) => { |
|
|
|
const outputCb = (decoded) => { |
|
|
|
|
|
|
|
if (outputOverride) { |
|
|
|
outputOverride.innerHTML = '' |
|
|
|
outputOverride.innerHTML = '' |
|
|
|
outputOverride.appendChild(decoded) |
|
|
|
outputOverride.appendChild(decoded) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const promptCb = (okCb, cancelCb) => { |
|
|
|
|
|
|
|
modalCustom.promptPassphrase('Passphrase requested', 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const isSpecialFunction = args.funABI.type === 'fallback' || args.funABI.type === 'receive' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// contractsDetails is used to resolve libraries
|
|
|
|
// contractsDetails is used to resolve libraries
|
|
|
|
txFormat.buildData( |
|
|
|
txFormat.buildData(args.contractName, args.contractABI, {}, false, args.funABI, args.funABI.type !== 'fallback' ? value : '', (error, data) => { |
|
|
|
args.contractName, |
|
|
|
|
|
|
|
args.contractAbi, |
|
|
|
|
|
|
|
{}, |
|
|
|
|
|
|
|
false, |
|
|
|
|
|
|
|
args.funABI, |
|
|
|
|
|
|
|
!isSpecialFunction ? value : '', // input parameters for the function to call
|
|
|
|
|
|
|
|
(error, data) => { |
|
|
|
|
|
|
|
if (!error) { |
|
|
|
if (!error) { |
|
|
|
if (!lookupOnly) { |
|
|
|
if (!lookupOnly) { |
|
|
|
self.logCallback(`${logMsg} pending ... `) |
|
|
|
self.logCallback(`${logMsg} pending ... `) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
self.logCallback(`${logMsg}`) |
|
|
|
self.logCallback(`${logMsg}`) |
|
|
|
} |
|
|
|
} |
|
|
|
if (isSpecialFunction) data.dataHex = value |
|
|
|
if (args.funABI.type === 'fallback') data.dataHex = value |
|
|
|
self.udapp.callFunction(args.address, data, args.funABI, confirmationCb, continueCb, promptCb, (error, txResult) => { |
|
|
|
self.udapp.callFunction(args.address, data, args.funABI, this.confirmationCb, continueCb, promptCb, (error, txResult) => { |
|
|
|
if (!error) { |
|
|
|
if (!error) { |
|
|
|
var isVM = self.executionContext.isVM() |
|
|
|
var isVM = self.executionContext.isVM() |
|
|
|
if (isVM) { |
|
|
|
if (isVM) { |
|
|
@ -396,9 +369,8 @@ UniversalDAppUI.prototype.clickButton = function (args, valArr, inputsValue) { |
|
|
|
self.logCallback(msg) |
|
|
|
self.logCallback(msg) |
|
|
|
}, (data, runTxCallback) => { |
|
|
|
}, (data, runTxCallback) => { |
|
|
|
// called for libraries deployment
|
|
|
|
// called for libraries deployment
|
|
|
|
self.udapp.runTx(data, confirmationCb, runTxCallback) |
|
|
|
self.udapp.runTx(data, this.confirmationCb, runTxCallback) |
|
|
|
} |
|
|
|
}) |
|
|
|
) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
module.exports = UniversalDAppUI |
|
|
|
module.exports = UniversalDAppUI |
|
|
|