Browse Source

- basic transaction creation.

cl-refactor
yann300 10 years ago
parent
commit
40cf37dbb8
  1. 36
      mix/ClientModel.cpp
  2. 11
      mix/ClientModel.h
  3. 57
      mix/qml/QAddressView.qml
  4. 8
      mix/qml/StateListModel.qml
  5. 29
      mix/qml/StructView.qml
  6. 55
      mix/qml/TransactionDialog.qml
  7. 3
      mix/qml/js/TransactionHelper.js

36
mix/ClientModel.cpp

@ -250,7 +250,10 @@ void ClientModel::setupState(QVariantMap _state)
u256 value = (qvariant_cast<QEther*>(transaction.value("value")))->toU256Wei();
u256 gasPrice = (qvariant_cast<QEther*>(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<TransactionSettings> 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<TransactionSettings> 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<TransactionSettings> 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<TransactionSettings> const& _sequence,
});
}
QString ClientModel::resolveToken(QString const& _value, vector<Address> 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);
}

11
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<TransactionSettings> const& _sequence, std::map<Address, dev::eth::Account> 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<dev::u256, dev::u256> const& _storage, unsigned _offset, dev::u256 const& _slot);
QString resolveToken(QString const& _value, std::vector<Address> const& _contracts);
std::atomic<bool> m_running;
std::atomic<bool> m_mining;

57
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();
}
}
}

8
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];

29
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();
}

55
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

3
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
};
}

Loading…
Cancel
Save