From 40cf37dbb8ba6b5a4162f0c61e283a01cb0871df Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 8 May 2015 10:31:10 +0200 Subject: [PATCH] - basic transaction creation. --- mix/ClientModel.cpp | 36 +++++++++++++++------ mix/ClientModel.h | 11 ++++--- mix/qml/QAddressView.qml | 57 +++++++++++++++++++++++++++++++++ mix/qml/StateListModel.qml | 8 +++-- mix/qml/StructView.qml | 29 ++--------------- mix/qml/TransactionDialog.qml | 55 +++++++++++++++++++++++++++++++ mix/qml/js/TransactionHelper.js | 3 +- 7 files changed, 156 insertions(+), 43 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 717757c70..7f4817c91 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -250,7 +250,10 @@ void ClientModel::setupState(QVariantMap _state) u256 value = (qvariant_cast(transaction.value("value")))->toU256Wei(); u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); QString sender = transaction.value("sender").toString(); - bool isStdContract = (transaction.value("stdContract").toBool()); + bool isStdContract = transaction.value("stdContract").toBool(); + bool isContractCall; + if (!transaction.value("isContractCall").isNull()) + isContractCall = transaction.value("isContractCall").toBool(); if (isStdContract) { if (contractId.isEmpty()) //TODO: This is to support old project files, remove later @@ -266,7 +269,7 @@ void ClientModel::setupState(QVariantMap _state) { if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later contractId = m_codeModel->contracts().keys()[0]; - TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString())); + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCall); transactionSettings.parameterValues = transaction.value("parameters").toMap(); if (contractId == functionId || functionId == "Constructor") @@ -301,6 +304,13 @@ void ClientModel::executeSequence(vector const& _sequence, onStateReset(); for (TransactionSettings const& transaction: _sequence) { + if (!transaction.isContractCall) + { + QString address = resolveToken(transaction.contractId, deployedContracts); + callAddress(Address(address.toStdString()), bytes(), transaction); + onNewTransaction(); + continue; + } ContractCallDataEncoder encoder; if (!transaction.stdContractUrl.isEmpty()) { @@ -342,11 +352,8 @@ void ClientModel::executeSequence(vector const& _sequence, { QSolidityType const* type = p->type(); QVariant value = transaction.parameterValues.value(p->name()); - if (type->type().type == SolidityType::Type::Address && value.toString().startsWith("<") && value.toString().endsWith(">")) - { - QStringList nb = value.toString().remove("<").remove(">").split(" - "); - value = QVariant(QString::fromStdString("0x" + toHex(deployedContracts.at(nb.back().toInt()).ref()))); - } + if (type->type().type == SolidityType::Type::Address) + value = QVariant(resolveToken(value.toString(), deployedContracts)); encoder.encode(value, type->type()); } @@ -376,7 +383,7 @@ void ClientModel::executeSequence(vector const& _sequence, emit runStateChanged(); return; } - callContract(contractAddressIter->second, encoder.encodedData(), transaction); + callAddress(contractAddressIter->second, encoder.encodedData(), transaction); } } onNewTransaction(); @@ -399,6 +406,17 @@ void ClientModel::executeSequence(vector const& _sequence, }); } +QString ClientModel::resolveToken(QString const& _value, vector
const& _contracts) +{ + QString ret = _value; + if (_value.startsWith("<") && _value.endsWith(">")) + { + QStringList nb = ret.remove("<").remove(">").split(" - "); + ret = QString::fromStdString("0x" + toHex(_contracts.at(nb.back().toInt()).ref())); + } + return ret; +} + void ClientModel::showDebugger() { ExecutionResult last = m_client->lastExecution(); @@ -603,7 +621,7 @@ Address ClientModel::deployContract(bytes const& _code, TransactionSettings cons return newAddress; } -void ClientModel::callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) +void ClientModel::callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) { m_client->submitTransaction(_tr.sender, _tr.value, _contract, _data, _tr.gas, _tr.gasPrice, _tr.gasAuto); } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 9b0529ae6..db11406d6 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -53,10 +53,10 @@ struct SolidityType; struct TransactionSettings { TransactionSettings() {} - TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender): - contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender) {} + TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender, int _isContractCall): + contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCall(_isContractCall) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): - contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl) {} + contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCall(true) {} /// Contract name QString contractId; @@ -76,6 +76,8 @@ struct TransactionSettings QString stdContractUrl; /// Sender Secret sender; + /// Is a call to a contract + bool isContractCall; }; @@ -220,12 +222,13 @@ private: QVariantMap gasCosts() const; void executeSequence(std::vector const& _sequence, std::map const& _accounts, Secret const& _miner); dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); - void callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); + void callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); void onNewTransaction(); void onStateReset(); void showDebuggerForTransaction(ExecutionResult const& _t); QVariant formatValue(SolidityType const& _type, dev::u256 const& _value); QVariant formatStorageValue(SolidityType const& _type, std::map const& _storage, unsigned _offset, dev::u256 const& _slot); + QString resolveToken(QString const& _value, std::vector
const& _contracts); std::atomic m_running; std::atomic m_mining; diff --git a/mix/qml/QAddressView.qml b/mix/qml/QAddressView.qml index 204e92508..19d98b166 100644 --- a/mix/qml/QAddressView.qml +++ b/mix/qml/QAddressView.qml @@ -8,6 +8,10 @@ Item property alias accountRef: ctrModel property string subType property bool readOnly + property alias currentIndex: trCombobox.currentIndex + property alias currentText: textinput.text + property variant accounts + signal indexChanged() id: editRoot height: 20 width: 320 @@ -17,6 +21,46 @@ Item id: boldFont } + function currentValue() { + return currentText; + } + + function currentType() + { + return accountRef.get(trCombobox.currentIndex).type; + } + + function load() + { + accountRef.clear(); + accountRef.append({"itemid": " - "}); + + if (subType === "contract" || subType === "address") + { + var trCr = 0; + for (var k = 0; k < transactionsModel.count; k++) + { + if (k >= transactionIndex) + break; + var tr = transactionsModel.get(k); + if (tr.functionId === tr.contractId /*&& (dec[1] === tr.contractId || item.subType === "address")*/) + { + accountRef.append({ "itemid": tr.contractId + " - " + trCr, "value": "<" + tr.contractId + " - " + trCr + ">", "type": "contract" }); + trCr++; + } + } + } + if (subType === "address") + { + for (k = 0; k < accounts.length; k++) + { + if (accounts[k].address === undefined) + accounts[k].address = clientModel.address(accounts[k].secret); + accountRef.append({ "itemid": accounts[k].name, "value": "0x" + accounts[k].address, "type": "address" }); + } + } + } + function init() { trCombobox.visible = !readOnly @@ -35,6 +79,18 @@ Item } } + function select(address) + { + for (var k = 0; k < accountRef.count; k++) + { + if (accountRef.get(k).value === address) + { + trCombobox.currentIndex = k; + break; + } + } + } + Rectangle { anchors.fill: parent radius: 4 @@ -96,6 +152,7 @@ Item { textinput.text = ""; } + indexChanged(); } } } diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 889a2d940..d4aa678a6 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -46,6 +46,7 @@ Item { t.sender = defaultAccount; //support for old project var r = { + type: t.type, contractId: t.contractId, functionId: t.functionId, url: t.url, @@ -55,7 +56,8 @@ Item { gasAuto: t.gasAuto, stdContract: t.stdContract ? true : false, parameters: {}, - sender: t.sender + sender: t.sender, + isContractCall: t.isContractCall }; for (var key in t.parameters) r.parameters[key] = t.parameters[key]; @@ -100,6 +102,7 @@ Item { function toPlainTransactionItem(t) { var r = { + type: t.type, contractId: t.contractId, functionId: t.functionId, url: t.url, @@ -109,7 +112,8 @@ Item { gasPrice: { value: t.gasPrice.value, unit: t.gasPrice.unit }, stdContract: t.stdContract, sender: t.sender, - parameters: {} + parameters: {}, + isContractCall: t.isContractCall }; for (var key in t.parameters) r.parameters[key] = t.parameters[key]; diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml index 4df9ace67..4feab2166 100644 --- a/mix/qml/StructView.qml +++ b/mix/qml/StructView.qml @@ -75,38 +75,13 @@ Column item.readOnly = context === "variable"; if (ptype.category === QSolidityType.Address) { + item.accounts = accounts item.value = getValue(); if (context === "parameter") { var dec = modelData.type.name.split(" "); item.subType = dec[0]; - item.accountRef.append({"itemid": " - "}); - - if (item.subType === "contract" || item.subType === "address") - { - var trCr = 0; - for (var k = 0; k < transactionsModel.count; k++) - { - if (k >= transactionIndex) - break; - var tr = transactionsModel.get(k); - if (tr.functionId === tr.contractId && (dec[1] === tr.contractId || item.subType === "address")) - { - item.accountRef.append({ "itemid": tr.contractId + " - " + trCr, "value": "<" + tr.contractId + " - " + trCr + ">", "type": "contract" }); - trCr++; - } - } - } - if (item.subType === "address") - { - for (k = 0; k < accounts.length; k++) - { - if (accounts[k].address === undefined) - accounts[k].address = clientModel.address(accounts[k].secret); - item.accountRef.append({ "itemid": accounts[k].name, "value": "0x" + accounts[k].address, "type": "address" }); - } - - } + item.load(); } item.init(); } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 66a98d19e..f56093336 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -82,6 +82,14 @@ Dialog { } initTypeLoader(); + trType.checked = item.isContractCall + trType.init(); + + recipients.accounts = senderComboBox.model; + recipients.subType = "address"; + recipients.load(); + recipients.init(); + recipients.select(contractId); visible = true; valueField.focus = true; } @@ -193,6 +201,13 @@ Dialog { item.functionId = transactionDialog.functionId; } + item.isContractCall = trType.checked; + if (!item.isContractCall) + { + item.functionId = recipients.currentText; + item.contractId = recipients.currentText; + } + item.sender = senderComboBox.model[senderComboBox.currentIndex].secret; item.parameters = paramValues; return item; @@ -238,6 +253,46 @@ Dialog { } } + RowLayout + { + id: rowIsContract + Layout.fillWidth: true + height: 150 + CheckBox { + id: trType + onCheckedChanged: + { + init(); + } + + function init() + { + rowFunction.visible = checked; + rowContract.visible = checked; + rowRecipient.visible = !checked; + } + + text: qsTr("is contract call") + checked: true + } + } + + RowLayout + { + id: rowRecipient + Layout.fillWidth: true + height: 150 + DefaultLabel { + Layout.preferredWidth: 75 + text: qsTr("Recipient") + } + + QAddressView + { + id: recipients + } + } + RowLayout { id: rowContract diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index be057917c..57b03757a 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -9,7 +9,8 @@ function defaultTransaction() gasAuto: true, gasPrice: createEther("100000", QEther.Wei), parameters: {}, - stdContract: false + stdContract: false, + isContractCall: true }; }