From e568c02be81daff5add261336348180c42184294 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 26 Feb 2014 10:47:20 +0000 Subject: [PATCH] Walleth work. --- walleth/Main.ui | 2 +- walleth/MainWin.cpp | 106 +++++++++++++++++++++++++++++++++----------- walleth/MainWin.h | 90 +++++++++++++++++++++++++++++++++++-- walleth/Simple.qml | 5 +-- 4 files changed, 170 insertions(+), 33 deletions(-) diff --git a/walleth/Main.ui b/walleth/Main.ui index 459aa8887..6904590a8 100644 --- a/walleth/Main.ui +++ b/walleth/Main.ui @@ -11,7 +11,7 @@ - AlethZero Ethereum Client + Walleth true diff --git a/walleth/MainWin.cpp b/walleth/MainWin.cpp index 2f298c1f0..79ec09b0f 100644 --- a/walleth/MainWin.cpp +++ b/walleth/MainWin.cpp @@ -1,6 +1,8 @@ #include #include -#include +//#include +//#include +#include #include #include #include @@ -8,6 +10,7 @@ #include #include #include +#include #include "MainWin.h" #include "ui_Main.h" using namespace std; @@ -51,21 +54,68 @@ using eth::c_instructionInfo; #define ADD_QUOTES_HELPER(s) #s #define ADD_QUOTES(s) ADD_QUOTES_HELPER(s) +QEthereum::QEthereum(QObject* _p): QObject(_p) +{ + m_client.reset(new Client("Walleth", Address(), eth::getDataDir() + "/Walleth")); + startTimer(200); +} + +QEthereum::~QEthereum() +{ +} + +Address QEthereum::address() const +{ + return m_client->address(); +} + +u256 QEthereum::balance() const +{ + return m_client->postState().balance(address()); +} + +u256 QEthereum::balanceAt(Address _a) const +{ + return m_client->postState().balance(_a); +} + +unsigned QEthereum::peerCount() const +{ + return m_client->peerCount(); +} + +void QEthereum::transact(Secret _secret, Address _dest, u256 _amount) +{ + m_client->transact(_secret, _dest, _amount); +} + +void QEthereum::timerEvent(QTimerEvent *) +{ + if (m_client->changed()) + changed(); +} + Main::Main(QWidget *parent) : QMainWindow(parent), ui(new Ui::Main) { setWindowFlags(Qt::Window); ui->setupUi(this); - m_client.reset(new Client("Walleth")); + + qRegisterMetaType("eth::u256"); + qRegisterMetaType("eth::KeyPair"); + qRegisterMetaType("eth::Secret"); + qRegisterMetaType("eth::Address"); /* ui->librariesView->setModel(m_libraryMan); ui->graphsView->setModel(m_graphMan); setWindowIcon(QIcon(":/Noted.png")); - - qmlRegisterSingletonType("com.llr", 1, 0, "Time", TimelineItem::constructTimeHelper); - qmlRegisterType("com.llr", 1, 0, "Graph"); +*/ + // TODO: Figure out why not working. +// qmlRegisterSingletonType("org.ethereum", 1, 0, "balance", QEthereum::constructU256Helper); +// qmlRegisterSingletonType("org.ethereum", 1, 0, "key", QEthereum::constructKeyHelper); +/* qmlRegisterType("com.llr", 1, 0, "Graph"); qmlRegisterType("com.llr", 1, 0, "CursorGraph"); qmlRegisterType("com.llr", 1, 0, "Interval"); qmlRegisterType("com.llr", 1, 0, "Cursor"); @@ -78,7 +128,13 @@ Main::Main(QWidget *parent) : */ m_view = new QQuickView(); QQmlContext* context = m_view->rootContext(); -// context->setContextProperty("eth", m_eth); + + m_eth = new QEthereum(); + context->setContextProperty("eth", m_eth); + // TODO: should be singletons. + context->setContextProperty("u256", new U256Helper(this)); + context->setContextProperty("key", new KeyHelper(this)); + /* context->setContextProperty("compute", compute()); context->setContextProperty("data", data()); context->setContextProperty("graphs", graphs()); @@ -153,9 +209,9 @@ void Main::writeSettings() s.setValue("idealPeers", m_idealPeers); s.setValue("port", m_port); - if (m_client->peerServer()) + if (m_eth->client()->peerServer()) { - bytes d = m_client->peerServer()->savePeers(); + bytes d = m_eth->client()->peerServer()->savePeers(); m_peers = QByteArray((char*)d.data(), (int)d.size()); } @@ -185,7 +241,7 @@ void Main::readSettings() m_myKeys.append(KeyPair(k)); } } - m_client->setAddress(m_myKeys.back().address()); + m_eth->client()->setAddress(m_myKeys.back().address()); m_peers = s.value("peers").toByteArray(); ui->upnp->setChecked(s.value("upnp", true).toBool()); m_clientName = s.value("clientName", "").toString(); @@ -195,25 +251,25 @@ void Main::readSettings() void Main::refreshNetwork() { - auto ps = m_client->peers(); + auto ps = m_eth->client()->peers(); ui->peerCount->setText(QString::fromStdString(toString(ps.size())) + " peer(s)"); } eth::State const& Main::state() const { - return ui->preview->isChecked() ? m_client->postState() : m_client->state(); + return ui->preview->isChecked() ? m_eth->client()->postState() : m_eth->client()->state(); } void Main::refresh(bool _override) { - m_client->lock(); + m_eth->client()->lock(); auto const& st = state(); - bool c = m_client->changed(); + bool c = m_eth->client()->changed(); if (c || _override) { - auto d = m_client->blockChain().details(); - auto diff = BlockInfo(m_client->blockChain().block()).difficulty; + auto d = m_eth->client()->blockChain().details(); + auto diff = BlockInfo(m_eth->client()->blockChain().block()).difficulty; ui->blockCount->setText(QString("#%1 @%3 T%2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff))); } @@ -228,7 +284,7 @@ void Main::refresh(bool _override) } ui->balance->setText(QString::fromStdString(formatBalance(totalBalance))); } - m_client->unlock(); + m_eth->client()->unlock(); } void Main::on_net_triggered(bool _auto) @@ -237,21 +293,21 @@ void Main::on_net_triggered(bool _auto) if (m_clientName.size()) n += "/" + m_clientName.toStdString(); n += "/" ADD_QUOTES(ETH_BUILD_TYPE) "/" ADD_QUOTES(ETH_BUILD_PLATFORM); - m_client->setClientVersion(n); + m_eth->client()->setClientVersion(n); if (ui->net->isChecked()) { if (_auto) { QString s = m_servers[rand() % m_servers.size()]; - m_client->startNetwork(m_port, s.section(':', 0, 0).toStdString(), s.section(':', 1).toInt(), NodeMode::Full, m_idealPeers, std::string(), ui->upnp->isChecked()); + m_eth->client()->startNetwork(m_port, s.section(':', 0, 0).toStdString(), s.section(':', 1).toInt(), NodeMode::Full, m_idealPeers, std::string(), ui->upnp->isChecked()); } else - m_client->startNetwork(m_port, string(), 0, NodeMode::Full, m_idealPeers, std::string(), ui->upnp->isChecked()); + m_eth->client()->startNetwork(m_port, string(), 0, NodeMode::Full, m_idealPeers, std::string(), ui->upnp->isChecked()); if (m_peers.size()) - m_client->peerServer()->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size())); + m_eth->client()->peerServer()->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size())); } else - m_client->stopNetwork(); + m_eth->client()->stopNetwork(); } void Main::on_connect_triggered() @@ -267,7 +323,7 @@ void Main::on_connect_triggered() { string host = s.section(":", 0, 0).toStdString(); unsigned short port = s.section(":", 1).toInt(); - m_client->connect(host, port); + m_eth->client()->connect(host, port); } } @@ -275,11 +331,11 @@ void Main::on_mine_triggered() { if (ui->mine->isChecked()) { - m_client->setAddress(m_myKeys.last().address()); - m_client->startMining(); + m_eth->client()->setAddress(m_myKeys.last().address()); + m_eth->client()->startMining(); } else - m_client->stopMining(); + m_eth->client()->stopMining(); } void Main::on_create_triggered() diff --git a/walleth/MainWin.h b/walleth/MainWin.h index 045450160..6cb409b63 100644 --- a/walleth/MainWin.h +++ b/walleth/MainWin.h @@ -6,6 +6,7 @@ #include #include #include +using eth::u256; // workaround for Q_PROPERTY which can't handle scoped types. namespace Ui { class Main; @@ -17,10 +18,93 @@ class State; } class QQuickView; +class QEthereum; +class QQmlEngine; +class QJSEngine; -class QEthereum +Q_DECLARE_METATYPE(eth::u256) + +class U256Helper: public QObject +{ + Q_OBJECT + +public: + U256Helper(QObject* _p = nullptr): QObject(_p) {} + + Q_INVOKABLE eth::u256 add(eth::u256 _a, eth::u256 _b) const { return _a + _b; } + Q_INVOKABLE eth::u256 sub(eth::u256 _a, eth::u256 _b) const { return _a - _b; } + Q_INVOKABLE eth::u256 mul(eth::u256 _a, int _b) const { return _a * _b; } + Q_INVOKABLE eth::u256 mul(int _a, eth::u256 _b) const { return _a * _b; } + Q_INVOKABLE eth::u256 div(eth::u256 _a, int _b) const { return _a / _b; } + + Q_INVOKABLE eth::u256 wei(double _s) const { return (eth::u256)_s; } + Q_INVOKABLE eth::u256 szabo(double _s) const { return (eth::u256)(_s * (double)eth::szabo); } + Q_INVOKABLE eth::u256 finney(double _s) const { return (eth::u256)(_s * (double)eth::finney); } + Q_INVOKABLE eth::u256 ether(double _s) const { return (eth::u256)(_s * (double)eth::ether); } + Q_INVOKABLE eth::u256 wei(unsigned _s) const { return (eth::u256)_s; } + Q_INVOKABLE eth::u256 szabo(unsigned _s) const { return (eth::u256)(_s * eth::szabo); } + Q_INVOKABLE eth::u256 finney(unsigned _s) const { return (eth::u256)(_s * eth::finney); } + Q_INVOKABLE eth::u256 ether(unsigned _s) const { return (eth::u256)(_s * eth::ether); } + Q_INVOKABLE double toWei(eth::u256 _t) const { return (double)_t; } + Q_INVOKABLE double toSzabo(eth::u256 _t) const { return toWei(_t) / (double)eth::szabo; } + Q_INVOKABLE double toFinney(eth::u256 _t) const { return toWei(_t) / (double)eth::finney; } + Q_INVOKABLE double toEther(eth::u256 _t) const { return toWei(_t) / (double)eth::ether; } + + Q_INVOKABLE QString toString(eth::u256 _t) const { return QString::fromStdString(eth::formatBalance(_t)); } + + Q_INVOKABLE QString test() const { return "Hello"; } +}; + +class KeyHelper: public QObject { + Q_OBJECT +public: + KeyHelper(QObject* _p = nullptr): QObject(_p) {} + + Q_INVOKABLE eth::KeyPair create() const { return eth::KeyPair::create(); } + Q_INVOKABLE eth::Address address(eth::KeyPair _p) const { return _p.address(); } + Q_INVOKABLE eth::Secret secret(eth::KeyPair _p) const { return _p.secret(); } + Q_INVOKABLE eth::KeyPair keypair(eth::Secret _k) const { return eth::KeyPair(_k); } + + Q_INVOKABLE eth::Address fromString(QString _s) const { return eth::Address(_s.toStdString()); } + Q_INVOKABLE QString toString(eth::Address _a) const { return QString::fromStdString(eth::asHex(_a.asArray())); } + Q_INVOKABLE QString toAbridged(eth::Address _a) const { return QString::fromStdString(_a.abridged()); } +}; + +class QEthereum: public QObject +{ + Q_OBJECT + +public: + QEthereum(QObject* _p = nullptr); + virtual ~QEthereum(); + + eth::Client* client() const { return m_client.get(); } + + static QObject* constructU256Helper(QQmlEngine*, QJSEngine*) { return new U256Helper; } + static QObject* constructKeyHelper(QQmlEngine*, QJSEngine*) { return new KeyHelper; } + + eth::u256 balance() const; + + Q_INVOKABLE eth::Address address() const; + Q_INVOKABLE eth::u256 balanceAt(eth::Address _a) const; + + Q_INVOKABLE unsigned peerCount() const; + +public slots: + void transact(eth::Secret _secret, eth::Address _dest, eth::u256 _amount); + +signals: + void changed(); + +protected: + virtual void timerEvent(QTimerEvent *); + +private: + Q_PROPERTY(eth::u256 balance READ balance NOTIFY changed) + + std::unique_ptr m_client; }; class Main : public QMainWindow @@ -60,8 +144,6 @@ private: std::unique_ptr ui; - std::unique_ptr m_client; - QByteArray m_peers; QMutex m_guiLock; QTimer* m_refresh; @@ -77,7 +159,7 @@ private: QNetworkAccessManager m_webCtrl; - QEthereum m_eth; + QEthereum* m_eth; }; #endif // MAIN_H diff --git a/walleth/Simple.qml b/walleth/Simple.qml index e46b2c431..31aaa8b95 100644 --- a/walleth/Simple.qml +++ b/walleth/Simple.qml @@ -1,17 +1,16 @@ import QtQuick 2.1 import QtQuick.Controls 1.0 import QtQuick.Layouts 1.0 +//import org.ethereum 1.0 Item { id: main anchors.fill: parent anchors.margins: 9 Label { - text: "This fills the whole cell" + text: "Balance: " + u256.toWei(eth.balance) + "\nAccount: " + key.toString(eth.account) + "\n" + u256.test() Layout.minimumHeight: 30 Layout.fillHeight: true Layout.fillWidth: true } - - }