convert universal dapp ui to a class and update syntax

pull/1/head
Iuri Matias 5 years ago
parent c11bb34c35
commit 433cedb2d8
  1. 336
      src/app/ui/universal-dapp-ui.js

@ -1,33 +1,27 @@
/* global */ /* global */
'use strict' 'use strict'
var $ = require('jquery') const $ = require('jquery')
var yo = require('yo-yo') const yo = require('yo-yo')
var ethJSUtil = require('ethereumjs-util') const ethJSUtil = require('ethereumjs-util')
var BN = ethJSUtil.BN const BN = ethJSUtil.BN
var helper = require('../../lib/helper') const helper = require('../../lib/helper')
var copyToClipboard = require('./copy-to-clipboard') const copyToClipboard = require('./copy-to-clipboard')
var css = require('../../universal-dapp-styles') const css = require('../../universal-dapp-styles')
var MultiParamManager = require('./multiParamManager') const MultiParamManager = require('./multiParamManager')
var remixLib = require('remix-lib') const remixLib = require('remix-lib')
var txFormat = remixLib.execution.txFormat const txFormat = remixLib.execution.txFormat
var txHelper = remixLib.execution.txHelper const txHelper = remixLib.execution.txHelper
var confirmDialog = require('./confirmDialog') const confirmDialog = require('./confirmDialog')
var modalCustom = require('./modal-dialog-custom') const modalCustom = require('./modal-dialog-custom')
var modalDialog = require('./modaldialog') const modalDialog = require('./modaldialog')
var TreeView = require('./TreeView') const TreeView = require('./TreeView')
function UniversalDAppUI (blockchain, logCallback) {
this.blockchain = blockchain
this.logCallback = logCallback
this.compilerData = {contractsDetails: {}}
}
function decodeResponseToTreeView (response, fnabi) { function decodeResponseToTreeView (response, fnabi) {
var treeView = new TreeView({ const treeView = new TreeView({
extractData: (item, parent, key) => { extractData: (item, parent, key) => {
var ret = {} let ret = {}
if (BN.isBN(item)) { if (BN.isBN(item)) {
ret.self = item.toString(10) ret.self = item.toString(10)
ret.children = [] ret.children = []
@ -40,27 +34,42 @@ function decodeResponseToTreeView (response, fnabi) {
return treeView.render(txFormat.decodeResponse(response, fnabi)) return treeView.render(txFormat.decodeResponse(response, fnabi))
} }
UniversalDAppUI.prototype.renderInstance = function (contract, address, contractName) { class UniversalDAppUI {
var noInstances = document.querySelector('[class^="noInstancesText"]')
if (noInstances) { constructor (blockchain, logCallback) {
noInstances.parentNode.removeChild(noInstances) this.blockchain = blockchain
this.logCallback = logCallback
this.compilerData = { contractsDetails: {} }
}
renderInstance (contract, address, contractName) {
const noInstances = document.querySelector('[class^="noInstancesText"]')
if (noInstances) {
noInstances.parentNode.removeChild(noInstances)
}
const abi = txHelper.sortAbiFunction(contract.abi)
return this.renderInstanceFromABI(abi, address, contractName)
} }
const abi = txHelper.sortAbiFunction(contract.abi)
return this.renderInstanceFromABI(abi, address, contractName)
}
// TODO this function was named before "appendChild". // TODO this function was named before "appendChild".
// this will render an instance: contract name, contract address, and all the public functions // this will render an instance: contract name, contract address, and all the public functions
// basically this has to be called for the "atAddress" (line 393) and when a contract creation succeed // basically this has to be called for the "atAddress" (line 393) and when a contract creation succeed
// this returns a DOM element // this returns a DOM element
UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address, contractName) { renderInstanceFromABI (contractABI, address, contractName) {
address = (address.slice(0, 2) === '0x' ? '' : '0x') + address.toString('hex') address = (address.slice(0, 2) === '0x' ? '' : '0x') + address.toString('hex')
address = ethJSUtil.toChecksumAddress(address) address = ethJSUtil.toChecksumAddress(address)
var instance = yo`<div class="instance ${css.instance} ${css.hidesub}" id="instance${address}"></div>` const instance = yo`<div class="instance ${css.instance} ${css.hidesub}" id="instance${address}"></div>`
const context = this.blockchain.context() const context = this.blockchain.context()
var shortAddress = helper.shortenAddress(address) function toggleClass (e) {
var title = yo` $(instance).toggleClass(`${css.hidesub}`)
// e.currentTarget.querySelector('i')
e.currentTarget.querySelector('i').classList.toggle(`fa-angle-right`)
e.currentTarget.querySelector('i').classList.toggle(`fa-angle-down`)
}
const shortAddress = helper.shortenAddress(address)
const title = yo`
<div class="${css.title} alert alert-secondary p-2"> <div class="${css.title} alert alert-secondary p-2">
<button class="btn ${css.titleExpander}" onclick="${(e) => { toggleClass(e) }}"> <button class="btn ${css.titleExpander}" onclick="${(e) => { toggleClass(e) }}">
<i class="fas fa-angle-right" aria-hidden="true"></i> <i class="fas fa-angle-right" aria-hidden="true"></i>
@ -78,166 +87,155 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address
</div> </div>
` `
var close = yo` const close = yo`
<button <button
class="${css.udappClose} p-1 btn btn-secondary" class="${css.udappClose} p-1 btn btn-secondary"
onclick=${remove} onclick=${() => { instance.remove() }}
title="Remove from the list" title="Remove from the list"
> >
<i class="${css.closeIcon} fas fa-times" aria-hidden="true"></i> <i class="${css.closeIcon} fas fa-times" aria-hidden="true"></i>
</button>` </button>`
title.querySelector('.btn-group').appendChild(close) title.querySelector('.btn-group').appendChild(close)
var contractActionsWrapper = yo` const contractActionsWrapper = yo`
<div class="${css.cActionsWrapper}"> <div class="${css.cActionsWrapper}">
</div> </div>
` `
function remove () { instance.appendChild(title)
instance.remove() instance.appendChild(contractActionsWrapper)
// @TODO perhaps add a callack here to warn the caller that the instance has been removed
}
function toggleClass (e) {
$(instance).toggleClass(`${css.hidesub}`)
// e.currentTarget.querySelector('i')
e.currentTarget.querySelector('i').classList.toggle(`fa-angle-right`)
e.currentTarget.querySelector('i').classList.toggle(`fa-angle-down`)
}
instance.appendChild(title) // Add the fallback function
instance.appendChild(contractActionsWrapper) const fallback = txHelper.getFallbackInterface(contractABI)
// Add the fallback function if (fallback) {
const fallback = txHelper.getFallbackInterface(contractABI) contractActionsWrapper.appendChild(this.getCallButton({
funABI: fallback,
if (fallback) { address: address,
contractActionsWrapper.appendChild(this.getCallButton({ contractAbi: contractABI,
funABI: fallback, contractName: contractName
address: address, }))
contractAbi: contractABI,
contractName: contractName
}))
}
$.each(contractABI, (i, funABI) => {
if (funABI.type !== 'function') {
return
} }
// @todo getData cannot be used with overloaded functions
contractActionsWrapper.appendChild(this.getCallButton({
funABI: funABI,
address: address,
contractAbi: contractABI,
contractName: contractName
}))
})
return instance $.each(contractABI, (i, funABI) => {
} if (funABI.type !== 'function') {
return
}
// @todo getData cannot be used with overloaded functions
contractActionsWrapper.appendChild(this.getCallButton({
funABI: funABI,
address: address,
contractAbi: contractABI,
contractName: contractName
}))
})
return instance
}
UniversalDAppUI.prototype.getConfirmationCb = function (modalDialog, confirmDialog) { getConfirmationCb (modalDialog, confirmDialog) {
const confirmationCb = (network, tx, gasEstimation, continueTxExecution, cancelCb) => { const confirmationCb = (network, tx, gasEstimation, continueTxExecution, cancelCb) => {
if (network.name !== 'Main') { if (network.name !== 'Main') {
return continueTxExecution(null) return continueTxExecution(null)
} }
const amount = this.blockchain.fromWei(tx.value, true, 'ether') const amount = this.blockchain.fromWei(tx.value, true, 'ether')
const content = confirmDialog(tx, amount, gasEstimation, null, this.blockchain.determineGasFees(tx), this.blockchain.determineGasPrice) const content = confirmDialog(tx, amount, gasEstimation, null, this.blockchain.determineGasFees(tx), this.blockchain.determineGasPrice)
modalDialog('Confirm transaction', content, modalDialog('Confirm transaction', content,
{ {
label: 'Confirm', label: 'Confirm',
fn: () => { fn: () => {
this.config.setUnpersistedProperty('doNotShowTransactionConfirmationAgain', content.querySelector('input#confirmsetting').checked) this.config.setUnpersistedProperty('doNotShowTransactionConfirmationAgain', content.querySelector('input#confirmsetting').checked)
// TODO: check if this is check is still valid given the refactor // TODO: check if this is check is still valid given the refactor
if (!content.gasPriceStatus) { if (!content.gasPriceStatus) {
cancelCb('Given gas price is not correct') cancelCb('Given gas price is not correct')
} else { } else {
var gasPrice = this.blockchain.toWei(content.querySelector('#gasprice').value, 'gwei') const gasPrice = this.blockchain.toWei(content.querySelector('#gasprice').value, 'gwei')
continueTxExecution(gasPrice) continueTxExecution(gasPrice)
}
}
}, {
label: 'Cancel',
fn: () => {
return cancelCb('Transaction canceled by user.')
} }
} }
}, { )
label: 'Cancel', }
fn: () => {
return cancelCb('Transaction canceled by user.') return confirmationCb
}
}
)
} }
return confirmationCb // TODO this is used by renderInstance when a new instance is displayed.
} // this returns a DOM element.
getCallButton (args) {
// args.funABI, args.address [fun only]
// args.contractName [constr only]
const lookupOnly = args.funABI.stateMutability === 'view' || args.funABI.stateMutability === 'pure' || args.funABI.constant
// TODO this is used by renderInstance when a new instance is displayed. const outputOverride = yo`<div class=${css.value}></div>` // show return value
// this returns a DOM element.
UniversalDAppUI.prototype.getCallButton = function (args) {
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
function clickButton (valArr, inputsValues) {
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)'}`
}
const confirmationCb = self.getConfirmationCb(modalDialog, confirmDialog) const clickButton = (valArr, inputsValues) => {
const continueCb = (error, continueTxExecution, cancelCb) => { let logMsg
if (error) { if (!lookupOnly) {
const msg = typeof error !== 'string' ? error.message : error logMsg = `call to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'}`
modalDialog( } else {
'Gas estimation failed', logMsg = `transact to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'}`
yo` }
const confirmationCb = this.getConfirmationCb(modalDialog, confirmDialog)
const continueCb = (error, continueTxExecution, cancelCb) => {
if (error) {
const msg = typeof error !== 'string' ? error.message : error
modalDialog(
'Gas estimation failed',
yo`
<div>Gas estimation errored with the following message (see below). <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> The transaction execution will likely fail. Do you want to force sending? <br>${msg}</div>
`, `,
{ {
label: 'Send Transaction', label: 'Send Transaction',
fn: () => continueTxExecution() fn: () => continueTxExecution()
}, },
{ {
label: 'Cancel Transaction', label: 'Cancel Transaction',
fn: () => cancelCb() fn: () => cancelCb()
} }
) )
} else { } else {
continueTxExecution() continueTxExecution()
}
} }
}
const outputCb = (returnValue) => { const outputCb = (returnValue) => {
const decoded = decodeResponseToTreeView(returnValue, args.funABI) const decoded = decodeResponseToTreeView(returnValue, args.funABI)
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 promptCb = (okCb, cancelCb) => { const callType = args.funABI.type !== 'fallback' ? inputsValues : ''
modalCustom.promptPassphrase('Passphrase requested', 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb) this.blockchain.runOrCallContractMethod(args.contractName, args.contractAbi, args.funABI, inputsValues, args.address, callType, lookupOnly, logMsg, this.logCallback, outputCb, confirmationCb, continueCb, promptCb)
} }
const callType = args.funABI.type !== 'fallback' ? inputsValues : '' let inputs = ''
self.blockchain.runOrCallContractMethod(args.contractName, args.contractAbi, args.funABI, inputsValues, args.address, callType, lookupOnly, logMsg, self.logCallback, outputCb, confirmationCb, continueCb, promptCb) if (args.funABI.inputs) {
} inputs = txHelper.inputParametersDeclarationToString(args.funABI.inputs)
}
let inputs = '' const multiParamManager = new MultiParamManager(lookupOnly, args.funABI, (valArray, inputsValues, domEl) => {
if (args.funABI.inputs) { clickButton(valArray, inputsValues, domEl)
inputs = txHelper.inputParametersDeclarationToString(args.funABI.inputs) }, inputs)
}
const multiParamManager = new MultiParamManager(lookupOnly, args.funABI, (valArray, inputsValues, domEl) => { const contractActionsContainer = yo`<div class="${css.contractActionsContainer}" >${multiParamManager.render()}</div>`
clickButton(valArray, inputsValues, domEl) contractActionsContainer.appendChild(outputOverride)
}, inputs)
const contractActionsContainer = yo`<div class="${css.contractActionsContainer}" >${multiParamManager.render()}</div>` return contractActionsContainer
contractActionsContainer.appendChild(outputOverride) }
return contractActionsContainer
} }
module.exports = UniversalDAppUI module.exports = UniversalDAppUI

Loading…
Cancel
Save