From 39220456ce7429f3554c965819666138bd3b4ac2 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 23 Nov 2015 10:04:54 -0500 Subject: [PATCH] Remove light_client --- programs/CMakeLists.txt | 5 - programs/light_client/Account.cpp | 137 ----- programs/light_client/Account.hpp | 90 ---- programs/light_client/Asset.cpp | 49 -- programs/light_client/Asset.hpp | 61 --- programs/light_client/Balance.cpp | 36 -- programs/light_client/Balance.hpp | 53 -- programs/light_client/BoostMultiIndex.hpp | 34 -- programs/light_client/CMakeLists.txt | 45 -- programs/light_client/ChainDataModel.cpp | 305 ----------- programs/light_client/ChainDataModel.hpp | 108 ---- programs/light_client/GrapheneApplication.cpp | 138 ----- programs/light_client/GrapheneApplication.hpp | 99 ---- programs/light_client/GrapheneObject.cpp | 23 - programs/light_client/GrapheneObject.hpp | 51 -- programs/light_client/Operations.cpp | 120 ----- programs/light_client/Operations.hpp | 163 ------ programs/light_client/README.md | 11 - programs/light_client/Transaction.cpp | 79 --- programs/light_client/Transaction.hpp | 102 ---- programs/light_client/Wallet.cpp | 480 ------------------ programs/light_client/Wallet.hpp | 177 ------- programs/light_client/main.cpp | 92 ---- programs/light_client/qml/.gitignore | 1 - programs/light_client/qml/AccountPicker.qml | 104 ---- programs/light_client/qml/FormBase.qml | 37 -- programs/light_client/qml/FormBox.qml | 154 ------ programs/light_client/qml/FormFlipper.qml | 52 -- programs/light_client/qml/Identicon.qml | 68 --- programs/light_client/qml/Scaling.qml | 12 - programs/light_client/qml/TooltipArea.qml | 23 - .../qml/TransactionConfirmationForm.qml | 105 ---- .../light_client/qml/TransactionDelegate.qml | 42 -- programs/light_client/qml/TransferForm.qml | 130 ----- .../qml/TransferOperationDelegate.qml | 59 --- .../qml/UnlockingFinishButtons.qml | 54 -- .../qml/jdenticon/jdenticon-1.0.1.min.js | 18 - .../light_client/qml/jdenticon/license.txt | 21 - programs/light_client/qml/main.qml | 207 -------- programs/light_client/qml/qml.qrc | 19 - programs/light_client/qml/qmldir | 1 - 41 files changed, 3565 deletions(-) delete mode 100644 programs/light_client/Account.cpp delete mode 100644 programs/light_client/Account.hpp delete mode 100644 programs/light_client/Asset.cpp delete mode 100644 programs/light_client/Asset.hpp delete mode 100644 programs/light_client/Balance.cpp delete mode 100644 programs/light_client/Balance.hpp delete mode 100644 programs/light_client/BoostMultiIndex.hpp delete mode 100644 programs/light_client/CMakeLists.txt delete mode 100644 programs/light_client/ChainDataModel.cpp delete mode 100644 programs/light_client/ChainDataModel.hpp delete mode 100644 programs/light_client/GrapheneApplication.cpp delete mode 100644 programs/light_client/GrapheneApplication.hpp delete mode 100644 programs/light_client/GrapheneObject.cpp delete mode 100644 programs/light_client/GrapheneObject.hpp delete mode 100644 programs/light_client/Operations.cpp delete mode 100644 programs/light_client/Operations.hpp delete mode 100644 programs/light_client/README.md delete mode 100644 programs/light_client/Transaction.cpp delete mode 100644 programs/light_client/Transaction.hpp delete mode 100644 programs/light_client/Wallet.cpp delete mode 100644 programs/light_client/Wallet.hpp delete mode 100644 programs/light_client/main.cpp delete mode 100644 programs/light_client/qml/.gitignore delete mode 100644 programs/light_client/qml/AccountPicker.qml delete mode 100644 programs/light_client/qml/FormBase.qml delete mode 100644 programs/light_client/qml/FormBox.qml delete mode 100644 programs/light_client/qml/FormFlipper.qml delete mode 100644 programs/light_client/qml/Identicon.qml delete mode 100644 programs/light_client/qml/Scaling.qml delete mode 100644 programs/light_client/qml/TooltipArea.qml delete mode 100644 programs/light_client/qml/TransactionConfirmationForm.qml delete mode 100644 programs/light_client/qml/TransactionDelegate.qml delete mode 100644 programs/light_client/qml/TransferForm.qml delete mode 100644 programs/light_client/qml/TransferOperationDelegate.qml delete mode 100644 programs/light_client/qml/UnlockingFinishButtons.qml delete mode 100755 programs/light_client/qml/jdenticon/jdenticon-1.0.1.min.js delete mode 100755 programs/light_client/qml/jdenticon/license.txt delete mode 100644 programs/light_client/qml/main.qml delete mode 100644 programs/light_client/qml/qml.qrc delete mode 100644 programs/light_client/qml/qmldir diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt index 96774a5d..4dee4f68 100644 --- a/programs/CMakeLists.txt +++ b/programs/CMakeLists.txt @@ -4,8 +4,3 @@ add_subdirectory( witness_node ) add_subdirectory( delayed_node ) add_subdirectory( js_operation_serializer ) add_subdirectory( size_checker ) - -set(BUILD_QT_GUI FALSE CACHE BOOL "Build the Qt-based light client GUI") -if(BUILD_QT_GUI) -# add_subdirectory(light_client) -endif() diff --git a/programs/light_client/Account.cpp b/programs/light_client/Account.cpp deleted file mode 100644 index 5ff6656f..00000000 --- a/programs/light_client/Account.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "Balance.hpp" -#include "ChainDataModel.hpp" -#include "Wallet.hpp" - -#include - -void Account::setAccountObject(const graphene::chain::account_object& obj) -{ - auto oldName = m_account.name; - auto oldMemoKey = memoKey(); - - m_account = obj; - if (oldName != m_account.name) - Q_EMIT nameChanged(); - if (oldMemoKey != memoKey()) - Q_EMIT memoKeyChanged(); - - if (!m_loaded) { - m_loaded = true; - Q_EMIT loaded(); - qDebug() << name() << "loaded."; - } -} - -QString Account::memoKey() const -{ - return toQString(m_account.options.memo_key); -} - -QQmlListProperty Account::balances() -{ - auto count = [](QQmlListProperty* list) { - return reinterpret_cast(list->data)->m_balances.size(); - }; - auto at = [](QQmlListProperty* list, int index) { - return reinterpret_cast(list->data)->m_balances[index]; - }; - - return QQmlListProperty(this, this, count, at); -} - -double Account::getActiveControl(Wallet* w, int depth)const -{ - if (depth >= GRAPHENE_MAX_SIG_CHECK_DEPTH) return 0; - if (m_account.active.num_auths() == 0) return 0; - if (m_account.active.weight_threshold == 0) return 0; - - uint64_t weight = 0; - for (auto& key : m_account.active.key_auths) - { - if (w->hasPrivateKey(toQString(key.first))) weight += key.second; - } - - ChainDataModel* model = qobject_cast(parent()); - for (auto& acnt : m_account.active.account_auths) - { - Account* account = model->getAccount(acnt.first.instance.value); - if (!account->m_loaded) { - QEventLoop el; - connect(account, &Account::loaded, &el, &QEventLoop::quit); - QTimer::singleShot(1000, &el, SLOT(quit())); - el.exec(); - if (!account->m_loaded) - // We don't have this account loaded yet... Oh well, move along - continue; - } - if (account->getActiveControl(w, depth + 1) >= 1.0) - weight += acnt.second; - } - - return double(weight) / double(m_account.active.weight_threshold); -} - -double Account::getOwnerControl(Wallet* w)const -{ - if (m_account.owner.num_auths() == 0) return 0; - if (m_account.owner.weight_threshold == 0) return 0; - uint64_t weight = 0; - for (auto& key : m_account.owner.key_auths) - { - if (w->hasPrivateKey(toQString(key.first))) weight += key.second; - } - - ChainDataModel* model = qobject_cast(parent()); - for (auto& acnt : m_account.owner.account_auths) - { - Account* account = model->getAccount(acnt.first.instance.value); - if (!account->m_loaded) - // We don't have this account loaded yet... Oh well, move along - continue; - if (account->getActiveControl(w) >= 1.0) - weight += acnt.second; - } - - return double(weight) / double(m_account.owner.weight_threshold); -} - -void Account::update(const graphene::chain::account_balance_object& balance) -{ - auto balanceItr = std::find_if(m_balances.begin(), m_balances.end(), - [&balance](Balance* b) { return b->type()->id() == balance.asset_type.instance.value; }); - - if (balanceItr != m_balances.end()) { - ilog("Updating ${a}'s balance: ${b}", ("a", name().toStdString())("b", balance)); - (*balanceItr)->update(balance); - Q_EMIT balancesChanged(); - } else { - ilog("Adding to ${a}'s new balance: ${b}", ("a", name().toStdString())("b", balance)); - Balance* newBalance = new Balance; - newBalance->setParent(this); - auto model = qobject_cast(parent()); - newBalance->setProperty("type", QVariant::fromValue(model->getAsset(balance.asset_type.instance.value))); - newBalance->setProperty("amount", QVariant::fromValue(balance.balance.value)); - m_balances.append(newBalance); - Q_EMIT balancesChanged(); - } -} diff --git a/programs/light_client/Account.hpp b/programs/light_client/Account.hpp deleted file mode 100644 index 75671c79..00000000 --- a/programs/light_client/Account.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once -#pragma GCC diagnostic ignored "-Wunknown-pragmas" - -#include "GrapheneObject.hpp" - -#include -#include - -namespace graphene { namespace chain { -class account_balance_object; -}} - -using graphene::chain::account_object; -using graphene::chain::account_balance_object; - -class Balance; -class Wallet; - -class Account : public GrapheneObject { - Q_OBJECT - - Q_PROPERTY(QString name READ name NOTIFY nameChanged) - Q_PROPERTY(QQmlListProperty balances READ balances NOTIFY balancesChanged) - Q_PROPERTY(QString memoKey READ memoKey NOTIFY memoKeyChanged) - Q_PROPERTY(bool isLoaded MEMBER m_loaded NOTIFY loaded) - - account_object m_account; - QList m_balances; - bool m_loaded = false; - -public: - Account(ObjectId id = -1, QString name = QString(), QObject* parent = nullptr) - : GrapheneObject(id, parent) - { - m_account.name = name.toStdString(); - } - void setAccountObject(const account_object& obj); - const account_object& accountObject()const { - return m_account; - } - - QString name()const { return QString::fromStdString(m_account.name); } - QString memoKey()const; - QQmlListProperty balances(); - - void setBalances(QList balances) { - if (balances != m_balances) { - m_balances = balances; - Q_EMIT balancesChanged(); - } - } - - void update(const account_balance_object& balance); - - /** - * Anything greater than 1.0 means full authority. - * Anything between (0 and 1.0) means partial authority - * 0 means no authority. - * - * @return the percent of direct control the wallet has over the account. - */ - Q_INVOKABLE double getOwnerControl(Wallet* w)const; - Q_INVOKABLE double getActiveControl(Wallet* w , int depth = 0)const; - -Q_SIGNALS: - void nameChanged(); - void balancesChanged(); - void memoKeyChanged(); - void loaded(); -}; diff --git a/programs/light_client/Asset.cpp b/programs/light_client/Asset.cpp deleted file mode 100644 index ea44a13e..00000000 --- a/programs/light_client/Asset.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "Asset.hpp" - -#include - -#include - -QString Asset::formatAmount(qint64 amount) const -{ - graphene::chain::asset_object ao; - ao.precision = m_precision; - return QString::fromStdString(ao.amount_to_string(amount)); -} - -void Asset::update(const graphene::chain::asset_object& asset) -{ - if (asset.id.instance() != id()) - setProperty("id", QVariant::fromValue(asset.id.instance())); - if (asset.symbol != m_symbol.toStdString()) { - m_symbol = QString::fromStdString(asset.symbol); - Q_EMIT symbolChanged(); - } - if (asset.precision != m_precision) { - m_precision = asset.precision; - Q_EMIT precisionChanged(); - } - - if (asset.options.core_exchange_rate != coreExchangeRate) - coreExchangeRate = asset.options.core_exchange_rate; -} diff --git a/programs/light_client/Asset.hpp b/programs/light_client/Asset.hpp deleted file mode 100644 index 8c067049..00000000 --- a/programs/light_client/Asset.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once - -#include "GrapheneObject.hpp" - -#include "graphene/chain/protocol/asset.hpp" - -class Asset : public GrapheneObject { - Q_OBJECT - - Q_PROPERTY(QString symbol MEMBER m_symbol READ symbol NOTIFY symbolChanged) - Q_PROPERTY(quint32 precision MEMBER m_precision NOTIFY precisionChanged) - - QString m_symbol; - quint32 m_precision; - - graphene::chain::price coreExchangeRate; - -public: - Asset(ObjectId id = -1, QString symbol = QString(), quint32 precision = 0, QObject* parent = nullptr) - : GrapheneObject(id, parent), m_symbol(symbol), m_precision(precision) - {} - - QString symbol() const { - return m_symbol; - } - - quint64 precisionPower() const { - quint64 power = 1; - for (int i = 0; i < m_precision; ++i) - power *= 10; - return power; - } - /// Given an amount like 123401, return "1234.01" - Q_INVOKABLE QString formatAmount(qint64 amount) const; - - void update(const graphene::chain::asset_object& asset); - -Q_SIGNALS: - void symbolChanged(); - void precisionChanged(); -}; diff --git a/programs/light_client/Balance.cpp b/programs/light_client/Balance.cpp deleted file mode 100644 index 626186f2..00000000 --- a/programs/light_client/Balance.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "Balance.hpp" -#include "Asset.hpp" - -#include - -qreal Balance::amountReal() const { - return amount / qreal(m_type->precisionPower()); -} - -void Balance::update(const graphene::chain::account_balance_object& update) -{ - if (update.balance != amount) { - amount = update.balance.value; - emit amountChanged(); - } -} diff --git a/programs/light_client/Balance.hpp b/programs/light_client/Balance.hpp deleted file mode 100644 index 61c40eca..00000000 --- a/programs/light_client/Balance.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once -#pragma GCC diagnostic ignored "-Wunknown-pragmas" - -#include "GrapheneObject.hpp" - -namespace graphene { namespace chain { -class account_balance_object; -}} - -class Asset; -class Balance : public GrapheneObject { - Q_OBJECT - - Q_PROPERTY(Asset* type MEMBER m_type READ type NOTIFY typeChanged) - Q_PROPERTY(qint64 amount MEMBER amount NOTIFY amountChanged) - - Asset* m_type; - qint64 amount; - -public: - // This ultimately needs to be replaced with a string equivalent - Q_INVOKABLE qreal amountReal() const; - - Asset* type()const { - return m_type; - } - - void update(const graphene::chain::account_balance_object& update); - -Q_SIGNALS: - void typeChanged(); - void amountChanged(); -}; diff --git a/programs/light_client/BoostMultiIndex.hpp b/programs/light_client/BoostMultiIndex.hpp deleted file mode 100644 index 30bc90d2..00000000 --- a/programs/light_client/BoostMultiIndex.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once - -#include -#include -#include -#include -#include - -using boost::multi_index_container; -using boost::multi_index::indexed_by; -using boost::multi_index::hashed_unique; -using boost::multi_index::tag; -using boost::multi_index::const_mem_fun; -using boost::multi_index::ordered_unique; diff --git a/programs/light_client/CMakeLists.txt b/programs/light_client/CMakeLists.txt deleted file mode 100644 index eac86b39..00000000 --- a/programs/light_client/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -cmake_minimum_required(VERSION 2.8.11) - -project(light_client) - -# Find includes in corresponding build directories -set(CMAKE_INCLUDE_CURRENT_DIR ON) -# Instruct CMake to run moc automatically when needed. -set(CMAKE_AUTOMOC ON) - -find_package(Qt5Core) -find_package(Qt5Widgets) -find_package(Qt5Quick) - -file(GLOB QML qml/*) - -# Skip building QRC in debug mode, since we access the QML files directly on disk in debug mode -if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - qt5_add_resources(QML_QRC qml/qml.qrc) -endif() - -add_executable(light_client - Wallet.cpp - ChainDataModel.cpp - Operations.cpp - GrapheneApplication.cpp - GrapheneObject.cpp - Asset.cpp - Account.cpp - Balance.cpp - Transaction.cpp - main.cpp ${QML_QRC} ${QML}) - -if (CMAKE_VERSION VERSION_LESS 3.0) - add_dependencies(light_client gen_qrc) -endif() - -target_link_libraries(light_client PRIVATE Qt5::Core Qt5::Widgets Qt5::Quick graphene_chain graphene_egenesis_brief graphene_utilities fc graphene_app ) - -install( TARGETS - light_client - - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) diff --git a/programs/light_client/ChainDataModel.cpp b/programs/light_client/ChainDataModel.cpp deleted file mode 100644 index 158edc4a..00000000 --- a/programs/light_client/ChainDataModel.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "ChainDataModel.hpp" -#include "Balance.hpp" -#include "Operations.hpp" -#include "Transaction.hpp" - -#include -#include - -#include - -#include - -using namespace graphene::app; - -template -QString idToString(T id) { - return QString("%1.%2.%3").arg(T::space_id).arg(T::type_id).arg(ObjectId(id.instance)); -} -QString idToString(graphene::db::object_id_type id) { - return QString("%1.%2.%3").arg(id.space(), id.type(), ObjectId(id.instance())); -} - -ChainDataModel::ChainDataModel(fc::thread& t, QObject* parent) - :QObject(parent),m_rpc_thread(&t){} - -void ChainDataModel::setDatabaseAPI(fc::api dbapi) { - m_db_api = dbapi; - m_rpc_thread->async([this] { - m_global_properties = m_db_api->get_global_properties(); - m_db_api->subscribe_to_objects([this](const variant& v) { - m_global_properties = v.as(); - }, {m_global_properties.id}); - - m_dynamic_global_properties = m_db_api->get_dynamic_global_properties(); - m_db_api->subscribe_to_objects([this](const variant& d) { - m_dynamic_global_properties = d.as(); - }, {m_dynamic_global_properties.id}); - - m_chain_properties = m_db_api->get_chain_properties(); - }); -} - -void ChainDataModel::setNetworkAPI(fc::api napi) -{ - m_net_api = napi; -} - -void ChainDataModel::broadcast(Transaction* transaction) -{ - try { - m_net_api->broadcast_transaction_with_callback([transaction](const fc::variant&) { - transaction->setStatus(Transaction::Complete); - }, transaction->internalTransaction()); - transaction->setStatus(Transaction::Pending); - } catch (const fc::exception& e) { - transaction->setStatus(Transaction::Failed); - Q_EMIT exceptionThrown(QString::fromStdString(e.to_string())); - } -} - -Asset* ChainDataModel::getAsset(ObjectId id) -{ - auto& by_id_idx = m_assets.get(); - auto itr = by_id_idx.find(id); - if (itr == by_id_idx.end()) - { - auto result = m_assets.insert(new Asset(id, QString::number(--m_account_query_num), 0, this)); - assert(result.second); - - // Run in RPC thread - m_rpc_thread->async([this,id,result]{ getAssetImpl(idToString(asset_id_type(id)), &*result.first); }); - return *result.first; - } - return *itr; -} - -Asset* ChainDataModel::getAsset(QString symbol) -{ - auto& by_symbol_idx = m_assets.get(); - auto itr = by_symbol_idx.find(symbol); - if (itr == by_symbol_idx.end()) - { - auto result = m_assets.insert(new Asset(--m_account_query_num, symbol, 0, this)); - assert(result.second); - - // Run in RPC thread - m_rpc_thread->async([this,symbol,result](){ getAssetImpl(symbol, &*result.first); }); - return *result.first; - } - return *itr; -} - -QDateTime ChainDataModel::chainTime() const { - return QDateTime::fromTime_t(m_dynamic_global_properties.time.sec_since_epoch()); -} - -void ChainDataModel::processUpdatedObject(const fc::variant& update) -{ - if (update.is_null()) - return; - if (&fc::thread::current() == m_rpc_thread) - { - ilog("Proxying object update to app thread."); - Q_EMIT queueExecute([this,update]{processUpdatedObject(update);}); - return; - } - - idump((update)); - try { - auto id = update.as()["id"].as(); - if (id.space() == protocol_ids) { - switch (id.type()) { - default: - wlog("Update procedure for ${update} is not yet implemented.", ("update", update)); - break; - } - } else if (id.space() == implementation_ids) { - switch (id.type()) { - case impl_account_balance_object_type: { - account_balance_object balance = update.as(); - auto owner = m_accounts.find(balance.owner.instance.value); - if (owner != m_accounts.end()) - (*owner)->update(balance); - else - elog("Got unexpected balance update:\n${u}\nfor an account I don't have.", - ("u", update)); - break; - } - - default: - wlog("Update procedure for ${update} is not yet implemented.", ("update", update)); - break; - } - } else - wlog("Update procedure for ${update} is not yet implemented.", ("update", update)); - } catch (const fc::exception& e) { - elog("Caught exception while updating object: ${e}", ("e", e.to_detail_string())); - } -} - -void ChainDataModel::getAssetImpl(QString assetIdentifier, Asset* const * assetInContainer) -{ - try { - ilog("Fetching asset ${asset}", ("asset", assetIdentifier.toStdString())); - auto result = m_db_api->lookup_asset_symbols({assetIdentifier.toStdString()}); - - // Run in main thread - Q_EMIT queueExecute([this,result,assetInContainer](){ - ilog("Processing result ${r}", ("r", result)); - auto itr = m_assets.iterator_to(*assetInContainer); - - if (result.size() == 0 || !result.front()) { - (*itr)->deleteLater(); - m_assets.erase(itr); - } else { - m_assets.modify(itr, - [=](Asset* a){ - a->setProperty("symbol", QString::fromStdString(result.front()->symbol)); - a->setProperty("id", ObjectId(result.front()->id.instance())); - a->setProperty("precision", result.front()->precision); - }); - } - }); - } - catch ( const fc::exception& e ) - { - Q_EMIT exceptionThrown(QString::fromStdString(e.to_string())); - } -} - -void ChainDataModel::getAccountImpl(QString accountIdentifier, Account* const * accountInContainer) -{ - try { - ilog("Fetching account ${acct}", ("acct", accountIdentifier.toStdString())); - auto result = m_db_api->get_full_accounts([this](const fc::variant& v) { - vector updates = v.as>(); - for (const variant& update : updates) { - if (update.is_object()) - processUpdatedObject(update); - else - elog("Handling object deletions is not yet implemented: ${update}", ("update", update)); - } - // TODO: replace true on the next line with a smarter decision as to whether we need status updates or not - }, {accountIdentifier.toStdString()}, true); - fc::optional accountPackage; - - if (result.count(accountIdentifier.toStdString())) { - accountPackage = result.at(accountIdentifier.toStdString()); - - // Fetch all necessary assets - QList assetsToFetch; - QList assetPlaceholders; - assetsToFetch.reserve(accountPackage->balances.size()); - // Get list of asset IDs the account has a balance in - std::transform(accountPackage->balances.begin(), accountPackage->balances.end(), std::back_inserter(assetsToFetch), - [](const account_balance_object& b) { return b.asset_type; }); - auto function = [this,&assetsToFetch,&assetPlaceholders] { - auto itr = assetsToFetch.begin(); - const auto& assets_by_id = m_assets.get(); - // Filter out assets I already have, create placeholders for the ones I don't. - while (itr != assetsToFetch.end()) { - if (assets_by_id.count(itr->instance)) - itr = assetsToFetch.erase(itr); - else { - assetPlaceholders.push_back(&*m_assets.insert(new Asset(itr->instance, QString(), 0, this)).first); - ++itr; - } - } - }; - QMetaObject::invokeMethod(parent(), "execute", Qt::BlockingQueuedConnection, - Q_ARG(const std::function&, function)); - assert(assetsToFetch.size() == assetPlaceholders.size()); - - // Blocking call to fetch and complete initialization for all the assets - for (int i = 0; i < assetsToFetch.size(); ++i) - getAssetImpl(idToString(assetsToFetch[i]), assetPlaceholders[i]); - } - - // Run in main thread - Q_EMIT queueExecute([this,accountPackage,accountInContainer](){ - ilog("Processing result ${r}", ("r", accountPackage)); - auto itr = m_accounts.iterator_to(*accountInContainer); - - if (!accountPackage.valid()) { - (*itr)->deleteLater(); - m_accounts.erase(itr); - } else { - m_accounts.modify(itr, [this,&accountPackage](Account* a){ - a->setProperty("id", ObjectId(accountPackage->account.id.instance())); - a->setAccountObject(accountPackage->account); - - // Set balances - QList balances; - std::transform(accountPackage->balances.begin(), accountPackage->balances.end(), std::back_inserter(balances), - [this](const account_balance_object& b) { - Balance* bal = new Balance; - bal->setParent(this); - bal->setProperty("amount", QVariant::fromValue(b.balance.value)); - bal->setProperty("type", QVariant::fromValue(getAsset(ObjectId(b.asset_type.instance)))); - return bal; - }); - a->setBalances(balances); - }); - } - }); - } - catch (const fc::exception& e) - { - Q_EMIT exceptionThrown(QString::fromStdString(e.to_string())); - } -} - -Account* ChainDataModel::getAccount(ObjectId id) -{ - auto& by_id_idx = m_accounts.get(); - auto itr = by_id_idx.find(id); - if( itr == by_id_idx.end() ) - { - auto tmp = new Account(id, tr("Account #%1").arg(--m_account_query_num), this); - auto result = m_accounts.insert(tmp); - assert(result.second); - - // Run in RPC thread - m_rpc_thread->async([this, id, result]{getAccountImpl(idToString(account_id_type(id)), &*result.first);}); - return *result.first; - } - return *itr; -} - -Account* ChainDataModel::getAccount(QString name) -{ - auto& by_name_idx = m_accounts.get(); - auto itr = by_name_idx.find(name); - if( itr == by_name_idx.end() ) - { - auto tmp = new Account(--m_account_query_num, name, this); - auto result = m_accounts.insert(tmp); - assert(result.second); - - // Run in RPC thread - m_rpc_thread->async([this, name, result]{getAccountImpl(name, &*result.first);}); - return *result.first; - } - return *itr; -} diff --git a/programs/light_client/ChainDataModel.hpp b/programs/light_client/ChainDataModel.hpp deleted file mode 100644 index a2e74585..00000000 --- a/programs/light_client/ChainDataModel.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once -#pragma GCC diagnostic ignored "-Wunknown-pragmas" - -#include -#include - -#include "BoostMultiIndex.hpp" -#include "Asset.hpp" -#include "Account.hpp" - -#include -#include - -using graphene::chain::by_id; - -namespace fc { -class thread; -} - -struct by_symbol_name; -typedef multi_index_container< - Asset*, - indexed_by< - hashed_unique< tag, const_mem_fun >, - ordered_unique< tag, const_mem_fun > - > -> asset_multi_index_type; - -struct by_account_name; -typedef multi_index_container< - Account*, - indexed_by< - hashed_unique< tag, const_mem_fun >, - ordered_unique< tag, const_mem_fun > - > -> account_multi_index_type; - -class Transaction; -class ChainDataModel : public QObject { - Q_OBJECT - Q_PROPERTY(QDateTime chainTime READ chainTime NOTIFY blockReceived) - - void processUpdatedObject(const fc::variant& update); - - void getAssetImpl(QString assetIdentifier, Asset* const * assetInContainer); - void getAccountImpl(QString accountIdentifier, Account* const * accountInContainer); - -public: - Q_INVOKABLE Account* getAccount(ObjectId id); - Q_INVOKABLE Account* getAccount(QString name); - Q_INVOKABLE Asset* getAsset(ObjectId id); - Q_INVOKABLE Asset* getAsset(QString symbol); - - QDateTime chainTime() const; - - ChainDataModel(){} - ChainDataModel(fc::thread& t, QObject* parent = nullptr); - - void setDatabaseAPI(fc::api dbapi); - void setNetworkAPI(fc::api napi); - - const graphene::chain::global_property_object& global_properties() const { return m_global_properties; } - const graphene::chain::dynamic_global_property_object& dynamic_global_properties() const { return m_dynamic_global_properties; } - const graphene::chain::chain_property_object& chain_properties() const { return m_chain_properties; } - -public Q_SLOTS: - void broadcast(Transaction* transaction); - -Q_SIGNALS: - void queueExecute(const std::function&); - void exceptionThrown(QString message); - void blockReceived(); - -private: - fc::thread* m_rpc_thread = nullptr; - std::string m_api_url; - fc::api m_db_api; - fc::api m_net_api; - - graphene::chain::global_property_object m_global_properties; - graphene::chain::dynamic_global_property_object m_dynamic_global_properties; - graphene::chain::chain_property_object m_chain_properties; - - ObjectId m_account_query_num = -1; - account_multi_index_type m_accounts; - asset_multi_index_type m_assets; -}; - diff --git a/programs/light_client/GrapheneApplication.cpp b/programs/light_client/GrapheneApplication.cpp deleted file mode 100644 index 5062b371..00000000 --- a/programs/light_client/GrapheneApplication.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "GrapheneApplication.hpp" -#include "ChainDataModel.hpp" -#include "Wallet.hpp" -#include "Operations.hpp" -#include "Transaction.hpp" - -#include - -#include - -#include - -using graphene::app::login_api; -using graphene::app::database_api; - -GrapheneApplication::GrapheneApplication(QObject* parent) -:QObject(parent),m_thread("app") -{ - connect(this, &GrapheneApplication::queueExecute, - this, &GrapheneApplication::execute); - - m_model = new ChainDataModel(m_thread, this); - m_operationBuilder = new OperationBuilder(*m_model, this); - m_wallet = new Wallet(this); - - connect(m_model, &ChainDataModel::queueExecute, - this, &GrapheneApplication::execute); - - connect(m_model, &ChainDataModel::exceptionThrown, - this, &GrapheneApplication::exceptionThrown); -} - -GrapheneApplication::~GrapheneApplication() -{ -} - -void GrapheneApplication::setIsConnected(bool v) -{ - if (v != m_isConnected) - { - m_isConnected = v; - Q_EMIT isConnectedChanged(m_isConnected); - } -} - -void GrapheneApplication::start(QString apiurl, QString user, QString pass) -{ - if (!m_thread.is_current()) - { - m_done = m_thread.async([=](){ return start(apiurl, user, pass); }); - return; - } - try { - m_client = std::make_shared(); - ilog("connecting...${s}", ("s",apiurl.toStdString())); - auto con = m_client->connect(apiurl.toStdString()); - m_connectionClosed = con->closed.connect([this]{queueExecute([this]{setIsConnected(false);});}); - auto apic = std::make_shared(*con); - auto remote_api = apic->get_remote_api(1); - auto db_api = apic->get_remote_api(0); - if (!remote_api->login(user.toStdString(), pass.toStdString())) - { - elog("login failed"); - Q_EMIT loginFailed(); - return; - } - auto net_api = remote_api->network_broadcast(); - - ilog("connecting..."); - queueExecute([=](){ - m_model->setDatabaseAPI(db_api); - m_model->setNetworkAPI(net_api); - }); - - queueExecute([=](){ setIsConnected(true); }); - } catch (const fc::exception& e) - { - Q_EMIT exceptionThrown(QString::fromStdString(e.to_string())); - } -} - -QString GrapheneApplication::defaultDataPath() -{ - return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); -} - -Transaction* GrapheneApplication::createTransaction() const -{ - return new Transaction; -} - -void GrapheneApplication::signTransaction(Transaction* transaction) const -{ - if (transaction == nullptr) return; - - auto getActiveAuth = [this](graphene::chain::account_id_type id) { - return &model()->getAccount(id.instance.value)->accountObject().active; - }; - auto getOwnerAuth = [this](graphene::chain::account_id_type id) { - return &model()->getAccount(id.instance.value)->accountObject().owner; - }; - - auto& chainId = model()->chain_properties().chain_id; - auto& trx = transaction->internalTransaction(); - trx.set_reference_block(model()->dynamic_global_properties().head_block_id); - flat_set pubKeys = wallet()->getAvailablePrivateKeys(); - auto requiredKeys = trx.get_required_signatures(chainId, pubKeys, getActiveAuth, getOwnerAuth); - trx.signatures = wallet()->signDigest(trx.digest(), requiredKeys); - idump((trx)); -} - - -Q_SLOT void GrapheneApplication::execute(const std::function& func)const -{ - func(); -} - - diff --git a/programs/light_client/GrapheneApplication.hpp b/programs/light_client/GrapheneApplication.hpp deleted file mode 100644 index 4dc688fd..00000000 --- a/programs/light_client/GrapheneApplication.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once -#pragma GCC diagnostic ignored "-Wunknown-pragmas" - -#include - -#include - -#include - - -namespace fc { namespace http { -class websocket_client; -}} - -class ChainDataModel; -class OperationBuilder; -class OperationBase; -class Transaction; -class Wallet; -class GrapheneApplication : public QObject { - Q_OBJECT - - Q_PROPERTY(ChainDataModel* model READ model CONSTANT) - Q_PROPERTY(OperationBuilder* operationBuilder READ operationBuilder CONSTANT) - Q_PROPERTY(Wallet* wallet READ wallet CONSTANT) - Q_PROPERTY(bool isConnected READ isConnected NOTIFY isConnectedChanged) - - - fc::thread m_thread; - ChainDataModel* m_model = nullptr; - Wallet* m_wallet = nullptr; - OperationBuilder* m_operationBuilder = nullptr; - bool m_isConnected = false; - - boost::signals2::scoped_connection m_connectionClosed; - - std::shared_ptr m_client; - fc::future m_done; - - void setIsConnected(bool v); - -protected Q_SLOTS: - void execute(const std::function&)const; - -public: - GrapheneApplication(QObject* parent = nullptr); - ~GrapheneApplication(); - - Wallet* wallet()const { return m_wallet; } - - ChainDataModel* model() const { - return m_model; - } - OperationBuilder* operationBuilder() const { - return m_operationBuilder; - } - - Q_INVOKABLE void start(QString apiUrl, - QString user, - QString pass); - - bool isConnected() const - { - return m_isConnected; - } - - Q_INVOKABLE static QString defaultDataPath(); - - /// Convenience method to get a Transaction in QML. Caller takes ownership of the new Transaction. - Q_INVOKABLE Transaction* createTransaction() const; - Q_INVOKABLE void signTransaction(Transaction* transaction) const; - -Q_SIGNALS: - void exceptionThrown(QString message); - void loginFailed(); - void isConnectedChanged(bool isConnected); - void queueExecute(const std::function&); -}; - diff --git a/programs/light_client/GrapheneObject.cpp b/programs/light_client/GrapheneObject.cpp deleted file mode 100644 index 89375533..00000000 --- a/programs/light_client/GrapheneObject.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "GrapheneObject.hpp" - -// This space intentionally left blank diff --git a/programs/light_client/GrapheneObject.hpp b/programs/light_client/GrapheneObject.hpp deleted file mode 100644 index 0c4001cd..00000000 --- a/programs/light_client/GrapheneObject.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once -#pragma GCC diagnostic ignored "-Wunknown-pragmas" - -#include - -#include - -using ObjectId = qint64; -Q_DECLARE_METATYPE(ObjectId) - -Q_DECLARE_METATYPE(std::function) - -class GrapheneObject : public QObject -{ - Q_OBJECT - Q_PROPERTY(ObjectId id MEMBER m_id READ id NOTIFY idChanged) - - ObjectId m_id; - -public: - GrapheneObject(ObjectId id = -1, QObject* parent = nullptr) - : QObject(parent), m_id(id) - {} - - ObjectId id() const { - return m_id; - } - -Q_SIGNALS: - void idChanged(); -}; diff --git a/programs/light_client/Operations.cpp b/programs/light_client/Operations.cpp deleted file mode 100644 index 43d00800..00000000 --- a/programs/light_client/Operations.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "Operations.hpp" -#include "Wallet.hpp" - -#include - -#include - -TransferOperation* OperationBuilder::transfer(ObjectId sender, ObjectId receiver, qint64 amount, - ObjectId amountType, QString memo, ObjectId feeType) -{ - try { - TransferOperation* op = new TransferOperation; - op->setSender(sender); - op->setReceiver(receiver); - op->setAmount(amount); - op->setAmountType(amountType); - op->setMemo(memo); - op->setFeeType(feeType); - auto feeParameters = model.global_properties().parameters.current_fees->get(); - op->setFee(op->operation().calculate_fee(feeParameters).value); - return op; - } catch (const fc::exception& e) { - qDebug() << e.to_detail_string().c_str(); - return nullptr; - } -} - -QString TransferOperation::memo() const { - if (!m_op.memo) - return QString::null; - if (memoIsEncrypted()) - return tr("Encrypted Memo"); - QString memo = QString::fromStdString(m_op.memo->get_message({}, {})); - while (memo.endsWith(QChar('\0'))) - memo.chop(1); - return memo; -} - -bool TransferOperation::memoIsEncrypted() const -{ - if (!m_op.memo) - return false; - if (m_op.memo->message.empty()) - return false; - if (m_op.memo->from == public_key_type() && m_op.memo->to == public_key_type()) - return false; - return true; -} - -bool TransferOperation::canEncryptMemo(Wallet* wallet, ChainDataModel* model) const -{ - if (!m_op.memo) return false; - auto pub = model->getAccount(sender())->memoKey(); - if (!wallet->hasPrivateKey(pub)) return false; - return graphene::utilities::wif_to_key(wallet->getPrivateKey(pub).toStdString()).valid(); -} - -bool TransferOperation::canDecryptMemo(Wallet* wallet, ChainDataModel* model) const -{ - if (!m_op.memo) return false; - auto pub = model->getAccount(receiver())->memoKey(); - if (!wallet->hasPrivateKey(pub)) return false; - return graphene::utilities::wif_to_key(wallet->getPrivateKey(pub).toStdString()).valid(); -} - -QString TransferOperation::decryptedMemo(Wallet* wallet, ChainDataModel* model) const -{ - fc::ecc::private_key privateKey; - fc::ecc::public_key publicKey; - - if (canEncryptMemo(wallet, model)) { - privateKey = *graphene::utilities::wif_to_key(wallet->getPrivateKey(model->getAccount(sender())->memoKey()).toStdString()); - publicKey = m_op.memo->to; - } else if (canDecryptMemo(wallet, model)) { - privateKey = *graphene::utilities::wif_to_key(wallet->getPrivateKey(model->getAccount(receiver())->memoKey()).toStdString()); - publicKey = m_op.memo->from; - } else return QString::null; - - return QString::fromStdString(m_op.memo->get_message(privateKey, publicKey)); -} - -void TransferOperation::setMemo(QString memo) { - if (memo == this->memo()) - return; - if (!m_op.memo) - m_op.memo = graphene::chain::memo_data(); - while (memo.size() % 32) - memo.append('\0'); - m_op.memo->set_message({}, {}, memo.toStdString()); - Q_EMIT memoChanged(); -} - -void TransferOperation::encryptMemo(Wallet* wallet, ChainDataModel* model) -{ - if (!canEncryptMemo(wallet, model)) return; - auto privateKey = graphene::utilities::wif_to_key(wallet->getPrivateKey(model->getAccount(sender())->memoKey()).toStdString()); - if (!privateKey) return; - m_op.memo->set_message(*privateKey, public_key_type(model->getAccount(receiver())->memoKey().toStdString()), memo().toStdString()); - Q_EMIT memoChanged(); -} diff --git a/programs/light_client/Operations.hpp b/programs/light_client/Operations.hpp deleted file mode 100644 index 62406753..00000000 --- a/programs/light_client/Operations.hpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once - -#include "ChainDataModel.hpp" - -#include - -#include -#include - -class OperationBase : public QObject { - Q_OBJECT - Q_PROPERTY(OperationType operationType READ operationType CONSTANT STORED false) - -public: - enum OperationType { - TransferOperationType = graphene::chain::operation::tag::value - }; - Q_ENUM(OperationType); - - OperationBase(QObject* parent = nullptr) - : QObject(parent) {} - virtual ~OperationBase() {} - - virtual OperationType operationType() const = 0; - virtual graphene::chain::operation genericOperation() const = 0; -}; -QML_DECLARE_INTERFACE(OperationBase) - -class TransferOperation : public OperationBase { - Q_OBJECT - Q_PROPERTY(qint64 fee READ fee WRITE setFee NOTIFY feeChanged) - Q_PROPERTY(ObjectId feeType READ feeType WRITE setFeeType NOTIFY feeTypeChanged) - Q_PROPERTY(ObjectId sender READ sender WRITE setSender NOTIFY senderChanged) - Q_PROPERTY(ObjectId receiver READ receiver WRITE setReceiver NOTIFY receiverChanged) - Q_PROPERTY(qint64 amount READ amount WRITE setAmount NOTIFY amountChanged) - Q_PROPERTY(ObjectId amountType READ amountType WRITE setAmountType NOTIFY amountTypeChanged) - Q_PROPERTY(QString memo READ memo WRITE setMemo NOTIFY memoChanged) - Q_PROPERTY(bool memoIsEncrypted READ memoIsEncrypted NOTIFY memoChanged) - - graphene::chain::transfer_operation m_op; - -public: - TransferOperation(){} - TransferOperation(const graphene::chain::transfer_operation& op) - : m_op(op) {} - - virtual OperationBase::OperationType operationType() const override { - return OperationBase::TransferOperationType; - } - virtual graphene::chain::operation genericOperation() const override { - return m_op; - } - - qint64 fee() const { return m_op.fee.amount.value; } - ObjectId feeType() const { return m_op.fee.asset_id.instance.value; } - ObjectId sender() const { return m_op.from.instance.value; } - ObjectId receiver() const { return m_op.to.instance.value; } - qint64 amount() const { return m_op.amount.amount.value; } - ObjectId amountType() const { return m_op.amount.asset_id.instance.value; } - /// This does not deal with encrypted memos. The memo stored here is unencrypted. The encryption step must be - /// performed by calling encryptMemo() - QString memo() const; - - bool memoIsEncrypted()const; - Q_INVOKABLE bool canEncryptMemo(Wallet* wallet, ChainDataModel* model) const; - Q_INVOKABLE bool canDecryptMemo(Wallet* wallet, ChainDataModel* model) const; - Q_INVOKABLE QString decryptedMemo(Wallet* wallet, ChainDataModel* model) const; - - const graphene::chain::transfer_operation& operation() const { return m_op; } - graphene::chain::transfer_operation& operation() { return m_op; } - -public Q_SLOTS: - void setFee(qint64 arg) { - if (arg == fee()) - return; - m_op.fee.amount = arg; - Q_EMIT feeChanged(); - } - void setFeeType(ObjectId arg) { - if (arg == feeType()) - return; - m_op.fee.asset_id = arg; - Q_EMIT feeTypeChanged(); - } - void setSender(ObjectId arg) { - if (arg == sender()) - return; - m_op.from = arg; - Q_EMIT senderChanged(); - } - void setReceiver(ObjectId arg) { - if (arg == receiver()) - return; - m_op.to = arg; - Q_EMIT receiverChanged(); - } - void setAmount(qint64 arg) { - if (arg == amount()) - return; - m_op.amount.amount = arg; - Q_EMIT amountChanged(); - } - void setAmountType(ObjectId arg) { - if (arg == amountType()) - return; - m_op.amount.asset_id = arg; - Q_EMIT amountTypeChanged(); - } - /// This does not deal with encrypted memos. The memo stored here is unencrypted. The encryption step must be - /// performed by calling encryptMemo() - void setMemo(QString memo); - void encryptMemo(Wallet* wallet, ChainDataModel* model); - -Q_SIGNALS: - void feeChanged(); - void feeTypeChanged(); - void senderChanged(); - void receiverChanged(); - void amountChanged(); - void amountTypeChanged(); - void memoChanged(); -}; -QML_DECLARE_TYPE(TransferOperation) - -/** - * @brief The OperationBuilder class creates operations which are inspectable by the GUI - * - * @note All operations returned by OperationBuilder are heap allocated on-demand and do not have parents. The caller - * must take ownership of these objects to prevent them from leaking. - */ -class OperationBuilder : public QObject { - Q_OBJECT - - ChainDataModel& model; - -public: - OperationBuilder(ChainDataModel& model, QObject* parent = nullptr) - : QObject(parent), model(model){} - - Q_INVOKABLE TransferOperation* transfer(ObjectId sender, ObjectId receiver, qint64 amount, - ObjectId amountType, QString memo, ObjectId feeType); - -}; diff --git a/programs/light_client/README.md b/programs/light_client/README.md deleted file mode 100644 index 7eb2d2ab..00000000 --- a/programs/light_client/README.md +++ /dev/null @@ -1,11 +0,0 @@ -== Graphene Client GUI == - -This is a Qt-based native GUI client for Graphene blockchains. - -To build this GUI, run cmake with -DBUILD_QT_GUI=ON - -This GUI depends on Qt 5.5 or later. If you do not have Qt 5.5 installed -in the canonical location on your OS (or if your OS does not have a -canonical location for libraries), you can specify the Qt path by running -cmake with -DCMAKE_PREFIX_PATH=/path/to/Qt/5.5/gcc_64 as appropriate for -your environment. diff --git a/programs/light_client/Transaction.cpp b/programs/light_client/Transaction.cpp deleted file mode 100644 index ec1a8487..00000000 --- a/programs/light_client/Transaction.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "Transaction.hpp" -#include "Operations.hpp" - -#include - -struct OperationConverter { - using result_type = OperationBase*; - - OperationBase* operator()(const graphene::chain::transfer_operation& op) const { - auto ret = new TransferOperation(op); - QObject::connect(ret, &QObject::destroyed, []{qDebug("Cleaned up operation");}); - return ret; - } - - template - OperationBase* operator()(const Op&) const { - elog("NYI: OperationConverter for ${type}", ("type", fc::get_typename::name())); - abort(); - } -}; - -QString Transaction::statusString() const -{ - return QMetaEnum::fromType().valueToKey(status()); -} - -QQmlListProperty Transaction::operations() -{ - auto append = [](QQmlListProperty* list, OperationBase* op) { - static_cast(list->data)->appendOperation(op); - }; - auto count = [](QQmlListProperty* list) { - return static_cast(list->data)->operationCount(); - }; - auto at = [](QQmlListProperty* list, int index) { - return static_cast(list->data)->operationAt(index); - }; - auto clear = [](QQmlListProperty* list) { - static_cast(list->data)->clearOperations(); - }; - - return QQmlListProperty(this, this, append, count, at, clear); -} - -OperationBase* Transaction::operationAt(int index) const { - return m_transaction.operations[index].visit(OperationConverter()); -} - -void Transaction::appendOperation(OperationBase* op) -{ - if (op == nullptr) - { - qWarning("Unable to append null operation to transaction"); - return; - } - op->setParent(this); - m_transaction.operations.push_back(op->genericOperation()); - Q_EMIT operationsChanged(); -} diff --git a/programs/light_client/Transaction.hpp b/programs/light_client/Transaction.hpp deleted file mode 100644 index c3c322e4..00000000 --- a/programs/light_client/Transaction.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once -#pragma GCC diagnostic ignored "-Wunknown-pragmas" - -#include - -#include -#include -#include -#include - -class OperationBase; -class Transaction : public QObject { - Q_OBJECT - -public: - enum Status { Unbroadcasted, Pending, Complete, Failed }; - Q_ENUM(Status); - - Status status() const { return m_status; } - QString statusString() const; - QQmlListProperty operations(); - - OperationBase* operationAt(int index) const; - int operationCount() const { - return m_transaction.operations.size(); - } - - graphene::chain::signed_transaction& internalTransaction() { - return m_transaction; - } - - QDateTime expiration() const - { - return QDateTime::fromTime_t(m_transaction.expiration.sec_since_epoch()); - } - -public Q_SLOTS: - void setStatus(Status status) - { - if (status == m_status) - return; - - m_status = status; - qDebug() << status; - emit statusChanged(status); - } - - /** - * @brief Append the operation to the transaction - * @param op The operation to append. This Transaction will take ownership of the operation. - */ - void appendOperation(OperationBase* op); - void clearOperations() { - m_transaction.operations.clear(); - Q_EMIT operationsChanged(); - } - - void setExpiration(QDateTime expiration) - { - fc::time_point_sec exp(expiration.toTime_t()); - if (exp == m_transaction.expiration) - return; - - m_transaction.expiration = exp; - emit expirationChanged(expiration); - } - -signals: - void statusChanged(Status status); - void operationsChanged(); - - void expirationChanged(QDateTime expiration); - -private: - Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged) - Q_PROPERTY(QString statusString READ statusString NOTIFY statusChanged STORED false) - Q_PROPERTY(QQmlListProperty operations READ operations NOTIFY operationsChanged) - Q_PROPERTY(QDateTime expiration READ expiration WRITE setExpiration NOTIFY expirationChanged) - - Status m_status = Unbroadcasted; - graphene::chain::signed_transaction m_transaction; -}; diff --git a/programs/light_client/Wallet.cpp b/programs/light_client/Wallet.cpp deleted file mode 100644 index 7be7be4c..00000000 --- a/programs/light_client/Wallet.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "Transaction.hpp" -#include "Wallet.hpp" - -#include -#include - -#include -#include - -QString toQString(public_key_type k) { return QString::fromStdString(fc::variant(k).as_string()); } - -Wallet::Wallet(QObject* parent) -:QObject(parent) -{ -} - -Wallet::~Wallet() -{ - close(); -} - -bool Wallet::open(QString file_path) -{ - fc::path p(file_path.toStdString()); - if( !fc::exists(p) ) - { - ilog("Unable to open wallet file '${f}'; it does not exist", ("f",p)); - return false; - } - - _data = fc::json::from_file(p).as(); - - for( const auto& key : _data.encrypted_private_keys ) - { - if( key.second.label != string() ) - _label_to_key[QString::fromStdString(key.second.label)] = toQString(key.first); - if( key.second.encrypted_private_key.size() ) - _available_private_keys.insert(key.first); - } - _wallet_file_path = p; - - Q_EMIT isOpenChanged(true); - return true; -} - -bool Wallet::isOpen()const -{ - return _wallet_file_path != fc::path(); -} - -bool Wallet::close() -{ - if( !isOpen() ) return false; - save(); - _wallet_file_path = fc::path(); - Q_EMIT isOpenChanged(false); - return false; -} - -bool Wallet::save() -{ - if( !isOpen() ) return false; - /// TODO: backup existing wallet file first. - fc::json::save_to_file(_data, _wallet_file_path); - return false; -} - -bool Wallet::saveAs(QString file_path) -{ - if( !isOpen() ) return false; - fc::path p(file_path.toStdString()); - if( fc::exists(p) ) return false; - fc::json::save_to_file(_data, _wallet_file_path); - return true; -} - -bool Wallet::create(QString file_path, QString password, QString brain_key) -{ - if( isOpen() ) return false; - if( password == QString() ) return false; - - fc::path p(file_path.toStdString()); - if( fc::exists(p) ) - { - ilog("Unable to create wallet file '${f}' because a file with that name already exists.", ("f",p)); - return false; - } - - if( brain_key == QString() ) - { - auto key = fc::ecc::private_key::generate().get_secret(); - brain_key.fromStdString( fc::variant(key).as_string() ); - } - auto brainkey = brain_key.toStdString(); - auto pw_str = password.toStdString(); - - auto password_hash = fc::sha512::hash(pw_str.c_str(), pw_str.size()); - _decrypted_master_key = fc::sha512::hash(fc::ecc::private_key::generate().get_secret()); - _data.master_key_digest = fc::sha512::hash(_decrypted_master_key); - _data.encrypted_master_key = fc::aes_encrypt(password_hash, fc::raw::pack(_decrypted_master_key)); - - _data.brain_key_digest = fc::sha512::hash(brainkey.c_str(), brainkey.size()); - _data.encrypted_brain_key = fc::aes_encrypt(_decrypted_master_key, fc::raw::pack(brainkey)); - - QFileInfo(file_path).absoluteDir().mkpath("."); - fc::json::save_to_file(_data, p); - _wallet_file_path = p; - ilog("Created wallet file '${f}'", ("f", p)); - - return true; -} - -bool Wallet::loadBrainKey(QString brain_key) -{ - if( !isOpen() ) return false; - - if( brain_key == QString() ) return false; - auto brainkey = brain_key.toStdString(); - - if( _data.brain_key_digest != fc::sha512::hash(brainkey.c_str(), brainkey.size()) ) - return false; - - _brain_key = brain_key; - return true; -} - -bool Wallet::purgeBrainKey() -{ - if( !isOpen() ) return false; - _data.encrypted_brain_key.resize(0); - _brain_key = QString(); - return save(); -} - -bool Wallet::hasBrainKey()const -{ - if( !isOpen() ) return false; - return _brain_key != QString() || _data.encrypted_brain_key.size(); -} - -QString Wallet::getBrainKey() -{ - if( !isOpen() ) return QString(); - if( isLocked() ) return QString(); - - if( _brain_key != QString() ) - return _brain_key; - - auto dec_brain_key = fc::aes_decrypt(_decrypted_master_key, _data.encrypted_brain_key); - auto dec_brain_key_str = fc::raw::unpack(dec_brain_key); - _brain_key.fromStdString(dec_brain_key_str); - return _brain_key; -} - -bool Wallet::isLocked()const -{ - if( !isOpen() ) return true; - return _decrypted_master_key == fc::sha512(); -} -bool Wallet::unlock(QString password) -{ - try { - if( !isLocked() ) return true; - auto pw_str = password.toStdString(); - auto password_hash = fc::sha512::hash(pw_str.c_str(), pw_str.size()); - auto plain_txt = fc::aes_decrypt(password_hash, _data.encrypted_master_key); - _decrypted_master_key = fc::raw::unpack(plain_txt); - if( _data.master_key_digest != fc::sha512::hash(_decrypted_master_key) ) - _decrypted_master_key = fc::sha512(); - - Q_EMIT isLockedChanged(isLocked()); - return !isLocked(); - } catch (const fc::exception& e) { - elog(e.to_detail_string()); - return false; - } -} - -bool Wallet::lock() -{ - if( !isOpen() ) return false; - _brain_key = QString(); - _decrypted_master_key = fc::sha512(); - - Q_EMIT isLockedChanged(isLocked()); - return true; -} -bool Wallet::changePassword(QString new_password) -{ - if( !isOpen() ) return false; - if( isLocked() ) return false; - - auto pw_str = new_password.toStdString(); - auto password_hash = fc::sha512::hash(pw_str.c_str(), pw_str.size()); - _data.encrypted_master_key = fc::aes_encrypt(password_hash, fc::raw::pack(_decrypted_master_key)); - - save(); - - return true; -} -bool Wallet::hasPrivateKey(QString pubkey, bool include_with_brain_key) -{ - auto pub = fc::variant(pubkey.toStdString()).as(); - auto itr = _data.encrypted_private_keys.find(pub); - if( itr == _data.encrypted_private_keys.end() ) - return false; - if( itr->second.encrypted_private_key.size() ) - return true; - if( include_with_brain_key && itr->second.brain_sequence >= 0 ) - { - if( !itr->second.owner ) - return true; - return hasPrivateKey(toQString(*itr->second.owner), include_with_brain_key); - } - return false; -} - -QString Wallet::getPrivateKey(QString pubkey) -{ - if( !isOpen() ) return QString(); - if( isLocked() ) return QString(); - - auto pub = fc::variant(pubkey.toStdString()).as(); - auto itr = _data.encrypted_private_keys.find(pub); - if( itr == _data.encrypted_private_keys.end() ) - return QString(); - if( itr->second.encrypted_private_key.size() == 0 ) - return QString(); - auto plain = fc::aes_decrypt(_decrypted_master_key, itr->second.encrypted_private_key); - return QString::fromStdString(fc::raw::unpack(plain)); -} - -QString Wallet::getPublicKey(QString wif_private_key)const -{ - auto priv = graphene::utilities::wif_to_key(wif_private_key.toStdString()); - if( !priv ) return QString(); - - auto pub = public_key_type(priv->get_public_key()); - - return QString::fromStdString(fc::variant(pub).as_string()); -} - -QString Wallet::getActivePrivateKey(QString owner_pub_key, uint32_t seq) -{ - if( !isOpen() ) return QString(); - if( isLocked() ) return QString(); - - auto owner_wif_private_key = getPrivateKey(owner_pub_key); - if( owner_wif_private_key == QString() ) return QString(); - - auto seed = (owner_wif_private_key + " " + QString::number(seq)).toStdString(); - auto secret = fc::sha256::hash(fc::sha512::hash(seed.c_str(), seed.size())); - - auto wif = graphene::utilities::key_to_wif(secret); - auto priv_key = graphene::utilities::wif_to_key(wif); - if( !priv_key ) return QString(); - - public_key_type active_pub_key(priv_key->get_public_key()); - _data.encrypted_private_keys[active_pub_key].encrypted_private_key = fc::aes_encrypt(_decrypted_master_key, fc::raw::pack(wif)); - _data.encrypted_private_keys[active_pub_key].owner = fc::variant(owner_pub_key.toStdString()).as(); - _data.encrypted_private_keys[active_pub_key].brain_sequence = seq; - _available_private_keys.insert( active_pub_key ); - - return QString::fromStdString(wif); -} - -QString Wallet::getOwnerPrivateKey(uint32_t seq) -{ - if( !isOpen() ) return QString(); - if( isLocked() ) return QString(); - if( !hasBrainKey() ) return QString(); - - auto seed = (getBrainKey() + " " + QString::number(seq)).toStdString(); - - auto secret = fc::sha256::hash(fc::sha512::hash(seed.c_str(), seed.size())); - - auto wif = graphene::utilities::key_to_wif(secret); - auto priv_key = graphene::utilities::wif_to_key(wif); - if( !priv_key ) return QString(); - - public_key_type owner_pub_key(priv_key->get_public_key()); - _data.encrypted_private_keys[owner_pub_key].encrypted_private_key = fc::aes_encrypt(_decrypted_master_key, fc::raw::pack(wif)); - _data.encrypted_private_keys[owner_pub_key].brain_sequence = seq; - _available_private_keys.insert(owner_pub_key); - - return QString::fromStdString(wif); -} - -QString Wallet::getActivePublicKey(QString active_pub, uint32_t seq) -{ - return getPublicKey(getActivePrivateKey(active_pub, seq)); -} - -QString Wallet::getOwnerPublicKey(uint32_t seq) -{ - return getPublicKey(getOwnerPrivateKey(seq)); -} - - -QString Wallet::getKeyLabel(QString pubkey) -{ - if( !isOpen() ) return QString(); - public_key_type key = fc::variant( pubkey.toStdString() ).as(); - auto itr = _data.encrypted_private_keys.find(key); - if( itr == _data.encrypted_private_keys.end() ) - return QString(); - return QString::fromStdString(itr->second.label); -} -/** - * The same label may not be assigned to more than one key, this method will - * fail if a key with the same label already exists. - * - * @return true if the label was set - */ -bool Wallet::setKeyLabel(QString pubkey, QString label) -{ - if( label == QString() ) // clear the label - { - auto pub = fc::variant(pubkey.toStdString()).as(); - auto old_label = _data.encrypted_private_keys[pub].label; - _data.encrypted_private_keys[pub].label = string(); - if( old_label.size() ) - _label_to_key.erase(QString::fromStdString(old_label)); - - return true; - } - - auto itr = _label_to_key.find(label); - if( itr != _label_to_key.end() ) - return false; - - _label_to_key[label] = pubkey; - - auto pub = fc::variant(pubkey.toStdString()).as(); - _data.encrypted_private_keys[pub].label = label.toStdString(); - - return true; -} - - -QList> Wallet::getAllPublicKeys(bool only_if_private)const -{ - QList< QPair> result; - if( !isOpen() ) return result; - - for( const auto& item : _data.encrypted_private_keys ) - { - if( only_if_private && !item.second.encrypted_private_key.size() ) continue; - result.push_back(qMakePair(toQString(item.first), QString::fromStdString(item.second.label))); - } - - return result; -} - -QString Wallet::getPublicKey(QString label) -{ - if( !isOpen() ) return QString::null; - - auto itr = _label_to_key.find(label); - if( itr != _label_to_key.end() ) - return QString::null; - - return itr->second; -} - -/** imports a public key and assigns it a label */ -bool Wallet::importPublicKey(QString pubkey, QString label) -{ - return setKeyLabel(pubkey, label); -} - -/** - * @param wifkey a private key in (WIF) Wallet Import Format - * @pre !isLocked() - **/ -bool Wallet::importPrivateKey(QString wifkey, QString label) -{ - if( !isOpen() ) return false; - if( isLocked() ) return false; - - auto priv = graphene::utilities::wif_to_key(wifkey.toStdString()); - if (!priv) return false; - - auto p = priv->get_public_key(); - auto pub = toQString(p); - importPublicKey(pub, label); - - _data.encrypted_private_keys[p].encrypted_private_key = fc::aes_encrypt(_decrypted_master_key, fc::raw::pack(wifkey.toStdString())); - _available_private_keys.insert(p); - - return true; -} - -/** removes the key, its lablel and its private key */ -bool Wallet::removePublicKey(QString pubkey) -{ - if( !isOpen() ) return false; - auto pub = fc::variant( pubkey.toStdString() ).as(); - _available_private_keys.erase(pub); - - auto itr = _data.encrypted_private_keys.find(pub); - if( itr != _data.encrypted_private_keys.end() ) - { - _label_to_key.erase(QString::fromStdString(itr->second.label)); - _data.encrypted_private_keys.erase(itr); - return true; - } - return false; -} - -/** removes only the private key, keeping the public key and label - * - * @pre isOpen() && !isLocked() - **/ -bool Wallet::removePrivateKey(QString pubkey) -{ - if( !isOpen() ) return false; - if( isLocked() ) return false; - - auto pub = fc::variant(pubkey.toStdString()).as(); - _data.encrypted_private_keys[pub].encrypted_private_key.resize(0); - _available_private_keys.erase(pub); - - return true; -} - -/** - * @pre !isLocked() - */ -vector Wallet::signDigest(const digest_type& d, const set& keys)const -{ - vector result; - if( !isOpen() ) return result; - if( isLocked() ) return result; - - result.reserve( keys.size() ); - - for( const auto& key : keys ) - { - auto itr = _data.encrypted_private_keys.find(key); - if( itr == _data.encrypted_private_keys.end() ) - return vector(); - if( itr->second.encrypted_private_key.size() == 0 ) - return vector(); - - auto plain_wif = fc::aes_decrypt(_decrypted_master_key, itr->second.encrypted_private_key); - auto wif = fc::raw::unpack(plain_wif); - auto priv = graphene::utilities::wif_to_key(wif); - if( !priv ) return vector(); - - result.push_back(priv->sign_compact(d)); - } - - return result; -} - -const flat_set& Wallet::getAvailablePrivateKeys()const -{ - return _available_private_keys; -} diff --git a/programs/light_client/Wallet.hpp b/programs/light_client/Wallet.hpp deleted file mode 100644 index 220805c7..00000000 --- a/programs/light_client/Wallet.hpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#pragma once -#pragma GCC diagnostic ignored "-Wunknown-pragmas" - -#include - -#include -#include -#include -#include - -using std::string; -using std::vector; -using std::set; -using fc::flat_set; -using std::map; -using graphene::chain::public_key_type; -using graphene::chain::digest_type; -using graphene::chain::signature_type; -using fc::optional; - -class Transaction; - -QString toQString(public_key_type k); - -struct key_data -{ - string label; /** unique label assigned to this key */ - /** encrypted as a packed std::string containing a wif private key */ - vector encrypted_private_key; - int32_t brain_sequence = -1; - optional owner; /// if this key was derived from an owner key + sequence -}; - -struct wallet_file -{ - vector encrypted_brain_key; - fc::sha512 brain_key_digest; - vector encrypted_master_key; - fc::sha512 master_key_digest; - map encrypted_private_keys; -}; - - -/** - * @class Wallet - * @brief Securely maintains a set of labeled public and private keys - * - * @note this API is designed for use with QML which does not support exceptions so - * all errors are passed via return values. - */ -class Wallet : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool isOpen READ isOpen NOTIFY isOpenChanged) - Q_PROPERTY(bool isLocked READ isLocked NOTIFY isLockedChanged) - public: - Wallet( QObject* parent = nullptr ); - ~Wallet(); - - Q_INVOKABLE bool open(QString file_path); - Q_INVOKABLE bool close(); - bool isOpen()const; - Q_INVOKABLE bool save(); - Q_INVOKABLE bool saveAs(QString file_path); - Q_INVOKABLE bool create(QString file_path, QString password, QString brain_key = QString()); - - /** required to generate new owner keys */ - Q_INVOKABLE bool loadBrainKey(QString brain_key); - - /** removes brain key to secure owner keys */ - Q_INVOKABLE bool purgeBrainKey(); - Q_INVOKABLE bool hasBrainKey()const; - - /** @pre hasBrainKey() */ - Q_INVOKABLE QString getBrainKey(); - - bool isLocked()const; - Q_INVOKABLE bool unlock(QString password); - Q_INVOKABLE bool lock(); - Q_INVOKABLE bool changePassword(QString new_password); - - /** - * @pre !isLocked(); - * @post save() - * @return WIF private key - */ - Q_INVOKABLE QString getActivePrivateKey(QString owner_public_key, uint32_t sequence); - Q_INVOKABLE QString getActivePublicKey(QString owner_public_key, uint32_t sequence); - - /** - * @pre !isLocked(); - * @pre hasBrainKey(); - * @post save() - * @return WIF private key - */ - Q_INVOKABLE QString getOwnerPrivateKey(uint32_t sequence); - Q_INVOKABLE QString getOwnerPublicKey(uint32_t sequence); - Q_INVOKABLE QString getPublicKey(QString wif_private_key)const; - - Q_INVOKABLE QString getKeyLabel(QString pubkey); - Q_INVOKABLE bool setKeyLabel(QString pubkey, QString label); - Q_INVOKABLE QString getPublicKey(QString label); - Q_INVOKABLE QString getPrivateKey(QString pubkey); - Q_INVOKABLE bool hasPrivateKey(QString pubkey, bool include_with_brain_key = false); - - /** imports a public key and assigns it a label */ - Q_INVOKABLE bool importPublicKey(QString pubkey, QString label = QString()); - - /** - * @param wifkey a private key in (WIF) Wallet Import Format - * @pre !isLocked() - **/ - Q_INVOKABLE bool importPrivateKey(QString wifkey, QString label = QString()); - - /** removes the key, its lablel and its private key */ - Q_INVOKABLE bool removePublicKey(QString pubkey); - - /** removes only the private key, keeping the public key and label */ - Q_INVOKABLE bool removePrivateKey(QString pubkey); - - /** - * @param only_if_private filter any public keys for which the wallet lacks a private key - * @return a list of PUBLICKEY, LABEL for all known public keys - */ - Q_INVOKABLE QList> getAllPublicKeys(bool only_if_private)const; - - /** - * @pre !isLocked() - */ - vector signDigest(const digest_type& d, - const set& keys)const; - - const flat_set& getAvailablePrivateKeys()const; - - Q_SIGNALS: - void isLockedChanged(bool state); - void isOpenChanged(bool state); - - private: - fc::path _wallet_file_path; - wallet_file _data; - /** used to decrypt all of the encrypted private keys */ - fc::sha512 _decrypted_master_key; - flat_set _available_private_keys; - map _label_to_key; - QString _brain_key; -}; -QML_DECLARE_TYPE(Wallet) - -FC_REFLECT( key_data, (label)(encrypted_private_key)(brain_sequence)(owner) ) -FC_REFLECT( wallet_file, - (encrypted_brain_key) - (brain_key_digest) - (encrypted_master_key) - (master_key_digest) - (encrypted_private_keys) - ) diff --git a/programs/light_client/main.cpp b/programs/light_client/main.cpp deleted file mode 100644 index e327f20d..00000000 --- a/programs/light_client/main.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2015 Cryptonomex, Inc., and contributors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Any modified source or binaries are used only with the BitShares network. - * - * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include -#include -#include - -#include "GrapheneApplication.hpp" -#include "ChainDataModel.hpp" -#include "Transaction.hpp" -#include "Operations.hpp" -#include "Balance.hpp" -#include "Wallet.hpp" - -class Crypto { - Q_GADGET - -public: - Q_INVOKABLE QString sha256(QByteArray data) { - return QCryptographicHash::hash(data, QCryptographicHash::Sha256).toHex(); - } -}; -QML_DECLARE_TYPE(Crypto) - -int main(int argc, char *argv[]) -{ -#ifndef NDEBUG - QQmlDebuggingEnabler enabler; -#endif - fc::thread::current().set_name("main"); - QApplication app(argc, argv); - app.setApplicationName("Graphene Client"); - app.setOrganizationDomain("cryptonomex.org"); - app.setOrganizationName("Cryptonomex, Inc."); - - qRegisterMetaType>(); - qRegisterMetaType(); - qRegisterMetaType>(); - qRegisterMetaType(); - - qmlRegisterType("Graphene.Client", 0, 1, "Asset"); - qmlRegisterType("Graphene.Client", 0, 1, "Balance"); - qmlRegisterType("Graphene.Client", 0, 1, "Account"); - qmlRegisterType("Graphene.Client", 0, 1, "DataModel"); - qmlRegisterType("Graphene.Client", 0, 1, "Wallet"); - qmlRegisterType("Graphene.Client", 0, 1, "GrapheneApplication"); - qmlRegisterType("Graphene.Client", 0, 1, "Transaction"); - - qmlRegisterUncreatableType("Graphene.Client", 0, 1, "OperationBase", - "OperationBase is an abstract base class; cannot be created"); - qmlRegisterType("Graphene.Client", 0, 1, "TransferOperation"); - - qmlRegisterUncreatableType("Graphene.Client", 0, 1, "OperationBuilder", - QStringLiteral("OperationBuilder cannot be created from QML")); - - QQmlApplicationEngine engine; - QVariant crypto; - crypto.setValue(Crypto()); - engine.rootContext()->setContextProperty("Crypto", crypto); -#ifdef NDEBUG - engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); -#else - engine.load(QUrl(QStringLiteral("qml/main.qml"))); - QFileSystemWatcher watcher; - qDebug() << watcher.addPath("qml/"); - QObject::connect(&watcher, &QFileSystemWatcher::directoryChanged, &engine, [&](QString path) { - qDebug() << "Changed file" << path; - engine.clearComponentCache(); - }); -#endif - - return app.exec(); -} - -#include "main.moc" diff --git a/programs/light_client/qml/.gitignore b/programs/light_client/qml/.gitignore deleted file mode 100644 index c6593022..00000000 --- a/programs/light_client/qml/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.depends diff --git a/programs/light_client/qml/AccountPicker.qml b/programs/light_client/qml/AccountPicker.qml deleted file mode 100644 index 91ed1dd0..00000000 --- a/programs/light_client/qml/AccountPicker.qml +++ /dev/null @@ -1,104 +0,0 @@ -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Dialogs 1.2 -import QtQuick.Layouts 1.2 - -import Graphene.Client 0.1 - -import "." - -/// A component for choosing an Account from the chain -RowLayout { - property GrapheneApplication app - /// The text to show in the name field when it is empty - property alias placeholderText: accountNameField.placeholderText - /// Index into the balances Array of the balance to show beneath the name field - property int showBalance: -1 - - /// The Account object the user has selected - property Account account - /// A real in the range [0,1] representing the amount of control the wallet has over this account - property real accountControlLevel: account && account.isLoaded? account.getActiveControl(app.wallet) : 0 - /// An Array of Balance objects held by account - property var balances: account? Object.keys(account.balances).map(function(key){return account.balances[key]}) - .filter(function(balance){return balance.amount > 0}) - : null - - /// Set the name field to have active focus - function setFocus() { - accountNameField.forceActiveFocus() - } - - signal balanceClicked(var balance) - - Identicon { - name: account && account.name == accountNameField.text? accountNameField.text : "" - width: Scaling.cm(2) - height: Scaling.cm(2) - showOwnership: accountControlLevel > 0 - fullOwnership: accountControlLevel >= 1 - } - Column { - Layout.fillWidth: true - TextField { - id: accountNameField - width: parent.width - - onEditingFinished: accountDetails.update(text) - onTextChanged: if (account && account.name !== text) accountDetails.update("") - } - Text { - id: accountDetails - width: parent.width - height: text? implicitHeight : 0 - onLinkActivated: if (link === "balance") balanceClicked(balances[showBalance].amountReal()) - - Behavior on height { NumberAnimation{ easing.type: Easing.InOutQuad } } - - function update(name) { - if (!name) - { - text = "" - account = null - return - } - - account = app.model.getAccount(name) - if (account == null) { - text = qsTr("Error fetching account.") - } else { - text = Qt.binding(function() { - if (account == null) - return qsTr("Account does not exist.") - var text = qsTr("Account ID: %1").arg(!account.isLoaded? qsTr("Loading...") - : account.id) - if (showBalance >= 0) { - var bal = balances[showBalance] - text += "
" + qsTr("Balance: %1 %2").arg(String(bal.amountReal())) - .arg(bal.type.symbol) - } - return text - }) - } - } - - Behavior on text { - SequentialAnimation { - PropertyAnimation { - target: accountDetails - property: "opacity" - from: 1; to: 0 - duration: 100 - } - PropertyAction { target: accountDetails; property: "text" } - PropertyAnimation { - target: accountDetails - property: "opacity" - from: 0; to: 1 - duration: 100 - } - } - } - } - } -} diff --git a/programs/light_client/qml/FormBase.qml b/programs/light_client/qml/FormBase.qml deleted file mode 100644 index 2a4936d2..00000000 --- a/programs/light_client/qml/FormBase.qml +++ /dev/null @@ -1,37 +0,0 @@ -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Dialogs 1.2 -import QtQuick.Layouts 1.2 - -import Graphene.Client 0.1 - -import "." - -/** - * Base for all forms - * - * This base contains all of the properties, slots, and signals which all forms are expected to expose. It also - * automatically lays its children out in a ColumnLayout - */ -Rectangle { - anchors.fill: parent - - /// Reference to the GrapheneApplication object - property GrapheneApplication app - /// Parent should trigger this signal to notify the form that it is about to be displayed - /// See specific form for the argument semantics - signal display(var arg) - /// Emitted when the form is canceled -- see specific form for the argument semantics - signal canceled(var arg) - /// Emitted when the form is completed -- see specific form for the argument semantics - signal completed(var arg) - - default property alias childItems: childLayout.data - - ColumnLayout { - id: childLayout - anchors.centerIn: parent - width: parent.width - Scaling.cm(2) - spacing: Scaling.mm(5) - } -} diff --git a/programs/light_client/qml/FormBox.qml b/programs/light_client/qml/FormBox.qml deleted file mode 100644 index 137173aa..00000000 --- a/programs/light_client/qml/FormBox.qml +++ /dev/null @@ -1,154 +0,0 @@ -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Dialogs 1.2 - -Rectangle { - id: greySheet - state: "HIDDEN" - color: Qt.rgba(0, 0, 0, showOpacity) - - property real showOpacity: .5 - property int animationTime: 300 - - /// Emitted immediately when opening, before fade-in animation - signal opening - /// Emitted when opened, following fade-in animation - signal opened - /// Emitted immediately when closing, before fade-out animation - signal closing - /// Emitted when closed, following fade-out animation - signal closed - - function showForm(formType, params, closedCallback) { - if (formType.status === Component.Error) - console.log(formType.errorString()) - if (!params instanceof Object) - params = {app: app} - else - params.app = app - - var form = formType.createObject(formContainer, params) - formContainer.data = [form] - form.canceled.connect(function(){state = "HIDDEN"; internal.callbackArgs = []}) - form.completed.connect(function(){state = "HIDDEN"; internal.callbackArgs = arguments}) - if (closedCallback instanceof Function) - internal.callback = closedCallback - // Notify the form that it's about to go live - form.display({}) - state = "SHOWN" - } - - FocusScope { - id: scope - anchors.fill: parent - - // Do not let focus leave this scope while form is open - onFocusChanged: if (enabled && !focus) forceActiveFocus() - - Keys.onEscapePressed: greySheet.state = "HIDDEN" - - MouseArea { - id: mouseTrap - anchors.fill: parent - onClicked: { - mouse.accepted = true - greySheet.state = "HIDDEN" - } - acceptedButtons: Qt.AllButtons - } - MouseArea { - // This mouse area blocks clicks inside the form from reaching the mouseTrap - anchors.fill: formContainer - acceptedButtons: Qt.AllButtons - onClicked: mouse.accepted = true - } - Item { - id: formContainer - anchors.centerIn: parent - width: parent.width / 2 - height: parent.height / 2 - } - } - - states: [ - State { - name: "HIDDEN" - PropertyChanges { - target: greySheet - opacity: 0 - enabled: false - } - StateChangeScript { - name: "preHidden" - script: { - greySheet.closing() - } - } - StateChangeScript { - name: "postHidden" - script: { - greySheet.closed() - formContainer.data = [] - if (internal.callback instanceof Function) - internal.callback.apply(this, internal.callbackArgs) - internal.callback = undefined - internal.callbackArgs = [] - } - } - }, - State { - name: "SHOWN" - PropertyChanges { - target: greySheet - opacity: 1 - enabled: true - } - StateChangeScript { - name: "preShown" - script: { - greySheet.opening() - } - } - StateChangeScript { - name: "postShown" - script: { - greySheet.opened() - } - } - } - ] - transitions: [ - Transition { - from: "HIDDEN" - to: "SHOWN" - SequentialAnimation { - ScriptAction { scriptName: "preShown" } - PropertyAnimation { - target: greySheet - property: "opacity" - duration: animationTime - } - ScriptAction { scriptName: "postShown" } - } - }, - Transition { - from: "SHOWN" - to: "HIDDEN" - SequentialAnimation { - ScriptAction { scriptName: "preHidden" } - PropertyAnimation { - target: greySheet - property: "opacity" - duration: animationTime - } - ScriptAction { scriptName: "postHidden" } - } - } - ] - - QtObject { - id: internal - property var callback - property var callbackArgs - } -} diff --git a/programs/light_client/qml/FormFlipper.qml b/programs/light_client/qml/FormFlipper.qml deleted file mode 100644 index 923ee6c5..00000000 --- a/programs/light_client/qml/FormFlipper.qml +++ /dev/null @@ -1,52 +0,0 @@ -import QtQuick 2.5 - -import Graphene.Client 0.1 - -Flipable { - id: flipable - anchors.fill: parent - - property Component frontComponent - property Component backComponent - - signal display(var arg) - signal canceled(var arg) - signal completed(var arg) - - property bool flipped: false - - Component.onCompleted: { - back = backComponent.createObject(flipable, {app: app, enabled: Qt.binding(function(){return rotation.angle > 90})}) - front = frontComponent.createObject(flipable, {app: app, enabled: Qt.binding(function(){return rotation.angle < 90})}) - front.canceled.connect(function() { canceled.apply(this, arguments) }) - front.completed.connect(function() { - back.display.apply(this, arguments) - flipped = true - }) - back.canceled.connect(function() { - front.display.apply(this, arguments) - flipped = false - }) - back.completed.connect(function() { completed.apply(this, arguments) }) - } - - transform: Rotation { - id: rotation - origin.x: flipable.width/2 - origin.y: flipable.height/2 - // set axis.y to 1 to rotate around y-axis - axis.x: 0; axis.y: 1; axis.z: 0 - // the default angle - angle: 0 - } - - states: State { - name: "back" - PropertyChanges { target: rotation; angle: 180 } - when: flipable.flipped - } - - transitions: Transition { - NumberAnimation { target: rotation; property: "angle"; duration: 500 } - } -} diff --git a/programs/light_client/qml/Identicon.qml b/programs/light_client/qml/Identicon.qml deleted file mode 100644 index d339c4f4..00000000 --- a/programs/light_client/qml/Identicon.qml +++ /dev/null @@ -1,68 +0,0 @@ -import QtQuick 2.5 - -import "jdenticon/jdenticon-1.0.1.min.js" as Jdenticon - -Canvas { - id: identicon - contextType: "2d" - - property var name - property bool showOwnership: false - property bool fullOwnership: false - - onNameChanged: requestPaint() - - onPaint: { - if (name) - Jdenticon.draw(identicon, name) - else { - var context = identicon.context - if (!context) return - - context.reset() - var draw_circle = function(context, x, y, radius) { - context.beginPath() - context.arc(x, y, radius, 0, 2 * Math.PI, false) - context.fillStyle = "rgba(0, 0, 0, 0.1)" - context.fill() - } - var size = Math.min(identicon.height, identicon.width) - var centerX = size / 2 - var centerY = size / 2 - var radius = size/15 - draw_circle(context, centerX, centerY, radius) - draw_circle(context, 2*radius, 2*radius, radius) - draw_circle(context, centerX, 2*radius, radius) - draw_circle(context, size - 2*radius, 2*radius, radius) - draw_circle(context, size - 2*radius, centerY, radius) - draw_circle(context, size - 2*radius, size - 2*radius, radius) - draw_circle(context, centerX, size - 2*radius, radius) - draw_circle(context, 2*radius, size - 2*radius, radius) - draw_circle(context, 2*radius, centerY, radius) - } - } - - Rectangle { - anchors { - bottom: parent.bottom - left: parent.left - right: parent.right - } - height: parent.height / 4 - color: fullOwnership? "green" : "blue" - opacity: .6 - visible: showOwnership - - Text { - anchors.centerIn: parent - color: "white" - font.pixelSize: parent.height * 2/3 - font.bold: true - text: fullOwnership? qsTr("FULL") : qsTr("PARTIAL") - } - TooltipArea { - text: fullOwnership? qsTr("You have full control of this account, and can use it to perform actions directly.") - : qsTr("You have partial control of this account, and can vote for it to take an action.") - } - } -} diff --git a/programs/light_client/qml/Scaling.qml b/programs/light_client/qml/Scaling.qml deleted file mode 100644 index 52ab128e..00000000 --- a/programs/light_client/qml/Scaling.qml +++ /dev/null @@ -1,12 +0,0 @@ -pragma Singleton -import QtQuick 2.5 -import QtQuick.Window 2.2 - -Item { - function mm(millimeters) { - return Screen.pixelDensity * millimeters - } - function cm(centimeters) { - return mm(centimeters * 10) - } -} diff --git a/programs/light_client/qml/TooltipArea.qml b/programs/light_client/qml/TooltipArea.qml deleted file mode 100644 index 5dda449e..00000000 --- a/programs/light_client/qml/TooltipArea.qml +++ /dev/null @@ -1,23 +0,0 @@ -import QtQuick 2.4 -import QtQuick.Controls.Private 1.0 - -// TooltipArea.qml -// This file contains private Qt Quick modules that might change in future versions of Qt -// Tested on: Qt 5.4.1 - -MouseArea { - id: _root - property string text: "" - - anchors.fill: parent - hoverEnabled: _root.enabled - - onExited: Tooltip.hideText() - onCanceled: Tooltip.hideText() - - Timer { - interval: 1000 - running: _root.enabled && _root.containsMouse && _root.text.length - onTriggered: Tooltip.showText(_root, Qt.point(_root.mouseX, _root.mouseY), _root.text) - } -} diff --git a/programs/light_client/qml/TransactionConfirmationForm.qml b/programs/light_client/qml/TransactionConfirmationForm.qml deleted file mode 100644 index c9e4694f..00000000 --- a/programs/light_client/qml/TransactionConfirmationForm.qml +++ /dev/null @@ -1,105 +0,0 @@ -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Dialogs 1.2 -import QtQuick.Layouts 1.2 -import QtGraphicalEffects 1.0 - -import Graphene.Client 0.1 - -import "." - -/** - * This is the form for previewing and approving a transaction prior to broadcasting it - * - * The arguments property should be populated with an Array of operations. These operations will be used to create a - * Transaction, display it, and get confirmation to sign and broadcast it. This form will populate the transaction with - * the operations and expiration details, sign it, and pass the signed transaction through the completed signal. - */ -FormBase { - id: base - - readonly property alias trx: __trx - - Component.onCompleted: console.log("Made a transaction confirmation form") - Component.onDestruction: console.log("Destroyed a transaction confirmation form") - - onDisplay: { - trx.clearOperations() - for (var op in arg) - trx.appendOperation(arg[op]) - } - - Transaction { - id: __trx - } - - Rectangle { - id: background - Layout.preferredHeight: childrenRect.height + Scaling.mm(4) - Layout.preferredWidth: childrenRect.width + Scaling.mm(4) - layer.enabled: true - layer.effect: DropShadow { - radius: 8.0 - samples: 16 - horizontalOffset: Scaling.mm(.5) - verticalOffset: Scaling.mm(.5) - source: background - color: "#80000000" - transparentBorder: true - } - - // Debugging shim; disable before release - Loader { - id: delegateLoader - x: Scaling.mm(2) - y: Scaling.mm(2) - Layout.preferredWidth: Scaling.cm(10) - Component.onCompleted: setSource("TransactionDelegate.qml", {"trx": __trx, "app": base.app}) - - MouseArea { - anchors.fill: parent - onClicked: { - console.log("Reloading transaction") - delegateLoader.source = "" - delegateLoader.setSource("TransactionDelegate.qml", {"trx": __trx, "app": base.app}) - } - } - } - } - RowLayout { - Label { - text: qsTr("Transaction expires in") - } - ComboBox { - id: expirationSelector - model: [qsTr("five seconds"), qsTr("thirty seconds"), qsTr("a minute"), qsTr("an hour"), qsTr("a month"), qsTr("a year")] - - function getExpiration() { - switch(expirationSelector.currentIndex) { - case 0: return new Date(app.model.chainTime.getTime() + 1000*5) - case 1: return new Date(app.model.chainTime.getTime() + 1000*30) - case 2: return new Date(app.model.chainTime.getTime() + 1000*60) - case 3: return new Date(app.model.chainTime.getTime() + 1000*60*60) - case 4: return new Date(app.model.chainTime.getTime() + 1000*60*60*24*30) - case 5: return new Date(app.model.chainTime.getTime() + 1000*60*60*24*365) - } - } - } - } - UnlockingFinishButtons { - app: base.app - Layout.fillWidth: true - rightButtonText: qsTr("Commit") - onLeftButtonClicked: canceled({}) - onRightButtonClicked: { - if (app.wallet.isLocked) - app.wallet.unlock(passwordField.text) - else { - trx.setExpiration(expirationSelector.getExpiration()) - app.signTransaction(trx) - app.model.broadcast(trx) - completed(trx) - } - } - } -} diff --git a/programs/light_client/qml/TransactionDelegate.qml b/programs/light_client/qml/TransactionDelegate.qml deleted file mode 100644 index 26f6b5c4..00000000 --- a/programs/light_client/qml/TransactionDelegate.qml +++ /dev/null @@ -1,42 +0,0 @@ -import QtQuick 2.5 -import QtQuick.Layouts 1.2 - -import Graphene.Client 0.1 - -import "." - -ColumnLayout { - id: base - spacing: Scaling.mm(2) - - property Transaction trx - property GrapheneApplication app - - Text { - font.bold: true - font.pointSize: Scaling.cm(.4) - text: qsTr("Transaction Status: %1").arg(trx.statusString) - } - Repeater { - model: trx.operations - Loader { - function load() { - var source - switch (modelData.operationType) { - case OperationBase.TransferOperationType: source = "TransferOperationDelegate.qml" - } - setSource(source, {"op": modelData, "app": base.app, "width": base.width}) - } - Component.onCompleted: load() - // Debugging shim; disable before release - MouseArea { - anchors.fill: item - onClicked: { - console.log("Reloading " + parent.source) - parent.source = "" - parent.load() - } - } - } - } -} diff --git a/programs/light_client/qml/TransferForm.qml b/programs/light_client/qml/TransferForm.qml deleted file mode 100644 index f2850000..00000000 --- a/programs/light_client/qml/TransferForm.qml +++ /dev/null @@ -1,130 +0,0 @@ -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.2 - -import Graphene.Client 0.1 - -import "." - -/** - * This is the form for transferring some amount of asset from one account to another. - */ -FormBase { - id: base - - /// The Account object for the sender - property alias senderAccount: senderPicker.account - /// The Account object for the receiver - property alias receiverAccount: recipientPicker.account - - function operation() { - if (!finishLine.rightButtonEnabled) return app.operationBuilder.transfer(0,0,0,0, memoField.text, 0) - - return app.operationBuilder.transfer(senderPicker.account.id, recipientPicker.account.id, - amountField.value * amountField.precisionAdjustment, - amountField.maxBalance.type.id, memoField.text, 0) - } - - Component.onCompleted: console.log("Made a transfer form") - Component.onDestruction: console.log("Destroyed a transfer form") - - AccountPicker { - id: senderPicker - // The senderPicker is really the heart of the form. Everything else in the form adjusts based on the account - // selected here. The assetField below updates to contain all assets this account has a nonzero balance in. - // The amountField updates based on the asset selected in the assetField to have the appropriate precision and - // to have a maximum value equal to the account's balance in that asset. The transfer button enables only when - // both accounts are set, and a nonzero amount is selected to be transferred. - - app: base.app - Layout.fillWidth: true - Layout.minimumWidth: Scaling.cm(5) - Component.onCompleted: setFocus() - placeholderText: qsTr("Sender") - showBalance: balances? balances.reduce(function(foundIndex, balance, index) { - if (foundIndex >= 0) return foundIndex - return balance.type.symbol === assetField.currentText? index : -1 - }, -1) : -1 - onBalanceClicked: amountField.value = balance - } - AccountPicker { - id: recipientPicker - app: base.app - Layout.fillWidth: true - Layout.minimumWidth: Scaling.cm(5) - placeholderText: qsTr("Recipient") - layoutDirection: Qt.RightToLeft - } - RowLayout { - Layout.fillWidth: true - TextField { - id: memoField - Layout.fillWidth: true - placeholderText: qsTr("Memo") - } - CheckBox { - id: encryptMemoField - text: qsTr("Encrypt Memo") - checked: true - } - } - RowLayout { - Layout.fillWidth: true - SpinBox { - id: amountField - Layout.preferredWidth: Scaling.cm(4) - Layout.minimumWidth: Scaling.cm(1.5) - enabled: maxBalance - minimumValue: 0 - maximumValue: maxBalance? maxBalance.amountReal() : 0 - decimals: maxBalance? maxBalance.type.precision : 0 - - Keys.onReturnPressed: if (finishLine.rightButtonEnabled) finishLine.clickRight() - - property Balance maxBalance: assetField.enabled && senderPicker.showBalance >= 0? - senderPicker.balances[senderPicker.showBalance] : null - property int precisionAdjustment: maxBalance? Math.pow(10, maxBalance.type.precision) : 1 - - // Workaround to preserve value in case form gets disabled then re-enabled - onEnabledChanged: if (!enabled) __valueBackup = value - onMaximumValueChanged: if (enabled && maximumValue > __valueBackup) value = __valueBackup - property real __valueBackup - } - ComboBox { - id: assetField - Layout.minimumWidth: Scaling.cm(1) - enabled: senderPicker.balances instanceof Array && senderPicker.balances.length > 0 - model: enabled? senderPicker.balances.filter(function(balance) { return balance.amount > 0 }) - .map(function(balance) { return balance.type.symbol }) - : ["Asset Type"] - } - Text { - font.pixelSize: assetField.height / 2.5 - text: { - if (!senderPicker.account || !amountField.maxBalance) - return "" - return qsTr("Fee:
") + amountField.maxBalance.type.formatAmount(operation().fee) + " CORE" - } - } - } - UnlockingFinishButtons { - id: finishLine - app: base.app - rightButtonText: { - return !senderAccount || - !senderAccount.isLoaded || - senderPicker.accountControlLevel >= 1? qsTr("Transfer") : qsTr("Propose") - } - rightButtonEnabled: senderPicker.account && recipientPicker.account && senderPicker.account !== recipientPicker.account && amountField.value - requiresUnlocking: encryptMemoField.checked && memoField.text - Layout.fillWidth: true - - onLeftButtonClicked: canceled({}) - onRightButtonClicked: { - var op = operation() - if (encryptMemoField.checked) - op.encryptMemo(app.wallet, app.model) - completed([op]) - } - } -} diff --git a/programs/light_client/qml/TransferOperationDelegate.qml b/programs/light_client/qml/TransferOperationDelegate.qml deleted file mode 100644 index e0f62c29..00000000 --- a/programs/light_client/qml/TransferOperationDelegate.qml +++ /dev/null @@ -1,59 +0,0 @@ -import QtQuick 2.5 -import QtQuick.Layouts 1.2 - -import Graphene.Client 0.1 - -import "." - -ColumnLayout { - id: base - - property TransferOperation op - property GrapheneApplication app - - property Asset transferAsset: app.model.getAsset(op.amountType) - property Asset feeAsset: app.model.getAsset(op.feeType) - property Account sender: app.model.getAccount(op.sender) - property Account receiver: app.model.getAccount(op.receiver) - - RowLayout { - Layout.fillWidth: true - Identicon { - height: Scaling.cm(1) - width: Scaling.cm(1) - name: sender.name - } - Text { - Layout.alignment: Qt.AlignVCenter - text: "->
%1 %2".arg(transferAsset.formatAmount(op.amount)).arg(transferAsset.symbol) - horizontalAlignment: Text.Center - } - Identicon { - height: Scaling.cm(1) - width: Scaling.cm(1) - name: receiver.name - } - ColumnLayout { - Layout.fillWidth: true - Text { - Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - text: qsTr("Transfer from %1 to %2").arg(sender.name).arg(receiver.name) - } - Text { - Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - font.pointSize: 9 - text: qsTr("Fee: %1 %2").arg(feeAsset.formatAmount(op.fee)).arg(feeAsset.symbol) - } - } - } - - Text { - text: op.memo? qsTr("Memo: %1").arg(op.memoIsEncrypted && !app.wallet.isLocked? op.decryptedMemo(app.wallet, app.model) - : op.memo) - : qsTr("No memo") - color: op.memo? "black" : "grey" - font.italic: !op.memo - } -} diff --git a/programs/light_client/qml/UnlockingFinishButtons.qml b/programs/light_client/qml/UnlockingFinishButtons.qml deleted file mode 100644 index 0b6d0497..00000000 --- a/programs/light_client/qml/UnlockingFinishButtons.qml +++ /dev/null @@ -1,54 +0,0 @@ -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.2 - -import "." - -import Graphene.Client 0.1 - -RowLayout { - property string leftButtonText: qsTr("Cancel") - property string unlockButtonText: qsTr("Unlock") - property string rightButtonText: qsTr("Finish") - property bool leftButtonEnabled: true - property bool rightButtonEnabled: true - property bool requiresUnlocking: true - property GrapheneApplication app - - signal leftButtonClicked - signal rightButtonClicked - - function clickLeft() { leftButton.clicked() } - function clickRight() { rightButton.clicked() } - - Item { Layout.fillWidth: true } - Button { - id: leftButton - text: leftButtonText - onClicked: leftButtonClicked() - } - TextField { - id: passwordField - property bool shown: requiresUnlocking && app.wallet.isLocked - property real desiredWidth: shown? Scaling.cm(4) : 0 - Layout.preferredWidth: desiredWidth - echoMode: TextInput.Password - placeholderText: qsTr("Wallet password") - visible: desiredWidth > 0 - onAccepted: rightButton.clicked() - - Behavior on desiredWidth { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } } - } - Button { - id: rightButton - text: passwordField.shown? unlockButtonText : rightButtonText - enabled: rightButtonEnabled - onClicked: { - if (passwordField.visible) - return app.wallet.unlock(passwordField.text) - - rightButtonClicked() - } - Behavior on implicitWidth { NumberAnimation {} } - } -} diff --git a/programs/light_client/qml/jdenticon/jdenticon-1.0.1.min.js b/programs/light_client/qml/jdenticon/jdenticon-1.0.1.min.js deleted file mode 100755 index dd0b1065..00000000 --- a/programs/light_client/qml/jdenticon/jdenticon-1.0.1.min.js +++ /dev/null @@ -1,18 +0,0 @@ -// Jdenticon 1.0.1 | jdenticon.com | zlib licensed | (c) 2014-2015 Daniel Mester Pirttijärvi -/*Alteration to official Jdenticon code: make jdenticon() a variable in this context instead of a property of window*/ -var jdenticon=function(){function h(){}function n(b,a,c,d){this.h=b;this.i=a;this.k=c;this.f=d}function u(b,a){this.e=b;this.g=a||n.q;b.beginPath()}function r(b,a,c){var d=(b="string"===typeof b?document.querySelector(b):b).getContext("2d");c=Math.min(b.width)*(1-2*(c===t?.08:c));d.save();d.clearRect(0,0,b.width,b.height);d.translate(0|(b.width-c)/2,0|(b.height-c)/2);v(d,a||b.getAttribute("data-jdenticon-hash"),c);d.restore()}function v(b,a,c){function d(b,c,d,e,g){e=e?parseInt(a.charAt(e),16): -0;c=c[parseInt(a.charAt(d),16)%c.length];var f;for(d=0;dc)throw Error("Jdenticon cannot render identicons smaller than 30 pixels.");if(!/^[0-9a-f]{10,}$/i.test(a))throw Error("Invalid hash passed to Jdenticon.");c|=0;for(var p=2*(0|c/8),f=parseInt(a.substr(-7),16)/268435455,m= -[h.o(76,76,76),h.m(f,.6),h.o(230,230,230),h.m(f,.8),h.n(f,.4)],l=[],k,f=0;3>f;f++){k=parseInt(a.charAt(8+f),16)%m.length;if(e([0,4])||e([2,3]))k=1;l.push(k)}b.clearRect(0,0,c,c);g(0);d(b,w,2,3,[[1,0],[2,0],[2,3],[1,3],[0,1],[3,1],[3,2],[0,2]]);g(1);d(b,w,4,5,[[0,0],[3,0],[3,3],[0,3]]);g(2);d(b,y,1,null,[[1,1],[2,1],[2,2],[1,2]])}function q(){for(var b,a=document.getElementsByTagName("canvas"),c=0;c= 0) - { - console.log("ID ALREADY SET" ); - console.log(JSON.stringify(acct)) - } - else - { - console.log("Waiting for result...") - acct.idChanged.connect(function() { - console.log( "ID CHANGED" ); - console.log(JSON.stringify(acct)) - }) - } - } - } - - TextField { - id: accountIdField - onAccepted: lookupAccountIdButton.clicked() - focus: true - } - Button { - id: lookupAccountIdButton - text: "Lookup Account ID" - onClicked: { - var acct = app.model.getAccount(parseInt(accountIdField.text)) - console.log(JSON.stringify(acct)) - // @disable-check M126 - if (acct == null) - console.log("Got back null account") - else if ( !(parseInt(acct.name) <= 0) ) - console.log(JSON.stringify(acct)) - else { - console.log("Waiting for result...") - acct.nameChanged.connect(function() { - console.log(JSON.stringify(acct)) - }) - } - } - } - - TextField { - id: assetIdField - onAccepted: lookupassetIdButton.clicked() - focus: true - } - Button { - id: lookupassetIdButton - text: "Lookup Asset ID" - onClicked: { - var acct = app.model.getAsset(parseInt(assetIdField.text)) - console.log(JSON.stringify(acct)) - // @disable-check M126 - if (acct == null) - console.log("Got back null asset") - else if ( !(parseInt(acct.name) <= 0) ) - { - console.log(JSON.stringify(acct)) - } - else - { - console.log("Waiting for result...") - acct.nameChanged.connect(function() { - console.log(JSON.stringify(acct)) - }) - } - } - } - TextField { - id: passwordField - echoMode: TextInput.Password - } - Button { - text: app.wallet.isLocked? "Unlock wallet" : "Lock wallet" - onClicked: { - if (app.wallet.isLocked) - app.wallet.unlock(passwordField.text) - else - app.wallet.lock() - } - } - TextField { - id: keyField - placeholderText: "Private key" - } - TextField { - id: keyLabelField - placeholderText: "Key label" - } - Button { - text: "Import key" - enabled: !app.wallet.isLocked && keyField.text && keyLabelField.text - onClicked: app.wallet.importPrivateKey(keyField.text, keyLabelField.text) - } - } - - FormBox { - id: formBox - anchors.fill: parent - z: 10 - } - - // This Settings is only for geometry -- it doesn't get an id. See appSettings for normal settings - Settings { - category: "windowGeometry" - property alias x: window.x - property alias y: window.y - property alias width: window.width - property alias height: window.height - } -} diff --git a/programs/light_client/qml/qml.qrc b/programs/light_client/qml/qml.qrc deleted file mode 100644 index 55cdc35a..00000000 --- a/programs/light_client/qml/qml.qrc +++ /dev/null @@ -1,19 +0,0 @@ - - - main.qml - FormBase.qml - TransferForm.qml - TransactionDelegate.qml - TransferOperationDelegate.qml - TransactionConfirmationForm.qml - FormBox.qml - FormFlipper.qml - UnlockingFinishButtons.qml - Scaling.qml - Identicon.qml - AccountPicker.qml - TooltipArea.qml - jdenticon/jdenticon-1.0.1.min.js - - - diff --git a/programs/light_client/qml/qmldir b/programs/light_client/qml/qmldir deleted file mode 100644 index 79c7d88a..00000000 --- a/programs/light_client/qml/qmldir +++ /dev/null @@ -1 +0,0 @@ -singleton Scaling Scaling.qml