2015-07-10 21:37:22 +00:00
|
|
|
#pragma once
|
2015-07-13 17:56:30 +00:00
|
|
|
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
2015-07-13 19:41:06 +00:00
|
|
|
|
|
|
|
|
#include <boost/multi_index_container.hpp>
|
|
|
|
|
#include <boost/multi_index/member.hpp>
|
|
|
|
|
#include <boost/multi_index/ordered_index.hpp>
|
|
|
|
|
#include <boost/multi_index/hashed_index.hpp>
|
|
|
|
|
#include <boost/multi_index/mem_fun.hpp>
|
|
|
|
|
|
2015-07-13 17:56:30 +00:00
|
|
|
#include <fc/network/http/websocket.hpp>
|
|
|
|
|
#include <fc/thread/thread.hpp>
|
2015-07-13 19:41:06 +00:00
|
|
|
#include <graphene/app/api.hpp>
|
2015-07-10 21:37:22 +00:00
|
|
|
|
2015-07-14 17:06:32 +00:00
|
|
|
#include <QtQml>
|
2015-07-10 21:37:22 +00:00
|
|
|
#include <QObject>
|
|
|
|
|
#include <QQmlListProperty>
|
|
|
|
|
|
2015-07-13 19:41:06 +00:00
|
|
|
using boost::multi_index_container;
|
|
|
|
|
using namespace boost::multi_index;
|
2015-07-13 17:56:30 +00:00
|
|
|
|
2015-07-17 19:35:24 +00:00
|
|
|
using graphene::chain::by_id;
|
|
|
|
|
|
2015-07-14 17:06:32 +00:00
|
|
|
using ObjectId = qint64;
|
2015-07-14 19:06:00 +00:00
|
|
|
Q_DECLARE_METATYPE(ObjectId)
|
2015-07-14 17:06:32 +00:00
|
|
|
|
2015-07-13 18:14:58 +00:00
|
|
|
Q_DECLARE_METATYPE(std::function<void()>)
|
2015-07-13 17:56:30 +00:00
|
|
|
|
2015-07-14 21:30:15 +00:00
|
|
|
class GrapheneObject : public QObject
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
2015-07-15 21:48:44 +00:00
|
|
|
Q_PROPERTY(ObjectId id MEMBER m_id READ id NOTIFY idChanged)
|
2015-07-14 21:30:15 +00:00
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
ObjectId m_id;
|
2015-07-14 21:30:15 +00:00
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
public:
|
|
|
|
|
GrapheneObject(ObjectId id = -1, QObject* parent = nullptr)
|
|
|
|
|
: QObject(parent), m_id(id)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
ObjectId id() const {
|
|
|
|
|
return m_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Q_SIGNALS:
|
|
|
|
|
void idChanged();
|
2015-07-14 21:30:15 +00:00
|
|
|
};
|
2015-07-14 17:06:32 +00:00
|
|
|
class Crypto {
|
|
|
|
|
Q_GADGET
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
Q_INVOKABLE QString sha256(QByteArray data) {
|
|
|
|
|
return QCryptographicHash::hash(data, QCryptographicHash::Sha256).toHex();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
QML_DECLARE_TYPE(Crypto)
|
2015-07-13 17:56:30 +00:00
|
|
|
|
2015-07-14 21:30:15 +00:00
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
class Asset : public GrapheneObject {
|
2015-07-10 21:37:22 +00:00
|
|
|
Q_OBJECT
|
|
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
Q_PROPERTY(QString symbol MEMBER m_symbol READ symbol NOTIFY symbolChanged)
|
|
|
|
|
Q_PROPERTY(quint32 precision MEMBER m_precision NOTIFY precisionChanged)
|
2015-07-14 21:30:15 +00:00
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
QString m_symbol;
|
|
|
|
|
quint32 m_precision;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2015-07-10 21:37:22 +00:00
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
quint64 precisionPower() const {
|
|
|
|
|
quint64 power = 1;
|
|
|
|
|
for (int i = 0; i < m_precision; ++i)
|
|
|
|
|
power *= 10;
|
|
|
|
|
return power;
|
|
|
|
|
}
|
2015-07-14 21:30:15 +00:00
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
Q_SIGNALS:
|
|
|
|
|
void symbolChanged();
|
|
|
|
|
void precisionChanged();
|
2015-07-10 21:37:22 +00:00
|
|
|
};
|
|
|
|
|
|
2015-07-14 21:30:15 +00:00
|
|
|
struct by_symbol_name;
|
|
|
|
|
typedef multi_index_container<
|
|
|
|
|
Asset*,
|
|
|
|
|
indexed_by<
|
2015-07-15 21:48:44 +00:00
|
|
|
hashed_unique< tag<by_id>, const_mem_fun<GrapheneObject, ObjectId, &GrapheneObject::id > >,
|
|
|
|
|
ordered_unique< tag<by_symbol_name>, const_mem_fun<Asset, QString, &Asset::symbol> >
|
2015-07-14 21:30:15 +00:00
|
|
|
>
|
|
|
|
|
> asset_multi_index_type;
|
|
|
|
|
|
|
|
|
|
class Balance : public GrapheneObject {
|
2015-07-10 21:37:22 +00:00
|
|
|
Q_OBJECT
|
|
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
Q_PROPERTY(Asset* type MEMBER type NOTIFY typeChanged)
|
|
|
|
|
Q_PROPERTY(qint64 amount MEMBER amount NOTIFY amountChanged)
|
2015-07-10 21:37:22 +00:00
|
|
|
|
|
|
|
|
Asset* type;
|
|
|
|
|
qint64 amount;
|
2015-07-15 21:48:44 +00:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// This ultimately needs to be replaced with a string equivalent
|
|
|
|
|
Q_INVOKABLE qreal amountReal() const {
|
|
|
|
|
return amount / qreal(type->precisionPower());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Q_SIGNALS:
|
|
|
|
|
void typeChanged();
|
|
|
|
|
void amountChanged();
|
2015-07-10 21:37:22 +00:00
|
|
|
};
|
|
|
|
|
|
2015-07-14 21:30:15 +00:00
|
|
|
class Account : public GrapheneObject {
|
2015-07-10 21:37:22 +00:00
|
|
|
Q_OBJECT
|
|
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
Q_PROPERTY(QString name MEMBER m_name READ name NOTIFY nameChanged)
|
|
|
|
|
Q_PROPERTY(QQmlListProperty<Balance> balances READ balances NOTIFY balancesChanged)
|
2015-07-10 21:37:22 +00:00
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
QString m_name;
|
2015-07-10 21:37:22 +00:00
|
|
|
QList<Balance*> m_balances;
|
|
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
public:
|
|
|
|
|
Account(ObjectId id = -1, QString name = QString(), QObject* parent = nullptr)
|
|
|
|
|
: GrapheneObject(id, parent), m_name(name)
|
|
|
|
|
{}
|
2015-07-13 20:21:01 +00:00
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
QString name()const { return m_name; }
|
|
|
|
|
QQmlListProperty<Balance> balances();
|
2015-07-14 13:46:38 +00:00
|
|
|
|
2015-07-17 19:35:24 +00:00
|
|
|
void setBalances(QList<Balance*> balances) {
|
|
|
|
|
if (balances != m_balances) {
|
|
|
|
|
m_balances = balances;
|
|
|
|
|
Q_EMIT balancesChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:48:44 +00:00
|
|
|
Q_SIGNALS:
|
|
|
|
|
void nameChanged();
|
|
|
|
|
void balancesChanged();
|
2015-07-10 21:37:22 +00:00
|
|
|
};
|
|
|
|
|
|
2015-07-13 21:24:25 +00:00
|
|
|
struct by_account_name;
|
2015-07-13 19:41:06 +00:00
|
|
|
typedef multi_index_container<
|
|
|
|
|
Account*,
|
|
|
|
|
indexed_by<
|
2015-07-15 21:48:44 +00:00
|
|
|
hashed_unique< tag<by_id>, const_mem_fun<GrapheneObject, ObjectId, &GrapheneObject::id > >,
|
|
|
|
|
ordered_unique< tag<by_account_name>, const_mem_fun<Account, QString, &Account::name> >
|
2015-07-13 19:41:06 +00:00
|
|
|
>
|
|
|
|
|
> account_multi_index_type;
|
|
|
|
|
|
2015-07-13 17:19:07 +00:00
|
|
|
class ChainDataModel : public QObject {
|
2015-07-10 21:37:22 +00:00
|
|
|
Q_OBJECT
|
|
|
|
|
|
2015-07-17 19:35:24 +00:00
|
|
|
void getAssetImpl(QString assetIdentifier, Asset* const * assetInContainer);
|
|
|
|
|
void getAccountImpl(QString accountIdentifier, Account* const * accountInContainer);
|
|
|
|
|
|
2015-07-10 21:37:22 +00:00
|
|
|
public:
|
2015-07-14 17:06:32 +00:00
|
|
|
Q_INVOKABLE Account* getAccount(ObjectId id);
|
2015-07-13 19:41:06 +00:00
|
|
|
Q_INVOKABLE Account* getAccount(QString name);
|
2015-07-15 21:48:44 +00:00
|
|
|
Q_INVOKABLE Asset* getAsset(ObjectId id);
|
2015-07-14 21:30:15 +00:00
|
|
|
Q_INVOKABLE Asset* getAsset(QString symbol);
|
2015-07-13 17:56:30 +00:00
|
|
|
|
|
|
|
|
ChainDataModel(){}
|
|
|
|
|
ChainDataModel( fc::thread& t, QObject* parent = nullptr );
|
|
|
|
|
|
2015-07-13 19:41:06 +00:00
|
|
|
void setDatabaseAPI( fc::api<graphene::app::database_api> dbapi ){ m_db_api = dbapi; }
|
|
|
|
|
|
|
|
|
|
Q_SIGNALS:
|
|
|
|
|
void queueExecute( const std::function<void()>& );
|
|
|
|
|
void exceptionThrown( QString message );
|
|
|
|
|
|
2015-07-13 17:56:30 +00:00
|
|
|
private:
|
2015-07-17 19:35:24 +00:00
|
|
|
fc::thread* m_rpc_thread = nullptr;
|
2015-07-13 19:41:06 +00:00
|
|
|
std::string m_api_url;
|
|
|
|
|
fc::api<graphene::app::database_api> m_db_api;
|
|
|
|
|
|
2015-07-14 17:06:32 +00:00
|
|
|
ObjectId m_account_query_num = -1;
|
2015-07-13 19:41:06 +00:00
|
|
|
account_multi_index_type m_accounts;
|
2015-07-14 21:30:15 +00:00
|
|
|
asset_multi_index_type m_assets;
|
2015-07-10 21:37:22 +00:00
|
|
|
};
|
2015-07-13 17:19:07 +00:00
|
|
|
|
|
|
|
|
class GrapheneApplication : public QObject {
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
Q_PROPERTY(ChainDataModel* model READ model CONSTANT)
|
|
|
|
|
Q_PROPERTY(bool isConnected READ isConnected NOTIFY isConnectedChanged)
|
|
|
|
|
|
|
|
|
|
|
2015-07-13 17:56:30 +00:00
|
|
|
fc::thread m_thread;
|
|
|
|
|
ChainDataModel* m_model = nullptr;
|
|
|
|
|
bool m_isConnected = false;
|
|
|
|
|
|
2015-07-14 20:49:17 +00:00
|
|
|
boost::signals2::scoped_connection m_connectionClosed;
|
|
|
|
|
|
2015-07-13 21:24:25 +00:00
|
|
|
std::shared_ptr<fc::http::websocket_client> m_client;
|
2015-07-17 19:35:24 +00:00
|
|
|
fc::future<void> m_done;
|
|
|
|
|
|
|
|
|
|
void setIsConnected(bool v);
|
2015-07-13 18:14:58 +00:00
|
|
|
|
2015-07-17 19:35:24 +00:00
|
|
|
protected Q_SLOTS:
|
|
|
|
|
void execute(const std::function<void()>&)const;
|
2015-07-13 18:14:58 +00:00
|
|
|
|
2015-07-13 17:19:07 +00:00
|
|
|
public:
|
2015-07-17 19:35:24 +00:00
|
|
|
GrapheneApplication(QObject* parent = nullptr);
|
2015-07-13 17:56:30 +00:00
|
|
|
~GrapheneApplication();
|
|
|
|
|
|
2015-07-13 17:19:07 +00:00
|
|
|
ChainDataModel* model() const
|
|
|
|
|
{
|
|
|
|
|
return m_model;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 18:35:17 +00:00
|
|
|
Q_INVOKABLE void start(QString apiUrl,
|
2015-07-17 19:35:24 +00:00
|
|
|
QString user,
|
|
|
|
|
QString pass);
|
2015-07-13 17:19:07 +00:00
|
|
|
|
|
|
|
|
bool isConnected() const
|
|
|
|
|
{
|
|
|
|
|
return m_isConnected;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 19:41:06 +00:00
|
|
|
Q_SIGNALS:
|
|
|
|
|
void exceptionThrown( QString message );
|
|
|
|
|
void loginFailed();
|
2015-07-13 17:19:07 +00:00
|
|
|
void isConnectedChanged(bool isConnected);
|
2015-07-13 18:14:58 +00:00
|
|
|
void queueExecute( const std::function<void()>& );
|
2015-07-13 17:19:07 +00:00
|
|
|
};
|