Browse Source

Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop

cl-refactor
Gav Wood 9 years ago
parent
commit
24a334719e
  1. 39
      mix/CodeModel.cpp
  2. 19
      mix/CodeModel.h
  3. 16
      mix/qml/Block.qml
  4. 1
      mix/qml/Ether.qml
  5. 24
      mix/qml/QAddressView.qml
  6. 21
      mix/qml/QBoolTypeView.qml
  7. 7
      mix/qml/QHashTypeView.qml
  8. 17
      mix/qml/QIntTypeView.qml
  9. 12
      mix/qml/QStringTypeView.qml
  10. 50
      mix/qml/StructView.qml
  11. 544
      mix/qml/TransactionDialog.qml
  12. 6
      mix/qml/js/NetworkDeployment.js
  13. 4
      mix/qml/js/TransactionHelper.js

39
mix/CodeModel.cpp

@ -392,6 +392,7 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs)
} }
eth::AssemblyItems const& runtimeAssembly = *_cs.getRuntimeAssemblyItems(n); eth::AssemblyItems const& runtimeAssembly = *_cs.getRuntimeAssemblyItems(n);
QString contractName = QString::fromStdString(contractDefinition.getName());
// Functional gas costs (per function, but also for accessors) // Functional gas costs (per function, but also for accessors)
for (auto it: contractDefinition.getInterfaceFunctions()) for (auto it: contractDefinition.getInterfaceFunctions())
{ {
@ -399,13 +400,15 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs)
continue; continue;
SourceLocation loc = it.second->getDeclaration().getLocation(); SourceLocation loc = it.second->getDeclaration().getLocation();
GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(runtimeAssembly, it.second->externalSignature()); GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(runtimeAssembly, it.second->externalSignature());
m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function); m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function,
contractName, QString::fromStdString(it.second->getDeclaration().getName()));
} }
if (auto const* fallback = contractDefinition.getFallbackFunction()) if (auto const* fallback = contractDefinition.getFallbackFunction())
{ {
SourceLocation loc = fallback->getLocation(); SourceLocation loc = fallback->getLocation();
GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(runtimeAssembly, "INVALID"); GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(runtimeAssembly, "INVALID");
m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function); m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function,
contractName, "fallback");
} }
for (auto const& it: contractDefinition.getDefinedFunctions()) for (auto const& it: contractDefinition.getDefinedFunctions())
{ {
@ -416,13 +419,15 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs)
GasEstimator::GasConsumption cost = GasEstimator::GasConsumption::infinite(); GasEstimator::GasConsumption cost = GasEstimator::GasConsumption::infinite();
if (entry > 0) if (entry > 0)
cost = GasEstimator::functionalEstimation(runtimeAssembly, entry, *it); cost = GasEstimator::functionalEstimation(runtimeAssembly, entry, *it);
m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function); m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function,
contractName, QString::fromStdString(it->getName()));
} }
if (auto const* constructor = contractDefinition.getConstructor()) if (auto const* constructor = contractDefinition.getConstructor())
{ {
SourceLocation loc = constructor->getLocation(); SourceLocation loc = constructor->getLocation();
GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(*_cs.getAssemblyItems(n)); GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(*_cs.getAssemblyItems(n));
m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Constructor); m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Constructor,
contractName, contractName);
} }
} }
} }
@ -435,6 +440,14 @@ QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const
return QVariantList(); return QVariantList();
} }
QVariantList CodeModel::gasCostBy(QString const& _contractName, QString const& _functionName) const
{
if (m_gasCostsMaps)
return m_gasCostsMaps->gasCostsBy(_contractName, _functionName);
else
return QVariantList();
}
void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector<std::string> const& _sourceNames) void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector<std::string> const& _sourceNames)
{ {
Guard pl(x_pendingContracts); Guard pl(x_pendingContracts);
@ -643,9 +656,9 @@ void CodeModel::setOptimizeCode(bool _value)
emit scheduleCompilationJob(++m_backgroundJobId); emit scheduleCompilationJob(++m_backgroundJobId);
} }
void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type) void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type, QString _contractName, QString _functionName)
{ {
GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, _type, this); GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, _type, _contractName, _functionName, this);
m_gasMaps.find(_source).value().push_back(QVariant::fromValue(gas)); m_gasMaps.find(_source).value().push_back(QVariant::fromValue(gas));
} }
@ -668,3 +681,17 @@ QVariantList GasMapWrapper::gasCostsByDocId(QString _source)
return QVariantList(); return QVariantList();
} }
QVariantList GasMapWrapper::gasCostsBy(QString _contractName, QString _functionName)
{
QVariantList gasMap;
for (auto const& map: m_gasMaps)
{
for (auto const& gas: map)
{
if (gas.value<GasMap*>()->contractName() == _contractName && (_functionName.isEmpty() || gas.value<GasMap*>()->functionName() == _functionName))
gasMap.push_back(gas);
}
}
return gasMap;
}

19
mix/CodeModel.h

@ -31,6 +31,7 @@
#include <QMetaEnum> #include <QMetaEnum>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libevmcore/Params.h>
#include <libevmasm/Assembly.h> #include <libevmasm/Assembly.h>
#include "SolidityType.h" #include "SolidityType.h"
#include "QBigInt.h" #include "QBigInt.h"
@ -140,6 +141,8 @@ class GasMap: public QObject
Q_PROPERTY(QString gas MEMBER m_gas CONSTANT) Q_PROPERTY(QString gas MEMBER m_gas CONSTANT)
Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT) Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT)
Q_PROPERTY(QString codeBlockType READ codeBlockType CONSTANT) Q_PROPERTY(QString codeBlockType READ codeBlockType CONSTANT)
Q_PROPERTY(QString contractName MEMBER m_contractName CONSTANT)
Q_PROPERTY(QString functionName MEMBER m_functionName CONSTANT)
public: public:
@ -150,13 +153,19 @@ public:
Constructor Constructor
}; };
GasMap(int _start, int _end, QString _gas, bool _isInfinite, type _type, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite), m_type(_type) {} GasMap(int _start, int _end, QString _gas, bool _isInfinite, type _type, QString _contractName, QString _functionName, QObject* _parent): QObject(_parent),
m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite), m_type(_type), m_contractName(_contractName), m_functionName(_functionName) {}
QString contractName() { return m_contractName; }
QString functionName() { return m_functionName; }
private:
int m_start; int m_start;
int m_end; int m_end;
QString m_gas; QString m_gas;
bool m_isInfinite; bool m_isInfinite;
type m_type; type m_type;
QString m_contractName;
QString m_functionName;
QString codeBlockType() const QString codeBlockType() const
{ {
@ -178,10 +187,11 @@ class GasMapWrapper: public QObject
public: public:
GasMapWrapper(QObject* _parent = nullptr): QObject(_parent){} GasMapWrapper(QObject* _parent = nullptr): QObject(_parent){}
void push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type); void push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type, QString _contractName = "", QString _functionName = "");
bool contains(QString _key); bool contains(QString _key);
void insert(QString _source, QVariantList _variantList); void insert(QString _source, QVariantList _variantList);
QVariantList gasCostsByDocId(QString _source); QVariantList gasCostsByDocId(QString _source);
QVariantList gasCostsBy(QString _contractName, QString _functionName = "");
private: private:
GasCostsMaps m_gasMaps; GasCostsMaps m_gasMaps;
@ -200,6 +210,8 @@ public:
Q_PROPERTY(bool compiling READ isCompiling NOTIFY stateChanged) Q_PROPERTY(bool compiling READ isCompiling NOTIFY stateChanged)
Q_PROPERTY(bool hasContract READ hasContract NOTIFY codeChanged) Q_PROPERTY(bool hasContract READ hasContract NOTIFY codeChanged)
Q_PROPERTY(bool optimizeCode MEMBER m_optimizeCode WRITE setOptimizeCode) Q_PROPERTY(bool optimizeCode MEMBER m_optimizeCode WRITE setOptimizeCode)
Q_PROPERTY(int callStipend READ callStipend)
Q_PROPERTY(int txGas READ txGas)
/// @returns latest compilation results for contracts /// @returns latest compilation results for contracts
QVariantMap contracts() const; QVariantMap contracts() const;
@ -234,7 +246,10 @@ public:
void gasEstimation(solidity::CompilerStack const& _cs); void gasEstimation(solidity::CompilerStack const& _cs);
/// Gas cost by doc id /// Gas cost by doc id
Q_INVOKABLE QVariantList gasCostByDocumentId(QString const& _documentId) const; Q_INVOKABLE QVariantList gasCostByDocumentId(QString const& _documentId) const;
Q_INVOKABLE QVariantList gasCostBy(QString const& _contractName, QString const& _functionName) const;
Q_INVOKABLE void setOptimizeCode(bool _value); Q_INVOKABLE void setOptimizeCode(bool _value);
int txGas() { return static_cast<int>(dev::eth::c_txGas); }
int callStipend() { return static_cast<int>(dev::eth::c_callStipend); }
signals: signals:
/// Emited on compilation state change /// Emited on compilation state change

16
mix/qml/Block.qml

@ -243,7 +243,6 @@ ColumnLayout
} }
} }
Rectangle Rectangle
{ {
Layout.preferredWidth: toWidth Layout.preferredWidth: toWidth
@ -266,8 +265,6 @@ ColumnLayout
} }
} }
function userFrienldyToken(value) function userFrienldyToken(value)
{ {
if (value && value.indexOf("<") === 0) if (value && value.indexOf("<") === 0)
@ -402,18 +399,5 @@ ColumnLayout
} }
} }
} }
Rectangle
{
id: right
Layout.preferredWidth: blockWidth
height: 10
anchors.top: parent.bottom
anchors.topMargin: 5
color: "#DEDCDC"
radius: 15
anchors.left: parent.left
anchors.leftMargin: statusWidth
}
} }

1
mix/qml/Ether.qml

@ -54,6 +54,7 @@ RowLayout {
{ {
id: units id: units
visible: displayUnitSelection; visible: displayUnitSelection;
implicitWidth: 145
onCurrentTextChanged: onCurrentTextChanged:
{ {
if (value) if (value)

24
mix/qml/QAddressView.qml

@ -2,14 +2,14 @@ import QtQuick 2.0
import QtQuick.Controls 1.3 import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3 import QtQuick.Controls.Styles 1.3
Item Row
{ {
property alias value: textinput.text property alias value: textinput.text
property alias accountRef: ctrModel property alias accountRef: ctrModel
property string subType property string subType
property bool readOnly property bool readOnly
property alias currentIndex: trCombobox.currentIndex property alias currentIndex: trCombobox.currentIndex
property alias currentText: textinput.text property alias displayInput: textInputRect.visible
property variant accounts property variant accounts
signal indexChanged() signal indexChanged()
id: editRoot id: editRoot
@ -22,7 +22,7 @@ Item
} }
function currentValue() { function currentValue() {
return currentText; return value;
} }
function currentType() function currentType()
@ -38,7 +38,6 @@ Item
function load() function load()
{ {
accountRef.clear(); accountRef.clear();
accountRef.append({"itemid": " - "});
if (subType === "contract" || subType === "address") if (subType === "contract" || subType === "address")
{ {
var trCr = 0; var trCr = 0;
@ -52,7 +51,7 @@ Item
if (i > transactionIndex) if (i > transactionIndex)
break; break;
var tr = blockChainPanel.model.blocks[k].transactions[i] var tr = blockChainPanel.model.blocks[k].transactions[i]
if (tr.functionId === tr.contractId /*&& (dec[1] === tr.contractId || item.subType === "address")*/) if (tr.functionId === tr.contractId)
{ {
accountRef.append({ "itemid": tr.contractId + " - " + trCr, "value": "<" + tr.contractId + " - " + trCr + ">", "type": "contract" }); accountRef.append({ "itemid": tr.contractId + " - " + trCr, "value": "<" + tr.contractId + " - " + trCr + ">", "type": "contract" });
trCr++; trCr++;
@ -87,6 +86,7 @@ Item
} }
trCombobox.currentIndex = 0; trCombobox.currentIndex = 0;
} }
trCombobox.update()
} }
function select(address) function select(address)
@ -102,10 +102,10 @@ Item
} }
Rectangle { Rectangle {
anchors.fill: parent
radius: 4 radius: 4
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
height: 20 height: 20
id: textInputRect
TextInput { TextInput {
id: textinput id: textinput
text: value text: value
@ -141,12 +141,12 @@ Item
property bool selected: false property bool selected: false
id: trCombobox id: trCombobox
model: ctrModel model: ctrModel
width: 350
textRole: "itemid" textRole: "itemid"
height: 20
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: textinput.parent.right
anchors.leftMargin: 3 function update()
onCurrentIndexChanged: { {
trCombobox.selected = false; trCombobox.selected = false;
if (currentText === "") if (currentText === "")
return; return;
@ -164,5 +164,9 @@ Item
} }
indexChanged(); indexChanged();
} }
onCurrentIndexChanged: {
update()
}
} }
} }

21
mix/qml/QBoolTypeView.qml

@ -21,16 +21,19 @@ Item
value = value === "true" ? "1" : value value = value === "true" ? "1" : value
value = value === "false" ? "0" : value; value = value === "false" ? "0" : value;
var setValue = "1"
if (value === "") if (value === "")
boolCombo.currentIndex = parseInt(defaultValue); setValue = parseInt(defaultValue);
else else
boolCombo.currentIndex = parseInt(value); setValue = parseInt(value);
boolCombo.checked = setValue === "1" ? true: false
boolCombo.enabled = !readOnly; boolCombo.enabled = !readOnly;
} }
Rectangle { Rectangle {
color: "transparent"
anchors.fill: parent anchors.fill: parent
ComboBox CheckBox
{ {
property bool inited; property bool inited;
Component.onCompleted: Component.onCompleted:
@ -41,17 +44,13 @@ Item
id: boolCombo id: boolCombo
anchors.fill: parent anchors.fill: parent
onCurrentIndexChanged: onCheckedChanged:
{ {
if (inited) if (inited)
value = comboModel.get(currentIndex).value; value = checked ? "1" : "0"
}
model: ListModel
{
id: comboModel
ListElement { text: qsTr("False"); value: "0" }
ListElement { text: qsTr("True"); value: "1" }
} }
text: qsTr("True")
} }
} }
} }

7
mix/qml/QHashTypeView.qml

@ -13,16 +13,10 @@ Item
id: boldFont id: boldFont
} }
Rectangle {
anchors.fill: parent
radius: 4
TextInput { TextInput {
id: textinput id: textinput
text: value text: value
anchors.fill: parent
wrapMode: Text.WrapAnywhere wrapMode: Text.WrapAnywhere
clip: true
font.family: boldFont.name
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
@ -31,4 +25,3 @@ Item
} }
} }
} }
}

17
mix/qml/QIntTypeView.qml

@ -1,29 +1,21 @@
import QtQuick 2.0 import QtQuick 2.0
import QtQuick.Controls 1.1
Item Item
{ {
property alias value: textinput.text property alias value: textinput.text
property alias readOnly: textinput.readOnly property alias readOnly: textinput.readOnly
id: editRoot id: editRoot
width: readOnly ? textinput.implicitWidth : 150 width: 200
DebuggerPaneStyle { DebuggerPaneStyle {
id: dbgStyle id: dbgStyle
} }
Rectangle { TextField {
anchors.fill: parent
radius: 4
TextInput {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
id: textinput id: textinput
font.family: dbgStyle.general.basicFont
clip: true
selectByMouse: true selectByMouse: true
text: value text: value
anchors.fill: parent implicitWidth: 200
font.pointSize: dbgStyle.general.basicFontSize
color: dbgStyle.general.basicColor
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
@ -32,4 +24,3 @@ Item
} }
} }
} }
}

12
mix/qml/QStringTypeView.qml

@ -1,4 +1,5 @@
import QtQuick 2.0 import QtQuick 2.0
import QtQuick.Controls 1.1
Item Item
{ {
@ -11,19 +12,11 @@ Item
id: dbgStyle id: dbgStyle
} }
Rectangle { TextField {
anchors.fill: parent
radius: 4
TextInput {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
id: textinput id: textinput
font.family: dbgStyle.general.basicFont
clip: true
selectByMouse: true selectByMouse: true
text: value text: value
anchors.fill: parent
font.pointSize: dbgStyle.general.basicFontSize
color: dbgStyle.general.basicColor
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
@ -32,7 +25,6 @@ Item
} }
} }
} }
}

50
mix/qml/StructView.qml

@ -13,58 +13,40 @@ Column
property int transactionIndex property int transactionIndex
property string context property string context
Layout.fillWidth: true Layout.fillWidth: true
spacing: 0 spacing: 5
DebuggerPaneStyle {
id: dbgStyle
}
Repeater Repeater
{ {
id: repeater id: repeater
visible: model.length > 0 visible: model.length > 0
Layout.fillWidth: true
RowLayout RowLayout
{ {
id: row id: row
height: 20 + (members[index].type.category === QSolidityType.Struct ? (20 * members[index].type.members.length) : 0) height: 30 + (members[index].type.category === QSolidityType.Struct ? (30 * members[index].type.members.length) : 0)
Layout.fillWidth: true Layout.fillWidth: true
DefaultLabel { Rectangle
height: 20 {
id: typeLabel Layout.preferredWidth: 150
text: modelData.type.name Row
{
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
font.family: dbgStyle.general.basicFont Label {
color: dbgStyle.general.basicColor
font.pointSize: dbgStyle.general.basicFontSize
}
DefaultLabel {
height: 20
id: nameLabel id: nameLabel
text: modelData.name text: modelData.name
anchors.verticalCenter: parent.verticalCenter
font.family: dbgStyle.general.basicFont
color: dbgStyle.general.basicColor
font.pointSize: dbgStyle.general.basicFontSize
} }
DefaultLabel { Label {
height: 20 id: typeLabel
id: equalLabel text: " (" + modelData.type.name + ")"
text: "=" font.italic: true
anchors.verticalCenter: parent.verticalCenter font.weight: Font.Light
font.family: dbgStyle.general.basicFont }
color: dbgStyle.general.basicColor }
font.pointSize: dbgStyle.general.basicFontSize
} }
Loader Loader
{ {
id: typeLoader id: typeLoader
height: 20
anchors.verticalCenter: parent.verticalCenter
sourceComponent: sourceComponent:
{ {
var t = modelData.type.category; var t = modelData.type.category;

544
mix/qml/TransactionDialog.qml

@ -7,12 +7,13 @@ import QtQuick.Controls.Styles 1.3
import org.ethereum.qml.QEther 1.0 import org.ethereum.qml.QEther 1.0
import "js/TransactionHelper.js" as TransactionHelper import "js/TransactionHelper.js" as TransactionHelper
import "js/InputValidator.js" as InputValidator import "js/InputValidator.js" as InputValidator
import "js/NetworkDeployment.js" as NetworkDeployment
import "." import "."
Dialog { Dialog {
id: modalTransactionDialog id: modalTransactionDialog
modality: Qt.ApplicationModal modality: Qt.ApplicationModal
width: 570 width: 580
height: 500 height: 500
visible: false visible: false
title: qsTr("Edit Transaction") title: qsTr("Edit Transaction")
@ -22,7 +23,7 @@ Dialog {
property alias gasAuto: gasAutoCheck.checked; property alias gasAuto: gasAutoCheck.checked;
property alias gasPrice: gasPriceField.value; property alias gasPrice: gasPriceField.value;
property alias transactionValue: valueField.value; property alias transactionValue: valueField.value;
property string contractId: contractComboBox.currentValue(); property string contractId: contractCreationComboBox.currentValue();
property alias functionId: functionComboBox.currentText; property alias functionId: functionComboBox.currentText;
property var paramValues; property var paramValues;
property var paramsModel: []; property var paramsModel: [];
@ -30,21 +31,16 @@ Dialog {
property alias stateAccounts: senderComboBox.model property alias stateAccounts: senderComboBox.model
property bool saveStatus property bool saveStatus
signal accepted; signal accepted;
property int rowWidth: 500
StateDialogStyle { StateDialogStyle {
id: transactionDialogStyle id: transactionDialogStyle
} }
function open(index, blockIdx, item) { function open(index, blockIdx, item) {
rowFunction.visible = !useTransactionDefaultValue;
rowValue.visible = !useTransactionDefaultValue;
rowGas.visible = !useTransactionDefaultValue;
rowGasPrice.visible = !useTransactionDefaultValue;
transactionIndex = index transactionIndex = index
blockIndex = blockIdx blockIndex = blockIdx
typeLoader.transactionIndex = index paramScroll.transactionIndex = index
typeLoader.blockIndex = blockIdx paramScroll.blockIndex = blockIdx
saveStatus = item.saveStatus saveStatus = item.saveStatus
gasValueEdit.gasValue = item.gas; gasValueEdit.gasValue = item.gas;
gasAutoCheck.checked = item.gasAuto ? true : false; gasAutoCheck.checked = item.gasAuto ? true : false;
@ -52,48 +48,20 @@ Dialog {
valueField.value = item.value; valueField.value = item.value;
var contractId = item.contractId; var contractId = item.contractId;
var functionId = item.functionId; var functionId = item.functionId;
rowFunction.visible = true;
paramValues = item.parameters !== undefined ? item.parameters : {}; paramValues = item.parameters !== undefined ? item.parameters : {};
if (item.sender) if (item.sender)
senderComboBox.select(item.sender); senderComboBox.select(item.sender);
contractsModel.clear();
var contractIndex = -1;
var contracts = codeModel.contracts;
for (var c in contracts) {
contractsModel.append({ cid: c, text: contracts[c].contract.name });
if (contracts[c].contract.name === contractId)
contractIndex = contractsModel.count - 1;
}
if (contractIndex == -1 && contractsModel.count > 0) trTypeCreate.checked = item.isContractCreation
contractIndex = 0; //@todo suggest unused contract trTypeSend.checked = !item.isFunctionCall
contractComboBox.currentIndex = contractIndex; trTypeExecute.checked = item.isFunctionCall && !item.isContractCreation
recipients.accounts = senderComboBox.model; load(item.isContractCreation, item.isFunctionCall, functionId, contractId)
recipients.subType = "address";
recipients.load();
recipients.init();
recipients.select(contractId);
if (item.isContractCreation)
loadFunctions(contractComboBox.currentValue());
else
loadFunctions(contractFromToken(recipients.currentValue()))
selectFunction(functionId);
trType.checked = item.isContractCreation
trType.init();
paramsModel = [];
if (item.isContractCreation)
loadCtorParameters();
else
loadParameters();
estimatedGas.updateView()
visible = true; visible = true;
valueField.focus = true;
} }
function loadCtorParameters(contractId) function loadCtorParameters(contractId)
@ -111,11 +79,11 @@ Dialog {
function loadFunctions(contractId) function loadFunctions(contractId)
{ {
functionsModel.clear(); functionsModel.clear();
functionsModel.append({ text: " - " });
var contract = codeModel.contracts[contractId]; var contract = codeModel.contracts[contractId];
if (contract) { if (contract) {
var functions = codeModel.contracts[contractId].contract.functions; var functions = codeModel.contracts[contractId].contract.functions;
for (var f = 0; f < functions.length; f++) { for (var f = 0; f < functions.length; f++) {
if (functions[f].name !== contractId)
functionsModel.append({ text: functions[f].name }); functionsModel.append({ text: functions[f].name });
} }
} }
@ -156,9 +124,9 @@ Dialog {
function loadParameters() { function loadParameters() {
paramsModel = [] paramsModel = []
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
var contract = codeModel.contracts[contractFromToken(recipients.currentValue())]; var contract = codeModel.contracts[contractFromToken(contractCreationComboBox.currentValue())];
if (contract) { if (contract) {
var func = contract.contract.functions[functionComboBox.currentIndex - 1]; var func = contract.contract.functions[functionComboBox.currentIndex + 1];
if (func) { if (func) {
var parameters = func.parameters; var parameters = func.parameters;
for (var p = 0; p < parameters.length; p++) for (var p = 0; p < parameters.length; p++)
@ -171,13 +139,11 @@ Dialog {
function initTypeLoader() function initTypeLoader()
{ {
typeLoader.value = {} paramScroll.value = {}
typeLoader.members = [] paramScroll.members = []
typeLoader.value = paramValues; paramScroll.value = paramValues;
typeLoader.members = paramsModel; paramScroll.members = paramsModel;
paramLabel.visible = paramsModel.length > 0; paramScroll.updateView()
paramScroll.visible = paramsModel.length > 0;
modalTransactionDialog.height = (paramsModel.length > 0 ? 500 : 300);
} }
function acceptAndClose() function acceptAndClose()
@ -213,16 +179,16 @@ Dialog {
item.functionId = transactionDialog.functionId; item.functionId = transactionDialog.functionId;
} }
item.isContractCreation = trType.checked; item.isContractCreation = trTypeCreate.checked;
if (item.isContractCreation) if (item.isContractCreation)
item.functionId = item.contractId; item.functionId = item.contractId;
item.isFunctionCall = item.functionId !== " - "; item.isFunctionCall = trTypeExecute.checked
if (!item.isContractCreation) if (!item.isContractCreation)
{ {
item.contractId = recipients.currentText; item.contractId = recipientsAccount.currentValue();
item.label = item.contractId + " " + item.functionId; item.label = contractFromToken(item.contractId) + "." + item.functionId + "()";
if (recipients.current().type === "address") if (recipientsAccount.current().type === "address")
{ {
item.functionId = ""; item.functionId = "";
item.isFunctionCall = false; item.isFunctionCall = false;
@ -230,8 +196,9 @@ Dialog {
} }
else else
{ {
item.isFunctionCall = true
item.functionId = item.contractId; item.functionId = item.contractId;
item.label = qsTr("Deploy") + " " + item.contractId; item.label = item.contractId + "." + item.contractId + "()";
} }
item.saveStatus = saveStatus item.saveStatus = saveStatus
item.sender = senderComboBox.model[senderComboBox.currentIndex].secret; item.sender = senderComboBox.model[senderComboBox.currentIndex].secret;
@ -246,29 +213,97 @@ Dialog {
return token; return token;
} }
function load(isContractCreation, isFunctionCall, functionId, contractId)
{
if (!isContractCreation)
{
contractCreationComboBox.visible = false
recipientsAccount.visible = true
recipientsAccount.accounts = senderComboBox.model;
amountLabel.text = qsTr("Amount")
if (!isFunctionCall)
recipientsAccount.subType = "address"
else
recipientsAccount.subType = "contract";
recipientsAccount.load();
recipientsAccount.init();
if (contractId)
recipientsAccount.select(contractId);
if (functionId)
selectFunction(functionId);
if (isFunctionCall)
{
labelRecipient.text = qsTr("Recipient Contract")
functionRect.show()
loadFunctions(contractFromToken(recipientsAccount.currentValue()))
loadParameters();
paramScroll.updateView()
}
else
{
paramsModel = []
paramScroll.updateView()
labelRecipient.text = qsTr("Recipient Account")
functionRect.hide()
}
}
else
{
//contract creation
contractsModel.clear();
var contractIndex = -1;
var contracts = codeModel.contracts;
for (var c in contracts) {
contractsModel.append({ cid: c, text: contracts[c].contract.name });
if (contracts[c].contract.name === contractId)
contractIndex = contractsModel.count - 1;
}
if (contractIndex == -1 && contractsModel.count > 0)
contractIndex = 0; //@todo suggest unused contract
contractCreationComboBox.currentIndex = contractIndex;
contractCreationComboBox.visible = true
labelRecipient.text = qsTr("Contract")
amountLabel.text = qsTr("Endownment")
functionRect.hide()
recipientsAccount.visible = false
loadCtorParameters(contractCreationComboBox.currentValue());
paramScroll.updateView()
}
}
contentItem: Rectangle { contentItem: Rectangle {
id: containerRect
color: transactionDialogStyle.generic.backgroundColor color: transactionDialogStyle.generic.backgroundColor
ColumnLayout {
anchors.fill: parent anchors.fill: parent
ColumnLayout { ScrollView
{
anchors.top: parent.top
anchors.fill: parent anchors.fill: parent
anchors.margins: 10
ColumnLayout { ColumnLayout {
id: dialogContent Layout.preferredWidth: rowWidth
anchors.top: parent.top anchors.top: parent.top
spacing: 10 anchors.topMargin: 10
anchors.left: parent.left
width: 500
anchors.leftMargin:
{
return (containerRect.width - 530) /2
}
RowLayout RowLayout
{ {
id: rowSender Rectangle
Layout.fillWidth: true {
height: 150 Layout.preferredWidth: 150
DefaultLabel { Label {
Layout.preferredWidth: 75 anchors.right: parent.right
text: qsTr("Sender") anchors.verticalCenter: parent.verticalCenter
text: qsTr("Sender Account")
}
} }
ComboBox {
ComboBox {
function select(secret) function select(secret)
{ {
for (var i in model) for (var i in model)
@ -278,9 +313,8 @@ Dialog {
break; break;
} }
} }
id: senderComboBox
Layout.preferredWidth: 350 Layout.preferredWidth: 350
id: senderComboBox
currentIndex: 0 currentIndex: 0
textRole: "name" textRole: "name"
editable: false editable: false
@ -289,68 +323,104 @@ Dialog {
RowLayout RowLayout
{ {
id: rowIsContract Rectangle
Layout.fillWidth: true
height: 150
CheckBox {
id: trType
onCheckedChanged:
{ {
init(); Layout.preferredWidth: 150
Layout.preferredHeight: 80
color: "transparent"
Label
{
anchors.verticalCenter: parent.verticalCenter
anchors.top: parent.top
anchors.right: parent.right
text: qsTr("Type of Transaction")
}
} }
function init() Column
{ {
rowFunction.visible = !checked; Layout.preferredWidth: 350
rowContract.visible = checked; Layout.preferredHeight: 90
rowRecipient.visible = !checked; ExclusiveGroup {
paramLabel.visible = checked; id: rbbuttonList
paramScroll.visible = checked; onCurrentChanged: {
functionComboBox.enabled = !checked; if (current)
if (checked) {
loadCtorParameters(contractComboBox.currentValue()); if (current.objectName === "trTypeSend")
{
recipientsAccount.visible = true
contractCreationComboBox.visible = false
modalTransactionDialog.load(false, false)
}
else if (current.objectName === "trTypeCreate")
{
contractCreationComboBox.visible = true
recipientsAccount.visible = false
modalTransactionDialog.load(true, true)
}
else if (current.objectName === "trTypeExecute")
{
recipientsAccount.visible = true
contractCreationComboBox.visible = false
modalTransactionDialog.load(false, true)
}
}
}
} }
text: qsTr("is contract creation") RadioButton {
checked: true id: trTypeSend
objectName: "trTypeSend"
exclusiveGroup: rbbuttonList
height: 30
text: qsTr("Send ether to account")
}
RadioButton {
id: trTypeCreate
objectName: "trTypeCreate"
exclusiveGroup: rbbuttonList
height: 30
text: qsTr("Create Contract")
}
RadioButton {
id: trTypeExecute
objectName: "trTypeExecute"
exclusiveGroup: rbbuttonList
height: 30
text: qsTr("Execute Contract")
}
} }
} }
RowLayout RowLayout
{ {
id: rowRecipient Rectangle
Layout.fillWidth: true {
height: 150 Layout.preferredWidth: 150
DefaultLabel { Label {
Layout.preferredWidth: 75 id: labelRecipient
text: qsTr("Recipient") anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
text: qsTr("Recipient Account")
}
} }
QAddressView QAddressView
{ {
id: recipients id: recipientsAccount
displayInput: false
onIndexChanged: onIndexChanged:
{ {
rowFunction.visible = current().type === "contract"; if (rbbuttonList.current.objectName === "trTypeExecute")
paramLabel.visible = current().type === "contract"; loadFunctions(contractFromToken(currentValue()))
paramScroll.visible = current().type === "contract";
if (!rowIsContract.checked)
loadFunctions(contractFromToken(recipients.currentValue()))
}
} }
} }
RowLayout
{
id: rowContract
Layout.fillWidth: true
height: 150
DefaultLabel {
Layout.preferredWidth: 75
text: qsTr("Contract")
}
ComboBox { ComboBox {
id: contractComboBox id: contractCreationComboBox
function currentValue() { function currentValue() {
return (currentIndex >=0 && currentIndex < contractsModel.count) ? contractsModel.get(currentIndex).cid : ""; return (currentIndex >=0 && currentIndex < contractsModel.count) ? contractsModel.get(currentIndex).cid : "";
} }
@ -369,13 +439,32 @@ Dialog {
RowLayout RowLayout
{ {
id: rowFunction Rectangle
Layout.fillWidth: true {
height: 150 Layout.preferredWidth: 150
DefaultLabel { id: functionRect
Layout.preferredWidth: 75
function hide()
{
parent.visible = false
functionRect.visible = false
functionComboBox.visible = false
}
function show()
{
parent.visible = true
functionRect.visible = true
functionComboBox.visible = true
}
Label {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
text: qsTr("Function") text: qsTr("Function")
} }
}
ComboBox { ComboBox {
id: functionComboBox id: functionComboBox
Layout.preferredWidth: 350 Layout.preferredWidth: 350
@ -391,42 +480,93 @@ Dialog {
} }
} }
CommonSeparator StructView
{ {
id: paramScroll
members: paramsModel;
accounts: senderComboBox.model
context: "parameter"
Layout.fillWidth: true Layout.fillWidth: true
function updateView()
{
paramScroll.visible = paramsModel.length > 0
paramScroll.Layout.preferredHeight = paramsModel.length < 6 ? paramsModel.length * 30 : 205
if (paramsModel.length === 0)
{
paramScroll.height = 0
}
}
} }
RowLayout RowLayout
{ {
id: rowValue Rectangle
Layout.fillWidth: true {
height: 150 Layout.preferredWidth: 150
DefaultLabel { Label {
Layout.preferredWidth: 75 id: amountLabel
text: qsTr("Value") anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
text: qsTr("Amount")
} }
}
Ether { Ether {
Layout.preferredWidth: 350
id: valueField id: valueField
edit: true edit: true
displayFormattedValue: true displayFormattedValue: false
displayUnitSelection: true
} }
} }
CommonSeparator Rectangle
{ {
Layout.preferredHeight: 30
Layout.fillWidth: true Layout.fillWidth: true
color: "transparent"
Rectangle
{
color: "#cccccc"
height: 1
width: parent.width
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle
{
height: 20
color: "transparent"
Layout.preferredWidth: 500
Rectangle
{
anchors.horizontalCenter: parent.horizontalCenter
Label {
text: qsTr("Transaction fees")
anchors.horizontalCenter: parent.horizontalCenter
}
}
} }
RowLayout RowLayout
{ {
id: rowGas Layout.preferredHeight: 45
Layout.fillWidth: true Rectangle
height: 150 {
DefaultLabel { Layout.preferredWidth: 150
Layout.preferredWidth: 75 Label {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
text: qsTr("Gas") text: qsTr("Gas")
} }
}
Row
{
Layout.preferredWidth: 350
DefaultTextField DefaultTextField
{ {
property variant gasValue property variant gasValue
@ -435,81 +575,119 @@ Dialog {
implicitWidth: 200 implicitWidth: 200
enabled: !gasAutoCheck.checked enabled: !gasAutoCheck.checked
id: gasValueEdit; id: gasValueEdit;
}
CheckBox Label
{ {
id: gasAutoCheck id: estimatedGas
checked: true anchors.top: parent.bottom
text: qsTr("Auto"); text: ""
Connections
{
target: functionComboBox
onCurrentIndexChanged:
{
estimatedGas.displayGas(contractFromToken(recipientsAccount.currentValue()), functionComboBox.currentText)
} }
} }
CommonSeparator function displayGas(contractName, functionName)
{ {
Layout.fillWidth: true var gasCost = codeModel.gasCostBy(contractName, functionName);
if (gasCost && gasCost.length > 0)
{
var gas = codeModel.txGas + codeModel.callStipend + parseInt(gasCost[0].gas)
estimatedGas.text = qsTr("Estimated cost: ") + gasCost[0].gas + " gas"
}
} }
RowLayout function updateView()
{ {
id: rowGasPrice if (rbbuttonList.current.objectName === "trTypeExecute")
Layout.fillWidth: true estimatedGas.displayGas(contractFromToken(recipientsAccount.currentValue()), functionComboBox.currentText)
height: 150 else if (rbbuttonList.current.objectName === "trTypeCreate")
DefaultLabel { {
Layout.preferredWidth: 75 var contractName = contractCreationComboBox.currentValue()
text: qsTr("Gas Price") estimatedGas.displayGas(contractName, contractName)
} }
Ether { else if (rbbuttonList.current.objectName === "trTypeSend")
id: gasPriceField {
edit: true var gas = codeModel.txGas + codeModel.callStipend
displayFormattedValue: true estimatedGas.text = qsTr("Estimated cost: ") + gas + " gas"
} }
} }
CommonSeparator Connections
{ {
Layout.fillWidth: true target: rbbuttonList
onCurrentChanged: {
estimatedGas.updateView()
}
}
}
} }
DefaultLabel { CheckBox
id: paramLabel {
text: qsTr("Parameters:") id: gasAutoCheck
Layout.preferredWidth: 75 checked: true
text: qsTr("Auto");
}
}
} }
ScrollView RowLayout
{ {
id: paramScroll Layout.preferredWidth: 500
anchors.top: paramLabel.bottom Layout.preferredHeight: 45
anchors.topMargin: 10 Rectangle
Layout.fillWidth: true
Layout.fillHeight: true
StructView
{ {
id: typeLoader
Layout.preferredWidth: 150 Layout.preferredWidth: 150
members: paramsModel; Label {
accounts: senderComboBox.model id: gasPriceLabel
context: "parameter" anchors.verticalCenter: parent.verticalCenter
} anchors.right: parent.right
} text: qsTr("Gas Price")
CommonSeparator Label {
id: gasPriceMarket
anchors.top: gasPriceLabel.bottom
Component.onCompleted:
{ {
Layout.fillWidth: true NetworkDeployment.gasPrice(function(result)
visible: paramsModel.length > 0 {
gasPriceMarket.text = qsTr("Current market: ") + " " + result + " Wei";
}, function (){});
}
} }
} }
} }
Ether {
Layout.preferredWidth: 350
id: gasPriceField
edit: true
displayFormattedValue: false
displayUnitSelection: true
}
}
RowLayout RowLayout
{ {
anchors.bottom: parent.bottom
anchors.right: parent.right;
Layout.preferredWidth: 500
Row
{
width: parent.width
anchors.right: parent.right
Button { Button {
id: updateBtn
text: qsTr("Cancel");
onClicked: close();
}
text: qsTr("OK"); Button {
text: qsTr("Update");
onClicked: { onClicked: {
var invalid = InputValidator.validate(paramsModel, paramValues); var invalid = InputValidator.validate(paramsModel, paramValues);
if (invalid.length === 0) if (invalid.length === 0)
@ -526,10 +704,6 @@ Dialog {
} }
} }
} }
Button {
text: qsTr("Cancel");
onClicked: close();
} }
MessageDialog { MessageDialog {
@ -538,7 +712,13 @@ Dialog {
icon: StandardIcon.Critical icon: StandardIcon.Critical
} }
} }
RowLayout
{
Layout.preferredHeight: 30
anchors.bottom: parent.bottom
}
}
} }
} }
} }

6
mix/qml/js/NetworkDeployment.js

@ -201,7 +201,7 @@ function executeTrNextStep(trIndex, state, ctrAddresses, callBack)
callBack(); callBack();
} }
function gasPrice(callBack) function gasPrice(callBack, error)
{ {
var requests = [{ var requests = [{
jsonrpc: "2.0", jsonrpc: "2.0",
@ -210,7 +210,9 @@ function gasPrice(callBack)
id: jsonRpcRequestId id: jsonRpcRequestId
}]; }];
rpcCall(requests, function (httpCall, response){ rpcCall(requests, function (httpCall, response){
callBack(JSON.parse(response)[0].result); callBack(JSON.parse(response)[0].result)
}, function(message){
error(message)
}); });
} }

4
mix/qml/js/TransactionHelper.js

@ -17,7 +17,7 @@ function defaultTransaction()
}; };
} }
function rpcCall(requests, callBack) function rpcCall(requests, callBack, error)
{ {
var jsonRpcUrl = "http://localhost:8545"; var jsonRpcUrl = "http://localhost:8545";
var rpcRequest = JSON.stringify(requests); var rpcRequest = JSON.stringify(requests);
@ -33,7 +33,7 @@ function rpcCall(requests, callBack)
{ {
var errorText = qsTr("Unable to initiate request to the live network. Please verify your ethereum node is up.") + qsTr(" Error status: ") + httpRequest.status; var errorText = qsTr("Unable to initiate request to the live network. Please verify your ethereum node is up.") + qsTr(" Error status: ") + httpRequest.status;
console.log(errorText); console.log(errorText);
deploymentError(errorText); error(errorText);
} }
else else
{ {

Loading…
Cancel
Save