|
|
@ -112,17 +112,6 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address |
|
|
|
instance.appendChild(title) |
|
|
|
instance.appendChild(title) |
|
|
|
instance.appendChild(contractActionsWrapper) |
|
|
|
instance.appendChild(contractActionsWrapper) |
|
|
|
|
|
|
|
|
|
|
|
// Add the fallback function
|
|
|
|
|
|
|
|
var fallback = self.udapp.getFallbackInterface(contractABI) |
|
|
|
|
|
|
|
if (fallback) { |
|
|
|
|
|
|
|
contractActionsWrapper.appendChild(this.getCallButton({ |
|
|
|
|
|
|
|
funABI: fallback, |
|
|
|
|
|
|
|
address: address, |
|
|
|
|
|
|
|
contractAbi: contractABI, |
|
|
|
|
|
|
|
contractName: contractName |
|
|
|
|
|
|
|
})) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$.each(contractABI, (i, funABI) => { |
|
|
|
$.each(contractABI, (i, funABI) => { |
|
|
|
if (funABI.type !== 'function') { |
|
|
|
if (funABI.type !== 'function') { |
|
|
|
return |
|
|
|
return |
|
|
@ -136,6 +125,108 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address |
|
|
|
})) |
|
|
|
})) |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.calldataInput = yo` |
|
|
|
|
|
|
|
<input class="m-0" title="Input the amount of Ether to send to receive function."> |
|
|
|
|
|
|
|
` |
|
|
|
|
|
|
|
this.amountInput = yo` |
|
|
|
|
|
|
|
<input class="m-0" title="Input calldata to send to fallback function."> |
|
|
|
|
|
|
|
` |
|
|
|
|
|
|
|
this.llIError = yo` |
|
|
|
|
|
|
|
<label class="text-danger"></label> |
|
|
|
|
|
|
|
` |
|
|
|
|
|
|
|
// constract LLInteractions elements
|
|
|
|
|
|
|
|
const lowLevelInteracions = yo` |
|
|
|
|
|
|
|
<div class="d-flex flex-column"> |
|
|
|
|
|
|
|
<div class="d-flex flex-row justify-content-between mt-2"> |
|
|
|
|
|
|
|
<label class="pt-2 border-top d-flex justify-content-start flex-grow-1"> |
|
|
|
|
|
|
|
Low level interactions with contract |
|
|
|
|
|
|
|
</label> |
|
|
|
|
|
|
|
<i aria-hidden="true" |
|
|
|
|
|
|
|
title="A contract can have at most one receive function, declared using receive() external payable { ... } and one fallback function, declared using fallback () external [payable]. |
|
|
|
|
|
|
|
These functions cannot have arguments, cannot return anything. Receive is executed on a call to the contract with empty calldata on plain Ether transfers (e.g. via .send() or .transfer()). |
|
|
|
|
|
|
|
If no such function exists, but a payable fallback function exists, the fallback function will be called on a plain Ether transfer. If neither a receive Ether nor a payable fallback function is present, the contract cannot receive Ether through regular transactions and throws an exception.
|
|
|
|
|
|
|
|
Fallback is executed on a call to the contract if none of the other functions match the given function signature." |
|
|
|
|
|
|
|
class="fas fa-info text-info my-3 mx-1"></i> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<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"> |
|
|
|
|
|
|
|
<label class="mr-2 m-0">Calldata</label> |
|
|
|
|
|
|
|
${this.calldataInput} |
|
|
|
|
|
|
|
<button class="btn btn-sm btn-secondary" title="Send data to contract." onclick=${() => sendCalldata()}>Send</button> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<div> |
|
|
|
|
|
|
|
${this.llIError} |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function setLLIError (text) { |
|
|
|
|
|
|
|
self.llIError.innerText = text |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function sendCalldata () { |
|
|
|
|
|
|
|
setLLIError('') |
|
|
|
|
|
|
|
const fallback = self.udapp.getFallbackInterface(contractABI) |
|
|
|
|
|
|
|
const args = { |
|
|
|
|
|
|
|
funABI: fallback, |
|
|
|
|
|
|
|
address: address, |
|
|
|
|
|
|
|
contractAbi: contractABI, |
|
|
|
|
|
|
|
contractName: contractName |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
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") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function sendEther () { |
|
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
|
// 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") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
contractActionsWrapper.appendChild(lowLevelInteracions) |
|
|
|
return instance |
|
|
|
return instance |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -145,19 +236,30 @@ UniversalDAppUI.prototype.getCallButton = function (args) { |
|
|
|
let self = this |
|
|
|
let self = this |
|
|
|
// args.funABI, args.address [fun only]
|
|
|
|
// args.funABI, args.address [fun only]
|
|
|
|
// args.contractName [constr only]
|
|
|
|
// args.contractName [constr only]
|
|
|
|
const lookupOnly = args.funABI.stateMutability === 'view' || args.funABI.stateMutability === 'pure' || args.funABI.constant |
|
|
|
const lookupOnly = args.funABI.stateMutability === 'view' || args.funABI.stateMutability === 'pure' || !!args.funABI.constant |
|
|
|
|
|
|
|
|
|
|
|
var outputOverride = yo`<div class=${css.value}></div>` // show return value
|
|
|
|
var outputOverride = yo`<div class=${css.value}></div>` // show return value
|
|
|
|
|
|
|
|
|
|
|
|
function clickButton (valArr, inputsValues) { |
|
|
|
const multiParamManager = new MultiParamManager(lookupOnly, args.funABI, (valArray, inputsValue) => { |
|
|
|
let logMsg |
|
|
|
this.clickButton(args, valArray, inputsValue) |
|
|
|
if (!lookupOnly) { |
|
|
|
}, self.udapp.getInputs(args.funABI)) |
|
|
|
logMsg = `call to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'}` |
|
|
|
|
|
|
|
} else { |
|
|
|
const contractActionsContainer = yo`<div class="${css.contractActionsContainer}" >${multiParamManager.render()}</div>` |
|
|
|
logMsg = `transact to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'}` |
|
|
|
contractActionsContainer.appendChild(outputOverride) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return contractActionsContainer |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var value = inputsValues |
|
|
|
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) => { |
|
|
|
const confirmationCb = (network, tx, gasEstimation, continueTxExecution, cancelCb) => { |
|
|
|
if (network.name !== 'Main') { |
|
|
|
if (network.name !== 'Main') { |
|
|
@ -251,15 +353,24 @@ UniversalDAppUI.prototype.getCallButton = function (args) { |
|
|
|
modalCustom.promptPassphrase('Passphrase requested', 'Personal mode is enabled. Please provide passphrase of account', '', 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(args.contractName, args.contractAbi, {}, false, args.funABI, args.funABI.type !== 'fallback' ? value : '', (error, data) => { |
|
|
|
txFormat.buildData( |
|
|
|
|
|
|
|
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 (args.funABI.type === 'fallback') data.dataHex = value |
|
|
|
if (isSpecialFunction) data.dataHex = value |
|
|
|
self.udapp.callFunction(args.address, data, args.funABI, confirmationCb, continueCb, promptCb, (error, txResult) => { |
|
|
|
self.udapp.callFunction(args.address, data, args.funABI, confirmationCb, continueCb, promptCb, (error, txResult) => { |
|
|
|
if (!error) { |
|
|
|
if (!error) { |
|
|
|
var isVM = self.executionContext.isVM() |
|
|
|
var isVM = self.executionContext.isVM() |
|
|
@ -286,17 +397,8 @@ UniversalDAppUI.prototype.getCallButton = function (args) { |
|
|
|
}, (data, runTxCallback) => { |
|
|
|
}, (data, runTxCallback) => { |
|
|
|
// called for libraries deployment
|
|
|
|
// called for libraries deployment
|
|
|
|
self.udapp.runTx(data, confirmationCb, runTxCallback) |
|
|
|
self.udapp.runTx(data, confirmationCb, runTxCallback) |
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
) |
|
|
|
const multiParamManager = new MultiParamManager(lookupOnly, args.funABI, (valArray, inputsValues, domEl) => { |
|
|
|
|
|
|
|
clickButton(valArray, inputsValues, domEl) |
|
|
|
|
|
|
|
}, self.udapp.getInputs(args.funABI)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const contractActionsContainer = yo`<div class="${css.contractActionsContainer}" >${multiParamManager.render()}</div>` |
|
|
|
|
|
|
|
contractActionsContainer.appendChild(outputOverride) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return contractActionsContainer |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
module.exports = UniversalDAppUI |
|
|
|
module.exports = UniversalDAppUI |
|
|
|