diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 95d4d497b..a58366046 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -256,9 +256,9 @@ void ClientModel::setupState(QVariantMap _state) u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); QString sender = transaction.value("sender").toString(); bool isStdContract = transaction.value("stdContract").toBool(); - bool isContractCall; - if (!transaction.value("isContractCall").isNull()) - isContractCall = transaction.value("isContractCall").toBool(); + bool isContractCreation; + if (!transaction.value("isContractCreation").isNull()) + isContractCreation = transaction.value("isContractCreation").toBool(); if (isStdContract) { if (contractId.isEmpty()) //TODO: This is to support old project files, remove later @@ -274,7 +274,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()), isContractCall); + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCreation); transactionSettings.parameterValues = transaction.value("parameters").toMap(); if (contractId == functionId || functionId == "Constructor") @@ -310,9 +310,10 @@ void ClientModel::executeSequence(vector const& _sequence, m_gasCosts.clear(); for (TransactionSettings const& transaction: _sequence) { - if (!transaction.isContractCall) + QString contractName = resolveContractName(transaction.contractId); + QString address = resolveToken(transaction.contractId, deployedContracts); + if (transaction.functionId == "(transfert)") { - QString address = resolveToken(transaction.contractId, deployedContracts); callAddress(Address(address.toStdString()), bytes(), transaction); onNewTransaction(); continue; @@ -332,7 +333,7 @@ void ClientModel::executeSequence(vector const& _sequence, else { //encode data - CompiledContract const& compilerRes = m_codeModel->contract(transaction.contractId); + CompiledContract const& compilerRes = m_codeModel->contract(contractName); QFunctionDefinition const* f = nullptr; bytes contractCode = compilerRes.bytes(); shared_ptr contractDef = compilerRes.sharedContract(); @@ -363,7 +364,7 @@ void ClientModel::executeSequence(vector const& _sequence, encoder.encode(value, type->type()); } - if (transaction.functionId.isEmpty() || transaction.functionId == transaction.contractId) + if (transaction.functionId.isEmpty() || transaction.functionId == contractName) { bytes param = encoder.encodedData(); contractCode.insert(contractCode.end(), param.begin(), param.end()); @@ -372,8 +373,9 @@ void ClientModel::executeSequence(vector const& _sequence, auto contractAddressIter = m_contractAddresses.find(transaction.contractId); if (contractAddressIter == m_contractAddresses.end() || newAddress != contractAddressIter->second) { - m_contractAddresses[transaction.contractId] = newAddress; - m_contractNames[newAddress] = transaction.contractId; + QString contractToken = "<" + transaction.contractId + " - " + QString::number(deployedContracts.size() - 1) + ">"; + m_contractAddresses[contractToken] = newAddress; + m_contractNames[newAddress] = contractToken; contractAddressesChanged(); } gasCostsChanged(); @@ -388,7 +390,7 @@ void ClientModel::executeSequence(vector const& _sequence, emit runStateChanged(); return; } - callAddress(contractAddressIter->second, encoder.encodedData(), transaction); + callAddress(Address(address.toStdString()), encoder.encodedData(), transaction); } m_gasCosts.append(m_client->lastExecution().gasUsed); } @@ -423,6 +425,14 @@ QString ClientModel::resolveToken(QString const& _value, vector
const& return ret; } +QString ClientModel::resolveContractName(QString const& _value) +{ + QString ret = _value; + if (_value.startsWith("<") && _value.endsWith(">")) + ret = ret.remove("<").remove(">").split(" - ").first(); + return ret; +} + void ClientModel::showDebugger() { ExecutionResult last = m_client->lastExecution(); @@ -446,7 +456,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t) //try to resolve contract for source level debugging auto nameIter = m_contractNames.find(code.address); CompiledContract const* compilerRes = nullptr; - if (nameIter != m_contractNames.end() && (compilerRes = m_codeModel->tryGetContract(nameIter->second))) //returned object is guaranteed to live till the end of event handler in main thread + if (nameIter != m_contractNames.end() && (compilerRes = m_codeModel->tryGetContract(resolveContractName(nameIter->second)))) //returned object is guaranteed to live till the end of event handler in main thread { eth::AssemblyItems assemblyItems = !_t.isConstructor() ? compilerRes->assemblyItems() : compilerRes->constructorAssemblyItems(); codes.back()->setDocument(compilerRes->documentId()); @@ -707,7 +717,7 @@ void ClientModel::onNewTransaction() auto contractAddressIter = m_contractNames.find(contractAddress); if (contractAddressIter != m_contractNames.end()) { - CompiledContract const& compilerRes = m_codeModel->contract(contractAddressIter->second); + CompiledContract const& compilerRes = m_codeModel->contract(resolveContractName(contractAddressIter->second)); const QContractDefinition* def = compilerRes.contract(); contract = def->name(); if (abi) diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 46cabe450..15cdc7086 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, int _isContractCall): - contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCall(_isContractCall) {} + TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender, int _isContractCreation): + contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCreation(_isContractCreation) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): - contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCall(true) {} + contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCreation(true) {} /// Contract name QString contractId; @@ -76,8 +76,8 @@ struct TransactionSettings QString stdContractUrl; /// Sender Secret sender; - /// Is a call to a contract - bool isContractCall; + /// Tr deploys a contract + bool isContractCreation; }; @@ -231,6 +231,7 @@ private: 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); + QString resolveContractName(QString const& _value); std::atomic m_running; std::atomic m_mining; diff --git a/mix/qml/QAddressView.qml b/mix/qml/QAddressView.qml index 19d98b166..c880f0904 100644 --- a/mix/qml/QAddressView.qml +++ b/mix/qml/QAddressView.qml @@ -30,6 +30,11 @@ Item return accountRef.get(trCombobox.currentIndex).type; } + function current() + { + return accountRef.get(trCombobox.currentIndex); + } + function load() { accountRef.clear(); diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index 13d01d474..f8da6dabd 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -436,7 +436,7 @@ Dialog { model: transactionsModel headerVisible: false TableViewColumn { - role: "name" + role: "label" title: qsTr("Name") width: 150 delegate: Item { @@ -476,7 +476,7 @@ Dialog { text: { if (styleData.row >= 0) return transactionsModel.get( - styleData.row).functionId + styleData.row).label else return "" } diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 3eac14a11..a6069d620 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -57,10 +57,15 @@ Item { stdContract: t.stdContract ? true : false, parameters: {}, sender: t.sender, - isContractCall: t.isContractCall + isContractCreation: t.isContractCreation, + label: t.label }; - if (r.isContractCall === undefined) - r.isContractCall = true; //support for old project + + if (!r.label) + r.label = r.contractId + " " + r.functionId; + + if (r.isContractCreation === undefined) + r.isContractCreation = true; //support for old project for (var key in t.parameters) r.parameters[key] = t.parameters[key]; @@ -115,7 +120,8 @@ Item { stdContract: t.stdContract, sender: t.sender, parameters: {}, - isContractCall: t.isContractCall + isContractCreation: t.isContractCreation, + label: t.label }; for (var key in t.parameters) r.parameters[key] = t.parameters[key]; diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 84abb854b..d26fbaf5a 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -66,34 +66,46 @@ Dialog { contractIndex = 0; //@todo suggest unused contract contractComboBox.currentIndex = contractIndex; - loadFunctions(contractComboBox.currentValue()); + recipients.accounts = senderComboBox.model; + 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 (functionId !== contractComboBox.currentValue()) + if (item.isContractCreation) + loadCtorParameters(); + else loadParameters(); - else { - var contract = codeModel.contracts[contractId]; - if (contract) { - var params = contract.contract.constructor.parameters; - for (var p = 0; p < params.length; p++) - loadParameter(params[p]); - } - } - 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; } + function loadCtorParameters(contractId) + { + paramsModel = []; + console.log(contractId); + var contract = codeModel.contracts[contractId]; + if (contract) { + var params = contract.contract.constructor.parameters; + for (var p = 0; p < params.length; p++) + loadParameter(params[p]); + } + initTypeLoader(); + } + function loadFunctions(contractId) { functionsModel.clear(); @@ -104,9 +116,7 @@ Dialog { functionsModel.append({ text: functions[f].name }); } } - //append constructor - functionsModel.append({ text: contractId }); - + functionsModel.append({ text: "(transfert)" }); } function selectContract(contractName) @@ -144,7 +154,7 @@ Dialog { function loadParameters() { paramsModel = [] if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { - var contract = codeModel.contracts[contractComboBox.currentValue()]; + var contract = codeModel.contracts[contractFromToken(recipients.currentValue())]; if (contract) { var func = contract.contract.functions[functionComboBox.currentIndex]; if (func) { @@ -201,17 +211,32 @@ Dialog { item.functionId = transactionDialog.functionId; } - item.isContractCall = trType.checked; - if (!item.isContractCall) + item.isContractCreation = trType.checked; + if (!item.isContractCreation) { - item.functionId = recipients.currentText; item.contractId = recipients.currentText; + item.label = item.contractId + " " + item.functionId; + if (recipients.current().type === "address") + item.functionId = "(transfert)"; + } + else + { + item.functionId = item.contractId; + item.label = qsTr("Deploy") + " " + item.contractId; } item.sender = senderComboBox.model[senderComboBox.currentIndex].secret; item.parameters = paramValues; return item; } + + function contractFromToken(token) + { + if (token.indexOf('<') === 0) + return token.replace("<", "").replace(">", "").split(" - ")[0]; + return token; + } + contentItem: Rectangle { color: transactionDialogStyle.generic.backgroundColor ColumnLayout { @@ -267,14 +292,17 @@ Dialog { function init() { - rowFunction.visible = checked; + rowFunction.visible = !checked; rowContract.visible = checked; rowRecipient.visible = !checked; paramLabel.visible = checked; paramScroll.visible = checked; + functionComboBox.enabled = !checked; + if (checked) + loadCtorParameters(contractComboBox.currentValue()); } - text: qsTr("is contract call") + text: qsTr("is contract creation") checked: true } } @@ -292,6 +320,14 @@ Dialog { QAddressView { id: recipients + onIndexChanged: + { + rowFunction.visible = current().type === "contract"; + paramLabel.visible = current().type === "contract"; + paramScroll.visible = current().type === "contract"; + if (!rowIsContract.checked) + loadFunctions(contractFromToken(recipients.currentValue())) + } } } @@ -317,7 +353,7 @@ Dialog { id: contractsModel } onCurrentIndexChanged: { - loadFunctions(currentValue()); + loadCtorParameters(currentValue()); } } } diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index 01fe65b5d..33072fdba 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -10,7 +10,8 @@ function defaultTransaction() gasPrice: createEther("100000", QEther.Wei), parameters: {}, stdContract: false, - isContractCall: true + isContractCreation: true, + label: "" }; }