mirror of
https://github.com/monero-project/monero-gui.git
synced 2024-12-24 12:39:25 +00:00
GUI cold signing
This commit is contained in:
parent
fd983955b4
commit
15c79df378
10 changed files with 454 additions and 35 deletions
4
main.cpp
4
main.cpp
|
@ -40,6 +40,7 @@
|
|||
#include "Wallet.h"
|
||||
#include "QRCodeImageProvider.h"
|
||||
#include "PendingTransaction.h"
|
||||
#include "UnsignedTransaction.h"
|
||||
#include "TranslationManager.h"
|
||||
#include "TransactionInfo.h"
|
||||
#include "TransactionHistory.h"
|
||||
|
@ -72,6 +73,9 @@ int main(int argc, char *argv[])
|
|||
qmlRegisterUncreatableType<PendingTransaction>("moneroComponents.PendingTransaction", 1, 0, "PendingTransaction",
|
||||
"PendingTransaction can't be instantiated directly");
|
||||
|
||||
qmlRegisterUncreatableType<UnsignedTransaction>("moneroComponents.UnsignedTransaction", 1, 0, "UnsignedTransaction",
|
||||
"UnsignedTransaction can't be instantiated directly");
|
||||
|
||||
qmlRegisterUncreatableType<WalletManager>("moneroComponents.WalletManager", 1, 0, "WalletManager",
|
||||
"WalletManager can't be instantiated directly");
|
||||
|
||||
|
|
64
main.qml
64
main.qml
|
@ -228,6 +228,8 @@ ApplicationWindow {
|
|||
currentWallet = wallet
|
||||
updateSyncing(false)
|
||||
|
||||
viewOnly = currentWallet.viewOnly;
|
||||
|
||||
// connect handlers
|
||||
currentWallet.refreshed.connect(onWalletRefresh)
|
||||
currentWallet.updated.connect(onWalletUpdate)
|
||||
|
@ -293,7 +295,6 @@ ApplicationWindow {
|
|||
|
||||
// wallet opened successfully, subscribing for wallet updates
|
||||
connectWallet(wallet)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -474,7 +475,7 @@ ApplicationWindow {
|
|||
|
||||
|
||||
// called on "transfer"
|
||||
function handlePayment(address, paymentId, amount, mixinCount, priority, description) {
|
||||
function handlePayment(address, paymentId, amount, mixinCount, priority, description, createFile) {
|
||||
console.log("Creating transaction: ")
|
||||
console.log("\taddress: ", address,
|
||||
", payment_id: ", paymentId,
|
||||
|
@ -522,6 +523,24 @@ ApplicationWindow {
|
|||
currentWallet.createTransactionAsync(address, paymentId, amountxmr, mixinCount, priority);
|
||||
}
|
||||
|
||||
//Choose where to save transaction
|
||||
FileDialog {
|
||||
id: saveTxDialog
|
||||
title: "Please choose a location"
|
||||
folder: "file://" +moneroAccountsDir
|
||||
selectExisting: false;
|
||||
|
||||
onAccepted: {
|
||||
handleTransactionConfirmed()
|
||||
}
|
||||
onRejected: {
|
||||
// do nothing
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function handleSweepUnmixable() {
|
||||
console.log("Creating transaction: ")
|
||||
|
||||
|
@ -562,7 +581,7 @@ ApplicationWindow {
|
|||
}
|
||||
|
||||
// called after user confirms transaction
|
||||
function handleTransactionConfirmed() {
|
||||
function handleTransactionConfirmed(fileName) {
|
||||
// grab transaction.txid before commit, since it clears it.
|
||||
// we actually need to copy it, because QML will incredibly
|
||||
// call the function multiple times when the variable is used
|
||||
|
@ -573,6 +592,20 @@ ApplicationWindow {
|
|||
for (var i = 0; i < txid_org.length; ++i)
|
||||
txid[i] = txid_org[i]
|
||||
|
||||
// View only wallet - we save the tx
|
||||
if(viewOnly && saveTxDialog.fileUrl){
|
||||
// No file specified - abort
|
||||
if(!saveTxDialog.fileUrl) {
|
||||
currentWallet.disposeTransaction(transaction)
|
||||
return;
|
||||
}
|
||||
|
||||
var path = walletManager.urlToLocalPath(saveTxDialog.fileUrl)
|
||||
|
||||
// Store to file
|
||||
transaction.setFilename(path);
|
||||
}
|
||||
|
||||
if (!transaction.commit()) {
|
||||
console.log("Error committing transaction: " + transaction.errorString);
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString
|
||||
|
@ -585,7 +618,7 @@ ApplicationWindow {
|
|||
txid_text += ", "
|
||||
txid_text += txid[i]
|
||||
}
|
||||
informationPopup.text = qsTr("Money sent successfully: %1 transaction(s) ").arg(txid.length) + txid_text + translationManager.emptyString
|
||||
informationPopup.text = (viewOnly)? qsTr("Transaction saved to file: %1").arg(path) : qsTr("Money sent successfully: %1 transaction(s) ").arg(txid.length) + txid_text + translationManager.emptyString
|
||||
informationPopup.icon = StandardIcon.Information
|
||||
if (transactionDescription.length > 0) {
|
||||
for (var i = 0; i < txid.length; ++i)
|
||||
|
@ -771,10 +804,31 @@ ApplicationWindow {
|
|||
id: transactionConfirmationPopup
|
||||
onAccepted: {
|
||||
close();
|
||||
handleTransactionConfirmed()
|
||||
|
||||
// Save transaction to file if view only wallet
|
||||
if(viewOnly) {
|
||||
saveTxDialog.open();
|
||||
return;
|
||||
} else
|
||||
handleTransactionConfirmed()
|
||||
}
|
||||
}
|
||||
|
||||
StandardDialog {
|
||||
id: confirmationDialog
|
||||
property var onAcceptedCallback
|
||||
property var onRejectedCallback
|
||||
onAccepted: {
|
||||
if (onAcceptedCallback)
|
||||
onAcceptedCallback()
|
||||
}
|
||||
onRejected: {
|
||||
if (onRejectedCallback)
|
||||
onRejectedCallback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Open Wallet from file
|
||||
FileDialog {
|
||||
id: fileDialog
|
||||
|
|
|
@ -9,7 +9,7 @@ CONFIG += c++11
|
|||
# cleaning "auto-generated" bitmonero directory on "make distclean"
|
||||
QMAKE_DISTCLEAN += -r $$WALLET_ROOT
|
||||
|
||||
INCLUDEPATH += $$WALLET_ROOT/include \
|
||||
INCLUDEPATH += $$WALLET_ROOT/include \
|
||||
$$PWD/src/libwalletqt \
|
||||
$$PWD/src/QR-Code-generator \
|
||||
$$PWD/src \
|
||||
|
@ -36,7 +36,8 @@ HEADERS += \
|
|||
src/daemon/DaemonManager.h \
|
||||
src/model/AddressBookModel.h \
|
||||
src/libwalletqt/AddressBook.h \
|
||||
src/zxcvbn-c/zxcvbn.h
|
||||
src/zxcvbn-c/zxcvbn.h \
|
||||
src/libwalletqt/UnsignedTransaction.h
|
||||
|
||||
|
||||
SOURCES += main.cpp \
|
||||
|
@ -59,7 +60,8 @@ SOURCES += main.cpp \
|
|||
src/daemon/DaemonManager.cpp \
|
||||
src/model/AddressBookModel.cpp \
|
||||
src/libwalletqt/AddressBook.cpp \
|
||||
src/zxcvbn-c/zxcvbn.c
|
||||
src/zxcvbn-c/zxcvbn.c \
|
||||
src/libwalletqt/UnsignedTransaction.cpp
|
||||
|
||||
lupdate_only {
|
||||
SOURCES = *.qml \
|
||||
|
@ -289,7 +291,8 @@ OTHER_FILES += \
|
|||
$$TRANSLATIONS
|
||||
|
||||
DISTFILES += \
|
||||
notes.txt
|
||||
notes.txt \
|
||||
monero/src/wallet/CMakeLists.txt
|
||||
|
||||
|
||||
# windows application icon
|
||||
|
|
|
@ -92,7 +92,10 @@ Rectangle {
|
|||
|
||||
Item {
|
||||
id: pageRoot
|
||||
anchors.fill: parent
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height:550
|
||||
Label {
|
||||
id: amountLabel
|
||||
anchors.left: parent.left
|
||||
|
@ -381,7 +384,7 @@ Rectangle {
|
|||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
|
||||
enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
|
||||
onClicked: {
|
||||
console.log("Transfer: paymentClicked")
|
||||
var priority = priorityModel.get(priorityDropdown.currentIndex).priority
|
||||
|
@ -395,25 +398,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: sweepUnmixableButton
|
||||
anchors.right: parent.right
|
||||
anchors.top: descriptionLine.bottom
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 17
|
||||
width: 60*2
|
||||
text: qsTr("SWEEP UNMIXABLE") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : true
|
||||
onClicked: {
|
||||
console.log("Transfer: sweepUnmixableClicked")
|
||||
root.sweepUnmixableClicked()
|
||||
|
||||
}
|
||||
}
|
||||
} // pageRoot
|
||||
|
||||
Rectangle {
|
||||
id:desaturate
|
||||
|
@ -422,7 +407,192 @@ Rectangle {
|
|||
opacity: 0.1
|
||||
visible: (pageRoot.enabled)? 0 : 1;
|
||||
}
|
||||
} // Rectangle
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: pageRoot.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 17
|
||||
spacing:10
|
||||
enabled: !viewOnly || pageRoot.enabled
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
id: manageWalletLabel
|
||||
Layout.fillWidth: true
|
||||
color: "#4A4949"
|
||||
text: qsTr("Advanced") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
Layout.topMargin: 20
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: "#DEDEDE"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
StandardButton {
|
||||
id: sweepUnmixableButton
|
||||
text: qsTr("SWEEP UNMIXABLE") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : pageRoot.enabled
|
||||
onClicked: {
|
||||
console.log("Transfer: sweepUnmixableClicked")
|
||||
root.sweepUnmixableClicked()
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: saveTxButton
|
||||
text: qsTr("create tx file") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible: appWindow.viewOnly
|
||||
enabled: pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
|
||||
onClicked: {
|
||||
console.log("Transfer: saveTx Clicked")
|
||||
var priority = priorityModel.get(priorityDropdown.currentIndex).priority
|
||||
console.log("priority: " + priority)
|
||||
console.log("amount: " + amountLine.text)
|
||||
addressLine.text = addressLine.text.trim()
|
||||
paymentIdLine.text = paymentIdLine.text.trim()
|
||||
root.paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, scaleValueToMixinCount(privacyLevelItem.fillLevel),
|
||||
priority, descriptionLine.text)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: signTxButton
|
||||
text: qsTr("sign tx file") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible: !appWindow.viewOnly
|
||||
onClicked: {
|
||||
console.log("Transfer: sign tx clicked")
|
||||
signTxDialog.open();
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: submitTxButton
|
||||
text: qsTr("submit tx file") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible: appWindow.viewOnly
|
||||
enabled: pageRoot.enabled
|
||||
onClicked: {
|
||||
console.log("Transfer: submit tx clicked")
|
||||
submitTxDialog.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//SignTxDialog
|
||||
FileDialog {
|
||||
id: signTxDialog
|
||||
title: "Please choose a file"
|
||||
folder: "file://" +moneroAccountsDir
|
||||
nameFilters: [ "Unsigned transfers (*)"]
|
||||
|
||||
onAccepted: {
|
||||
var path = walletManager.urlToLocalPath(fileUrl);
|
||||
// Load the unsigned tx from file
|
||||
var transaction = currentWallet.loadTxFile(path);
|
||||
|
||||
if (transaction.status !== PendingTransaction.Status_Ok) {
|
||||
console.error("Can't load unsigned transaction: ", transaction.errorString);
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Can't load unsigned transaction: ") + transaction.errorString
|
||||
informationPopup.icon = StandardIcon.Critical
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
// deleting transaction object, we don't want memleaks
|
||||
transaction.destroy();
|
||||
} else {
|
||||
confirmationDialog.text = qsTr("\nNumber of transactions: ") + transaction.txCount
|
||||
for (var i = 0; i < transaction.txCount; ++i) {
|
||||
confirmationDialog.text += qsTr("\nTransaction #%1").arg(i+1)
|
||||
+qsTr("\nRecipient: ") + transaction.recipientAddress[i]
|
||||
+ (transaction.paymentId[i] == "" ? "" : qsTr("\n\payment ID: ") + transaction.paymentId[i])
|
||||
+ qsTr("\nAmount: ") + walletManager.displayAmount(transaction.amount(i))
|
||||
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee(i))
|
||||
+ qsTr("\nMixin: ") + transaction.mixin(i)
|
||||
|
||||
// TODO: add descriptions to unsigned_tx_set?
|
||||
// + (transactionDescription === "" ? "" : (qsTr("\n\nDescription: ") + transactionDescription))
|
||||
+ translationManager.emptyString
|
||||
if (i > 0) {
|
||||
confirmationDialog.text += "\n\n"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
console.log(transaction.confirmationMessage);
|
||||
|
||||
// Show confirmation dialog
|
||||
confirmationDialog.title = qsTr("Confirmation") + translationManager.emptyString
|
||||
confirmationDialog.icon = StandardIcon.Question
|
||||
confirmationDialog.onAcceptedCallback = function() {
|
||||
transaction.sign(path+"_signed");
|
||||
transaction.destroy();
|
||||
};
|
||||
confirmationDialog.onRejectedCallback = transaction.destroy;
|
||||
|
||||
confirmationDialog.open()
|
||||
}
|
||||
|
||||
}
|
||||
onRejected: {
|
||||
// File dialog closed
|
||||
console.log("Canceled")
|
||||
}
|
||||
}
|
||||
|
||||
//SignTxDialog
|
||||
FileDialog {
|
||||
id: submitTxDialog
|
||||
title: "Please choose a file"
|
||||
folder: "file://" +moneroAccountsDir
|
||||
nameFilters: [ "signed transfers (*)"]
|
||||
|
||||
onAccepted: {
|
||||
if(!currentWallet.submitTxFile(walletManager.urlToLocalPath(fileUrl))){
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Can't submit transaction: ") + currentWallet.errorString
|
||||
informationPopup.icon = StandardIcon.Critical
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
} else {
|
||||
informationPopup.title = qsTr("Information") + translationManager.emptyString
|
||||
informationPopup.text = qsTr("Money sent successfully") + translationManager.emptyString
|
||||
informationPopup.icon = StandardIcon.Information
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
}
|
||||
}
|
||||
onRejected: {
|
||||
console.log("Canceled")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
x: root.width/2 - width/2
|
||||
|
@ -465,9 +635,10 @@ Rectangle {
|
|||
}
|
||||
|
||||
if (currentWallet.viewOnly) {
|
||||
statusText.text = qsTr("Wallet is view only.")
|
||||
return;
|
||||
// statusText.text = qsTr("Wallet is view only.")
|
||||
//return;
|
||||
}
|
||||
pageRoot.enabled = false;
|
||||
|
||||
switch (currentWallet.connected) {
|
||||
case Wallet.ConnectionStatus_Disconnected:
|
||||
|
|
|
@ -13,7 +13,10 @@ QString PendingTransaction::errorString() const
|
|||
|
||||
bool PendingTransaction::commit()
|
||||
{
|
||||
return m_pimpl->commit();
|
||||
// Save transaction to file if fileName is set.
|
||||
if(!m_fileName.isEmpty())
|
||||
return m_pimpl->commit(m_fileName.toStdString());
|
||||
return m_pimpl->commit(m_fileName.toStdString());
|
||||
}
|
||||
|
||||
quint64 PendingTransaction::amount() const
|
||||
|
@ -47,6 +50,11 @@ quint64 PendingTransaction::txCount() const
|
|||
return m_pimpl->txCount();
|
||||
}
|
||||
|
||||
void PendingTransaction::setFilename(const QString &fileName)
|
||||
{
|
||||
m_fileName = fileName;
|
||||
}
|
||||
|
||||
PendingTransaction::PendingTransaction(Monero::PendingTransaction *pt, QObject *parent)
|
||||
: QObject(parent), m_pimpl(pt)
|
||||
{
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
quint64 fee() const;
|
||||
QStringList txid() const;
|
||||
quint64 txCount() const;
|
||||
Q_INVOKABLE void setFilename(const QString &fileName);
|
||||
|
||||
private:
|
||||
explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = 0);
|
||||
|
@ -51,6 +52,7 @@ private:
|
|||
private:
|
||||
friend class Wallet;
|
||||
Monero::PendingTransaction * m_pimpl;
|
||||
QString m_fileName;
|
||||
};
|
||||
|
||||
#endif // PENDINGTRANSACTION_H
|
||||
|
|
89
src/libwalletqt/UnsignedTransaction.cpp
Normal file
89
src/libwalletqt/UnsignedTransaction.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include "UnsignedTransaction.h"
|
||||
#include <QVector>
|
||||
#include <QDebug>
|
||||
|
||||
UnsignedTransaction::Status UnsignedTransaction::status() const
|
||||
{
|
||||
return static_cast<Status>(m_pimpl->status());
|
||||
}
|
||||
|
||||
QString UnsignedTransaction::errorString() const
|
||||
{
|
||||
return QString::fromStdString(m_pimpl->errorString());
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::amount(int index) const
|
||||
{
|
||||
std::vector<uint64_t> arr = m_pimpl->amount();
|
||||
if(index > arr.size() - 1)
|
||||
return 0;
|
||||
return arr[index];
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::fee(int index) const
|
||||
{
|
||||
std::vector<uint64_t> arr = m_pimpl->fee();
|
||||
if(index > arr.size() - 1)
|
||||
return 0;
|
||||
return arr[index];
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::mixin(int index) const
|
||||
{
|
||||
std::vector<uint64_t> arr = m_pimpl->mixin();
|
||||
if(index > arr.size() - 1)
|
||||
return 0;
|
||||
return arr[index];
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::txCount() const
|
||||
{
|
||||
return m_pimpl->txCount();
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::minMixinCount() const
|
||||
{
|
||||
return m_pimpl->minMixinCount();
|
||||
}
|
||||
|
||||
QString UnsignedTransaction::confirmationMessage() const
|
||||
{
|
||||
return QString::fromStdString(m_pimpl->confirmationMessage());
|
||||
}
|
||||
|
||||
QStringList UnsignedTransaction::paymentId() const
|
||||
{
|
||||
QList<QString> list;
|
||||
for (const auto &t: m_pimpl->paymentId())
|
||||
list.append(QString::fromStdString(t));
|
||||
return list;
|
||||
}
|
||||
|
||||
QStringList UnsignedTransaction::recipientAddress() const
|
||||
{
|
||||
QList<QString> list;
|
||||
for (const auto &t: m_pimpl->recipientAddress())
|
||||
list.append(QString::fromStdString(t));
|
||||
return list;
|
||||
}
|
||||
|
||||
bool UnsignedTransaction::sign(const QString &fileName) const
|
||||
{
|
||||
return m_pimpl->sign(fileName.toStdString());
|
||||
}
|
||||
|
||||
void UnsignedTransaction::setFilename(const QString &fileName)
|
||||
{
|
||||
m_fileName = fileName;
|
||||
}
|
||||
|
||||
UnsignedTransaction::UnsignedTransaction(Monero::UnsignedTransaction *pt, QObject *parent)
|
||||
: QObject(parent), m_pimpl(pt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
UnsignedTransaction::~UnsignedTransaction()
|
||||
{
|
||||
delete m_pimpl;
|
||||
}
|
58
src/libwalletqt/UnsignedTransaction.h
Normal file
58
src/libwalletqt/UnsignedTransaction.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
#ifndef UNSIGNEDTRANSACTION_H
|
||||
#define UNSIGNEDTRANSACTION_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <wallet/wallet2_api.h>
|
||||
|
||||
class UnsignedTransaction : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(Status status READ status)
|
||||
Q_PROPERTY(QString errorString READ errorString)
|
||||
// Q_PROPERTY(QList<qulonglong> amount READ amount)
|
||||
// Q_PROPERTY(QList<qulonglong> fee READ fee)
|
||||
Q_PROPERTY(quint64 txCount READ txCount)
|
||||
Q_PROPERTY(QString confirmationMessage READ confirmationMessage)
|
||||
Q_PROPERTY(QStringList recipientAddress READ recipientAddress)
|
||||
Q_PROPERTY(QStringList paymentId READ paymentId)
|
||||
Q_PROPERTY(quint64 minMixinCount READ minMixinCount)
|
||||
|
||||
public:
|
||||
enum Status {
|
||||
Status_Ok = Monero::UnsignedTransaction::Status_Ok,
|
||||
Status_Error = Monero::UnsignedTransaction::Status_Error,
|
||||
Status_Critical = Monero::UnsignedTransaction::Status_Critical
|
||||
};
|
||||
Q_ENUM(Status)
|
||||
|
||||
enum Priority {
|
||||
Priority_Low = Monero::UnsignedTransaction::Priority_Low,
|
||||
Priority_Medium = Monero::UnsignedTransaction::Priority_Medium,
|
||||
Priority_High = Monero::UnsignedTransaction::Priority_High
|
||||
};
|
||||
Q_ENUM(Priority)
|
||||
|
||||
Status status() const;
|
||||
QString errorString() const;
|
||||
Q_INVOKABLE quint64 amount(int index) const;
|
||||
Q_INVOKABLE quint64 fee(int index) const;
|
||||
Q_INVOKABLE quint64 mixin(int index) const;
|
||||
QStringList recipientAddress() const;
|
||||
QStringList paymentId() const;
|
||||
quint64 txCount() const;
|
||||
QString confirmationMessage() const;
|
||||
quint64 minMixinCount() const;
|
||||
Q_INVOKABLE bool sign(const QString &fileName) const;
|
||||
Q_INVOKABLE void setFilename(const QString &fileName);
|
||||
|
||||
private:
|
||||
explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, QObject *parent = 0);
|
||||
~UnsignedTransaction();
|
||||
private:
|
||||
friend class Wallet;
|
||||
Monero::UnsignedTransaction * m_pimpl;
|
||||
QString m_fileName;
|
||||
};
|
||||
|
||||
#endif // UNSIGNEDTRANSACTION_H
|
|
@ -1,5 +1,6 @@
|
|||
#include "Wallet.h"
|
||||
#include "PendingTransaction.h"
|
||||
#include "UnsignedTransaction.h"
|
||||
#include "TransactionHistory.h"
|
||||
#include "AddressBook.h"
|
||||
#include "model/TransactionHistoryModel.h"
|
||||
|
@ -211,7 +212,6 @@ quint64 Wallet::daemonBlockChainHeight() const
|
|||
|
||||
quint64 Wallet::daemonBlockChainTargetHeight() const
|
||||
{
|
||||
|
||||
if (m_daemonBlockChainTargetHeight == 0
|
||||
|| m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl) {
|
||||
m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight();
|
||||
|
@ -323,12 +323,31 @@ void Wallet::createSweepUnmixableTransactionAsync()
|
|||
});
|
||||
}
|
||||
|
||||
UnsignedTransaction * Wallet::loadTxFile(const QString &fileName)
|
||||
{
|
||||
qDebug() << "Trying to sign " << fileName;
|
||||
Monero::UnsignedTransaction * ptImpl = m_walletImpl->loadUnsignedTx(fileName.toStdString());
|
||||
UnsignedTransaction * result = new UnsignedTransaction(ptImpl, this);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Wallet::submitTxFile(const QString &fileName) const
|
||||
{
|
||||
qDebug() << "Trying to submit " << fileName;
|
||||
return m_walletImpl->submitTransaction(fileName.toStdString());
|
||||
}
|
||||
|
||||
void Wallet::disposeTransaction(PendingTransaction *t)
|
||||
{
|
||||
m_walletImpl->disposeTransaction(t->m_pimpl);
|
||||
delete t;
|
||||
}
|
||||
|
||||
void Wallet::disposeTransaction(UnsignedTransaction *t)
|
||||
{
|
||||
delete t;
|
||||
}
|
||||
|
||||
TransactionHistory *Wallet::history() const
|
||||
{
|
||||
return m_history;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "wallet/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here;
|
||||
#include "PendingTransaction.h" // we need to have an access to the PendingTransaction::Priority enum here;
|
||||
#include "UnsignedTransaction.h"
|
||||
|
||||
namespace Monero {
|
||||
class Wallet; // forward declaration
|
||||
|
@ -162,9 +163,19 @@ public:
|
|||
//! creates async sweep unmixable transaction
|
||||
Q_INVOKABLE void createSweepUnmixableTransactionAsync();
|
||||
|
||||
//! Sign a transfer from file
|
||||
Q_INVOKABLE UnsignedTransaction * loadTxFile(const QString &fileName);
|
||||
|
||||
//! Submit a transfer from file
|
||||
Q_INVOKABLE bool submitTxFile(const QString &fileName) const;
|
||||
|
||||
|
||||
//! deletes transaction and frees memory
|
||||
Q_INVOKABLE void disposeTransaction(PendingTransaction * t);
|
||||
|
||||
//! deletes unsigned transaction and frees memory
|
||||
Q_INVOKABLE void disposeTransaction(UnsignedTransaction * t);
|
||||
|
||||
//! returns transaction history
|
||||
TransactionHistory * history() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue