Fabcoin Core  0.16.2
P2P Digital Currency
createcontract.cpp
Go to the documentation of this file.
1 #include <createcontract.h>
2 #include <ui_createcontract.h>
3 #include <platformstyle.h>
4 #include <walletmodel.h>
5 #include <clientmodel.h>
6 #include <guiconstants.h>
7 #include <rpcconsole.h>
8 #include <execrpccommand.h>
9 #include <fabcoinunits.h>
10 #include <optionsmodel.h>
11 #include <validation.h>
12 #include <utilmoneystr.h>
13 #include <addressfield.h>
14 #include <abifunctionfield.h>
15 #include <contractabi.h>
16 #include <tabbarinfo.h>
17 #include <contractresult.h>
18 #include <sendcoinsdialog.h>
19 #include <styleSheet.h>
20 
21 #include <QRegularExpressionValidator>
22 
24 {
25 // Contract data names
26 static const QString PRC_COMMAND = "createcontract";
27 static const QString PARAM_BYTECODE = "bytecode";
28 static const QString PARAM_GASLIMIT = "gaslimit";
29 static const QString PARAM_GASPRICE = "gasprice";
30 static const QString PARAM_SENDER = "sender";
31 
32 static const CAmount SINGLE_STEP = 0.00000001*COIN;
33 static const CAmount HIGH_GASPRICE = 0.001*COIN;
34 }
35 using namespace CreateContract_NS;
36 
37 CreateContract::CreateContract(const PlatformStyle *platformStyle, QWidget *parent) :
38  QWidget(parent),
39  ui(new Ui::CreateContract),
40  m_model(0),
41  m_clientModel(0),
42  m_execRPCCommand(0),
43  m_ABIFunctionField(0),
44  m_contractABI(0),
45  m_tabInfo(0),
46  m_results(1)
47 {
48  // Setup ui components
49  Q_UNUSED(platformStyle);
50  ui->setupUi(this);
51 
52  // Set stylesheet
53  SetObjectStyleSheet(ui->pushButtonClearAll, StyleSheetNames::ButtonBlack);
54 
55  setLinkLabels();
58  ui->labelBytecode->setToolTip(tr("The bytecode of the contract"));
59  ui->labelSenderAddress->setToolTip(tr("The quantum address that will be used to create the contract."));
60 
62  m_tabInfo->addTab(0, tr("Create Contract"));
63 
64  // Set defaults
65  ui->lineEditGasPrice->setValue(DEFAULT_GAS_PRICE);
66  ui->lineEditGasPrice->setSingleStep(SINGLE_STEP);
67  ui->lineEditGasLimit->setMinimum(MINIMUM_GAS_LIMIT);
68  ui->lineEditGasLimit->setMaximum(DEFAULT_GAS_LIMIT_OP_CREATE);
69  ui->lineEditGasLimit->setValue(DEFAULT_GAS_LIMIT_OP_CREATE);
70  ui->pushButtonCreateContract->setEnabled(false);
71 
72  // Create new PRC command line interface
73  QStringList lstMandatory;
74  lstMandatory.append(PARAM_BYTECODE);
75  QStringList lstOptional;
76  lstOptional.append(PARAM_GASLIMIT);
77  lstOptional.append(PARAM_GASPRICE);
78  lstOptional.append(PARAM_SENDER);
79  QMap<QString, QString> lstTranslations;
80  lstTranslations[PARAM_BYTECODE] = ui->labelBytecode->text();
81  lstTranslations[PARAM_GASLIMIT] = ui->labelGasLimit->text();
82  lstTranslations[PARAM_GASPRICE] = ui->labelGasPrice->text();
83  lstTranslations[PARAM_SENDER] = ui->labelSenderAddress->text();
84  m_execRPCCommand = new ExecRPCCommand(PRC_COMMAND, lstMandatory, lstOptional, lstTranslations, this);
85  m_contractABI = new ContractABI();
86 
87  // Connect signals with slots
88  connect(ui->pushButtonClearAll, SIGNAL(clicked()), SLOT(on_clearAllClicked()));
89  connect(ui->pushButtonCreateContract, SIGNAL(clicked()), SLOT(on_createContractClicked()));
90  connect(ui->textEditBytecode, SIGNAL(textChanged()), SLOT(on_updateCreateButton()));
91  connect(ui->textEditInterface, SIGNAL(textChanged()), SLOT(on_newContractABI()));
92  connect(ui->stackedWidget, SIGNAL(currentChanged(int)), SLOT(on_updateCreateButton()));
93 
94  // Set bytecode validator
95  QRegularExpression regEx;
96  regEx.setPattern(paternHex);
97  QRegularExpressionValidator *bytecodeValidator = new QRegularExpressionValidator(ui->textEditBytecode);
98  bytecodeValidator->setRegularExpression(regEx);
99  ui->textEditBytecode->setCheckValidator(bytecodeValidator);
100 }
101 
103 {
104  delete m_contractABI;
105  delete ui;
106 }
107 
109 {
110  ui->labelSolidity->setOpenExternalLinks(true);
111  ui->labelSolidity->setText("<a href=\"https://ethereum.github.io/browser-solidity/\">Solidity compiler</a>");
112 
113  ui->labelToken->setOpenExternalLinks(true);
114  ui->labelToken->setText("<a href=\"https://ethereum.org/token#the-code\">Token template</a>");
115 }
116 
118 {
119  m_model = _model;
120 }
121 
123 {
125  return ui->textEditBytecode->isValid();
126 }
127 
129 {
131  return ui->textEditInterface->isValid();
132 }
133 
135 {
136  bool dataValid = true;
138  bool funcValid = func == -1 ? true : m_ABIFunctionField->isValid();
139 
140  if(!isValidBytecode())
141  dataValid = false;
142  if(!isValidInterfaceABI())
143  dataValid = false;
144  if(!funcValid)
145  dataValid = false;
146 
147  return dataValid;
148 }
149 
151 {
152  m_clientModel = _clientModel;
153 
154  if (m_clientModel)
155  {
156  connect(m_clientModel, SIGNAL(tipChanged()), this, SLOT(on_numBlocksChanged()));
158  }
159 }
160 
162 {
164  ui->lineEditGasLimit->setValue(DEFAULT_GAS_LIMIT_OP_CREATE);
165  ui->lineEditGasPrice->setValue(DEFAULT_GAS_PRICE);
166  ui->lineEditSenderAddress->setCurrentIndex(-1);
168  m_tabInfo->clear();
169 }
170 
172 {
173  if(isDataValid())
174  {
176  if(!ctx.isValid())
177  {
178  return;
179  }
180 
181  // Initialize variables
182  QMap<QString, QString> lstParams;
183  QVariant result;
184  QString errorMessage;
185  QString resultJson;
186  int unit = m_model->getOptionsModel()->getDisplayUnit();
187  uint64_t gasLimit = ui->lineEditGasLimit->value();
188  CAmount gasPrice = ui->lineEditGasPrice->value();
190 
191  // Check for high gas price
192  if(gasPrice > HIGH_GASPRICE)
193  {
194  QString message = tr("The Gas Price is too high, are you sure you want to possibly spend a max of %1 for this transaction?");
195  if(QMessageBox::question(this, tr("High Gas price"), message.arg(FabcoinUnits::formatWithUnit(unit, gasLimit * gasPrice))) == QMessageBox::No)
196  return;
197  }
198 
199  // Append params to the list
200  QString bytecode = ui->textEditBytecode->toPlainText() + toDataHex(func, errorMessage);
201  ExecRPCCommand::appendParam(lstParams, PARAM_BYTECODE, bytecode);
202  ExecRPCCommand::appendParam(lstParams, PARAM_GASLIMIT, QString::number(gasLimit));
203  ExecRPCCommand::appendParam(lstParams, PARAM_GASPRICE, FabcoinUnits::format(unit, gasPrice, false, FabcoinUnits::separatorNever));
204  ExecRPCCommand::appendParam(lstParams, PARAM_SENDER, ui->lineEditSenderAddress->currentText());
205 
206  QString questionString = tr("Are you sure you want to create contract? <br />");
207 
208  SendConfirmationDialog confirmationDialog(tr("Confirm contract creation."), questionString, 3, this);
209  confirmationDialog.exec();
210  QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result();
211  if(retval == QMessageBox::Yes)
212  {
213  // Execute RPC command line
214  if(errorMessage.isEmpty() && m_execRPCCommand->exec(lstParams, result, resultJson, errorMessage))
215  {
216  ContractResult *widgetResult = new ContractResult(ui->stackedWidget);
217  widgetResult->setResultData(result, FunctionABI(), QList<QStringList>(), ContractResult::CreateResult);
218  ui->stackedWidget->addWidget(widgetResult);
219  int position = ui->stackedWidget->count() - 1;
220  m_results = position == 1 ? 1 : m_results + 1;
221 
222  m_tabInfo->addTab(position, tr("Result %1").arg(m_results));
223  m_tabInfo->setCurrent(position);
224  }
225  else
226  {
227  QMessageBox::warning(this, tr("Create contract"), errorMessage);
228  }
229  }
230  }
231 }
232 
234 {
235  if(m_clientModel)
236  {
237  uint64_t blockGasLimit = 0;
238  uint64_t minGasPrice = 0;
239  uint64_t nGasPrice = 0;
240  m_clientModel->getGasInfo(blockGasLimit, minGasPrice, nGasPrice);
241 
242  ui->labelGasLimit->setToolTip(tr("Gas limit. Default = %1, Max = %2").arg(DEFAULT_GAS_LIMIT_OP_CREATE).arg(blockGasLimit));
243  ui->labelGasPrice->setToolTip(tr("Gas price: FABCOIN price per gas unit. Default = %1, Min = %2").arg(QString::fromStdString(FormatMoney(DEFAULT_GAS_PRICE))).arg(QString::fromStdString(FormatMoney(minGasPrice))));
244  ui->lineEditGasPrice->setMinimum(minGasPrice);
245  ui->lineEditGasLimit->setMaximum(blockGasLimit);
246 
248  }
249 }
250 
252 {
253  bool enabled = true;
254  if(ui->textEditBytecode->toPlainText().isEmpty())
255  {
256  enabled = false;
257  }
258  enabled &= ui->stackedWidget->currentIndex() == 0;
259 
260  ui->pushButtonCreateContract->setEnabled(enabled);
261 }
262 
264 {
265  std::string json_data = ui->textEditInterface->toPlainText().toStdString();
266  if(!m_contractABI->loads(json_data))
267  {
268  m_contractABI->clean();
270  }
271  else
272  {
274  }
276 
278 }
279 
280 QString CreateContract::toDataHex(int func, QString& errorMessage)
281 {
282  if(func == -1 || m_ABIFunctionField == NULL || m_contractABI == NULL)
283  {
284  return "";
285  }
286 
287  std::string strData;
288  std::vector<std::vector<std::string>> values = m_ABIFunctionField->getValuesVector();
289  FunctionABI function = m_contractABI->functions[func];
290  std::vector<ParameterABI::ErrorType> errors;
291  if(function.abiIn(values, strData, errors))
292  {
293  return QString::fromStdString(strData);
294  }
295  else
296  {
297  errorMessage = function.errorMessage(errors, true);
298  }
299  return "";
300 }
#define SetObjectStyleSheet(object, name)
Definition: styleSheet.h:10
void on_createContractClicked()
ABIFunctionField * m_ABIFunctionField
UnlockContext requestUnlock()
QPushButton * pushButtonCreateContract
void setSingleStep(const CAmount &step)
Set single step in satoshis.
#define paternHex
Definition: contractabi.h:13
void setResultData(QVariant result, FunctionABI function, QList< QStringList > paramValues, ContractTxType type)
void setupUi(QWidget *CreateContract)
QString toDataHex(int func, QString &errorMessage)
void setIsValidManually(bool value)
ExecRPCCommand * m_execRPCCommand
std::vector< FunctionABI > functions
Definition: contractabi.h:205
void on_refresh()
on_refresh Refresh the list of addresses
std::vector< std::vector< std::string > > getValuesVector()
getValuesVector Get params values vector List of all parameters that can be sent to a function...
TabBarInfo * m_tabInfo
bool exec(const QMap< QString, QString > &params, QVariant &result, QString &resultJson, QString &errorMessage)
exec Execute the RPC command
bool addTab(int index, const QString &name)
addTab Add new tab
Definition: tabbarinfo.cpp:14
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit)
bytes abiIn(std::string _id, T const &..._t)
Definition: ABI.h:64
void setContractABI(ContractABI *contractABI)
setContractABI Set the contract ABI (list of functions from the contract)
int64_t CAmount
Amount in lius (Can be negative)
Definition: amount.h:15
QStackedWidget * stackedWidget
QScrollArea * scrollAreaConstructor
void setCurrent(int index)
setCurrent Set current index
Definition: tabbarinfo.cpp:95
QValidatedTextEdit * textEditInterface
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
CreateContract(const PlatformStyle *platformStyle, QWidget *parent=0)
int getSelectedFunction() const
getSelectedFunction Get the ABI for the selected function from the contract
void setClientModel(ClientModel *clientModel)
WalletModel * m_model
QPushButton * pushButtonClearAll
void on_updateCreateButton()
int getDisplayUnit()
Definition: optionsmodel.h:70
void clear()
clear Remove all tabs except the first one which is not closable
Definition: tabbarinfo.cpp:101
Model for Fabcoin network client.
Definition: clientmodel.h:38
std::string FormatMoney(const CAmount &n)
Money parsing/formatting utilities.
QSpinBox * lineEditGasLimit
The ABIFunctionField class ABI functions widget.
void on_numBlocksChanged()
void setCheckValidator(const QValidator *v)
void setValue(const CAmount &value)
QValidatedTextEdit * textEditBytecode
ClientModel * m_clientModel
The ExecRPCCommand class Execution of RPC command line.
ContractABI * m_contractABI
Interface to Fabcoin wallet from Qt view code.
Definition: walletmodel.h:103
virtual QString currentText() const
currentText Get the current text
bool isValidInterfaceABI()
The TabBarInfo class Class for informations about tabs.
Definition: tabbarinfo.h:13
static void appendParam(QMap< QString, QString > &params, const QString &paramName, const QString &paramValue)
appendParam Append paramether to the list
bool loads(const std::string &json_data)
Definition: contractabi.cpp:54
Ui::CreateContract * ui
void setModel(WalletModel *model)
AddressField * lineEditSenderAddress
void setMinimum(const CAmount &min)
FabcoinAmountField * lineEditGasPrice
OptionsModel * getOptionsModel()
void getGasInfo(uint64_t &blockGasLimit, uint64_t &minGasPrice, uint64_t &nGasPrice) const
Get the information about the needed gas.