Gav Wood
11 years ago
8 changed files with 1334 additions and 538 deletions
@ -1,48 +0,0 @@ |
|||
cmake_policy(SET CMP0015 NEW) |
|||
|
|||
aux_source_directory(. SRC_LIST) |
|||
|
|||
include_directories(../libethereum) |
|||
link_directories(../libethereum) |
|||
|
|||
add_executable(eth-ncurses-cli ${SRC_LIST}) |
|||
|
|||
if (${TARGET_PLATFORM} STREQUAL "w64") |
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") |
|||
target_link_libraries(eth-ncurses-cli gcc) |
|||
target_link_libraries(eth-ncurses-cli gdi32) |
|||
target_link_libraries(eth-ncurses-cli ws2_32) |
|||
target_link_libraries(eth-ncurses-cli mswsock) |
|||
target_link_libraries(eth-ncurses-cli shlwapi) |
|||
target_link_libraries(eth-ncurses-cli iphlpapi) |
|||
target_link_libraries(eth-ncurses-cli cryptopp) |
|||
target_link_libraries(eth-ncurses-cli ncurses) |
|||
target_link_libraries(eth-ncurses-cli form) |
|||
target_link_libraries(eth-ncurses-cli boost_system-mt-s) |
|||
target_link_libraries(eth-ncurses-cli boost_filesystem-mt-s) |
|||
target_link_libraries(eth-ncurses-cli boost_thread_win32-mt-s) |
|||
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) |
|||
elseif (UNIX) |
|||
target_link_libraries(eth-ncurses-cli ncurses) |
|||
target_link_libraries(eth-ncurses-cli form) |
|||
else () |
|||
target_link_libraries(eth-ncurses-cli ${CRYPTOPP_LIBRARIES}) |
|||
target_link_libraries(eth-ncurses-cli boost_system) |
|||
target_link_libraries(eth-ncurses-cli boost_filesystem) |
|||
target_link_libraries(eth-ncurses-cli ncurses) |
|||
target_link_libraries(eth-ncurses-cli form) |
|||
find_package(Threads REQUIRED) |
|||
target_link_libraries(eth-ncurses-cli ${CMAKE_THREAD_LIBS_INIT}) |
|||
endif () |
|||
|
|||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") |
|||
include_directories(/usr/local/include) |
|||
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") |
|||
|
|||
target_link_libraries(eth-ncurses-cli ethereum) |
|||
target_link_libraries(eth-ncurses-cli miniupnpc) |
|||
target_link_libraries(eth-ncurses-cli leveldb) |
|||
target_link_libraries(eth-ncurses-cli gmp) |
|||
|
|||
install( TARGETS eth-ncurses-cli DESTINATION bin ) |
|||
|
@ -0,0 +1,115 @@ |
|||
cmake_policy(SET CMP0015 NEW) |
|||
|
|||
if ("${TARGET_PLATFORM}" STREQUAL "w64") |
|||
cmake_policy(SET CMP0020 NEW) |
|||
endif () |
|||
|
|||
|
|||
set(CMAKE_INCLUDE_CURRENT_DIR ON) |
|||
aux_source_directory(. SRC_LIST) |
|||
|
|||
include_directories(..) |
|||
link_directories(../libethereum) |
|||
|
|||
# Find Qt5 for Apple and update src_list for windows |
|||
if (APPLE) |
|||
# homebrew defaults to qt4 and installs qt5 as 'keg-only' |
|||
# which places it into /usr/local/opt insteadof /usr/local. |
|||
|
|||
set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) |
|||
include_directories(/usr/local/opt/qt5/include /usr/local/include) |
|||
elseif (${TARGET_PLATFORM} STREQUAL "w64") |
|||
set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) |
|||
elseif (UNIX) |
|||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") |
|||
endif () |
|||
|
|||
|
|||
find_package(Qt5Gui REQUIRED) |
|||
find_package(Qt5Quick REQUIRED) |
|||
find_package(Qt5Qml REQUIRED) |
|||
find_package(Qt5Network REQUIRED) |
|||
find_package(Qt5Widgets REQUIRED) |
|||
find_package(Qt5WebKit REQUIRED) |
|||
find_package(Qt5WebKitWidgets REQUIRED) |
|||
|
|||
set(EXECUTABLE qethereum) |
|||
|
|||
# Set name of binary and add_executable() |
|||
if (APPLE) |
|||
set(CMAKE_INSTALL_PREFIX ./) |
|||
set(BIN_INSTALL_DIR ".") |
|||
set(DOC_INSTALL_DIR ".") |
|||
|
|||
set(PROJECT_VERSION "${ETH_VERSION}") |
|||
set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") |
|||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") |
|||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") |
|||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") |
|||
set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") |
|||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") |
|||
set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) |
|||
include(BundleUtilities) |
|||
|
|||
add_library(${EXECUTABLE} SHARED ${RESOURCE_ADDED} ${SRC_LIST}) |
|||
else () |
|||
add_library(${EXECUTABLE} ${RESOURCE_ADDED} ${SRC_LIST}) |
|||
endif () |
|||
|
|||
qt5_use_modules(${EXECUTABLE} Core Gui WebKit WebKitWidgets Widgets Network Quick Qml) |
|||
target_link_libraries(${EXECUTABLE} ethereum secp256k1 ${CRYPTOPP_LIBRARIES}) |
|||
|
|||
if (APPLE) |
|||
if (${ADDFRAMEWORKS}) |
|||
set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") |
|||
endif () |
|||
|
|||
SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) |
|||
|
|||
# This is a workaround for when the build-type defaults to Debug, and when a multi-config generator like xcode is used, where the type |
|||
# will not be set but defaults to release. |
|||
set(generator_lowercase "${CMAKE_GENERATOR}") |
|||
string(TOLOWER "${CMAKE_GENERATOR}" generator_lowercase) |
|||
if (generator_lowercase STREQUAL "xcode") |
|||
# TODO: Not sure how to resolve this. Possibly \${TARGET_BUILD_DIR} |
|||
set(binary_build_dir "${CMAKE_CURRENT_BINARY_DIR}/Debug") |
|||
else () |
|||
set(binary_build_dir "${CMAKE_CURRENT_BINARY_DIR}") |
|||
endif () |
|||
|
|||
set(APPS ${binary_build_dir}/${EXECUTABLE}.app) |
|||
|
|||
# This tool and the next will automatically looked at the linked libraries in order to determine what dependencies are required. Thus, target_link_libaries only needs to add ethereum and secp256k1 (above) |
|||
install(CODE " |
|||
include(BundleUtilities) |
|||
set(BU_CHMOD_BUNDLE_ITEMS 1) |
|||
fixup_bundle(\"${APPS}\" \"${BUNDLELIBS}\" \"../libethereum ../secp256k1\") |
|||
" COMPONENT RUNTIME ) |
|||
|
|||
if (${ADDFRAMEWORKS}) |
|||
add_custom_target(addframeworks ALL |
|||
COMMAND /usr/local/opt/qt5/bin/macdeployqt ${binary_build_dir}/${EXECUTABLE}.app |
|||
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} |
|||
DEPENDS ${PROJECT_NAME} |
|||
) |
|||
endif () |
|||
|
|||
elseif (${TARGET_PLATFORM} STREQUAL "w64") |
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-keep-inline-dllexport -static-libgcc -static-libstdc++ -static") |
|||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-s -Wl,-subsystem,windows -mthreads -L/usr/x86_64-w64-mingw32/plugins/platforms") |
|||
target_link_libraries(${EXECUTABLE} gcc) |
|||
target_link_libraries(${EXECUTABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) |
|||
target_link_libraries(${EXECUTABLE} boost_system-mt-s) |
|||
target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) |
|||
target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) |
|||
target_link_libraries(${EXECUTABLE} Qt5PlatformSupport) |
|||
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) |
|||
elseif (UNIX) |
|||
else () |
|||
target_link_libraries(${EXECUTABLE} boost_system) |
|||
target_link_libraries(${EXECUTABLE} boost_filesystem) |
|||
find_package(Threads REQUIRED) |
|||
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) |
|||
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ) |
|||
endif () |
|||
|
@ -0,0 +1,319 @@ |
|||
#include <QtQml/QtQml> |
|||
#include <QtCore/QtCore> |
|||
#include <libethereum/Dagger.h> |
|||
#include <libethereum/Client.h> |
|||
#include <libethereum/Instruction.h> |
|||
#include <libethereum/FileSystem.h> |
|||
#include <libethereum/PeerServer.h> |
|||
#include "BuildInfo.h" |
|||
#include "QEthereum.h" |
|||
using namespace std; |
|||
|
|||
// types
|
|||
using eth::bytes; |
|||
using eth::bytesConstRef; |
|||
using eth::h160; |
|||
using eth::h256; |
|||
using eth::u160; |
|||
using eth::u256; |
|||
using eth::u256s; |
|||
using eth::Address; |
|||
using eth::BlockInfo; |
|||
using eth::Client; |
|||
using eth::Instruction; |
|||
using eth::KeyPair; |
|||
using eth::NodeMode; |
|||
using eth::PeerInfo; |
|||
using eth::RLP; |
|||
using eth::Secret; |
|||
using eth::Transaction; |
|||
|
|||
// functions
|
|||
using eth::toHex; |
|||
using eth::assemble; |
|||
using eth::compileLisp; |
|||
using eth::disassemble; |
|||
using eth::formatBalance; |
|||
using eth::fromHex; |
|||
using eth::right160; |
|||
using eth::simpleDebugOut; |
|||
using eth::toLog2; |
|||
using eth::toString; |
|||
using eth::units; |
|||
|
|||
// vars
|
|||
using eth::g_logPost; |
|||
using eth::g_logVerbosity; |
|||
using eth::c_instructionInfo; |
|||
|
|||
// Horrible global for the mainwindow. Needed for the QmlEthereums to find the Main window which acts as multiplexer for now.
|
|||
// Can get rid of this once we've sorted out ITC for signalling & multiplexed querying.
|
|||
eth::Client* g_qmlClient; |
|||
QObject* g_qmlMain; |
|||
|
|||
QmlAccount::QmlAccount(QObject*) |
|||
{ |
|||
} |
|||
|
|||
QmlAccount::~QmlAccount() |
|||
{ |
|||
} |
|||
|
|||
void QmlAccount::setEthereum(QmlEthereum* _eth) |
|||
{ |
|||
if (m_eth == _eth) |
|||
return; |
|||
if (m_eth) |
|||
disconnect(m_eth, SIGNAL(changed()), this, SIGNAL(changed())); |
|||
m_eth = _eth; |
|||
if (m_eth) |
|||
connect(m_eth, SIGNAL(changed()), this, SIGNAL(changed())); |
|||
ethChanged(); |
|||
changed(); |
|||
} |
|||
|
|||
eth::u256 QmlAccount::balance() const |
|||
{ |
|||
if (m_eth) |
|||
return m_eth->balanceAt(m_address); |
|||
return u256(0); |
|||
} |
|||
|
|||
double QmlAccount::txCount() const |
|||
{ |
|||
if (m_eth) |
|||
return m_eth->txCountAt(m_address); |
|||
return 0; |
|||
} |
|||
|
|||
bool QmlAccount::isContract() const |
|||
{ |
|||
if (m_eth) |
|||
return m_eth->isContractAt(m_address); |
|||
return 0; |
|||
} |
|||
|
|||
QmlEthereum::QmlEthereum(QObject* _p): QObject(_p) |
|||
{ |
|||
connect(g_qmlMain, SIGNAL(changed()), SIGNAL(changed())); |
|||
} |
|||
|
|||
QmlEthereum::~QmlEthereum() |
|||
{ |
|||
} |
|||
|
|||
Client* QmlEthereum::client() const |
|||
{ |
|||
return g_qmlClient; |
|||
} |
|||
|
|||
Address QmlEthereum::coinbase() const |
|||
{ |
|||
return client()->address(); |
|||
} |
|||
|
|||
void QmlEthereum::setCoinbase(Address _a) |
|||
{ |
|||
if (client()->address() != _a) |
|||
{ |
|||
client()->setAddress(_a); |
|||
changed(); |
|||
} |
|||
} |
|||
|
|||
u256 QmlEthereum::balanceAt(Address _a) const |
|||
{ |
|||
return client()->postState().balance(_a); |
|||
} |
|||
|
|||
bool QmlEthereum::isContractAt(Address _a) const |
|||
{ |
|||
return client()->postState().isContractAddress(_a); |
|||
} |
|||
|
|||
bool QmlEthereum::isMining() const |
|||
{ |
|||
return client()->isMining(); |
|||
} |
|||
|
|||
bool QmlEthereum::isListening() const |
|||
{ |
|||
return client()->haveNetwork(); |
|||
} |
|||
|
|||
void QmlEthereum::setMining(bool _l) |
|||
{ |
|||
if (_l) |
|||
client()->startMining(); |
|||
else |
|||
client()->stopMining(); |
|||
} |
|||
|
|||
void QmlEthereum::setListening(bool _l) |
|||
{ |
|||
if (_l) |
|||
client()->startNetwork(); |
|||
else |
|||
client()->stopNetwork(); |
|||
} |
|||
|
|||
double QmlEthereum::txCountAt(Address _a) const |
|||
{ |
|||
return (double)client()->postState().transactionsFrom(_a); |
|||
} |
|||
|
|||
unsigned QmlEthereum::peerCount() const |
|||
{ |
|||
return (unsigned)client()->peerCount(); |
|||
} |
|||
|
|||
void QmlEthereum::transact(Secret _secret, u256 _amount, u256 _gasPrice, u256 _gas, QByteArray _code, QByteArray _init) |
|||
{ |
|||
client()->transact(_secret, _amount, bytes(_code.data(), _code.data() + _code.size()), bytes(_init.data(), _init.data() + _init.size()), _gas, _gasPrice); |
|||
} |
|||
|
|||
void QmlEthereum::transact(Secret _secret, Address _dest, u256 _amount, u256 _gasPrice, u256 _gas, QByteArray _data) |
|||
{ |
|||
client()->transact(_secret, _amount, _dest, bytes(_data.data(), _data.data() + _data.size()), _gas, _gasPrice); |
|||
} |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
|
|||
QEthereum::QEthereum(QObject* _p, Client* _c, QList<eth::KeyPair> _accounts): QObject(_p), m_client(_c), m_accounts(_accounts) |
|||
{ |
|||
connect(_p, SIGNAL(changed()), SIGNAL(changed())); |
|||
} |
|||
|
|||
QEthereum::~QEthereum() |
|||
{ |
|||
} |
|||
|
|||
Client* QEthereum::client() const |
|||
{ |
|||
return m_client; |
|||
} |
|||
|
|||
QVariant QEthereum::coinbase() const |
|||
{ |
|||
return toQJS(client()->address()); |
|||
} |
|||
|
|||
QVariant QEthereum::account() const |
|||
{ |
|||
if (m_accounts.empty()) |
|||
return toQJS(Address()); |
|||
return toQJS(m_accounts[0].address()); |
|||
} |
|||
|
|||
QList<QVariant> QEthereum::accounts() const |
|||
{ |
|||
QList<QVariant> ret; |
|||
for (auto i: m_accounts) |
|||
ret.push_back(toQJS(i.address())); |
|||
return ret; |
|||
} |
|||
|
|||
QVariant QEthereum::key() const |
|||
{ |
|||
if (m_accounts.empty()) |
|||
return toQJS(KeyPair()); |
|||
return toQJS(m_accounts[0]); |
|||
} |
|||
|
|||
QList<QVariant> QEthereum::keys() const |
|||
{ |
|||
QList<QVariant> ret; |
|||
for (auto i: m_accounts) |
|||
ret.push_back(toQJS(i)); |
|||
return ret; |
|||
} |
|||
|
|||
void QEthereum::setCoinbase(QVariant _a) |
|||
{ |
|||
if (client()->address() != to<Address>(_a)) |
|||
{ |
|||
client()->setAddress(to<Address>(_a)); |
|||
changed(); |
|||
} |
|||
} |
|||
|
|||
QVariant QEthereum::balanceAt(QVariant _a) const |
|||
{ |
|||
return toQJS(client()->postState().balance(to<Address>(_a))); |
|||
} |
|||
|
|||
QVariant QEthereum::storageAt(QVariant _a, QVariant _p) const |
|||
{ |
|||
return toQJS(client()->postState().contractStorage(to<Address>(_a), to<u256>(_p))); |
|||
} |
|||
|
|||
u256 QEthereum::balanceAt(Address _a) const |
|||
{ |
|||
return client()->postState().balance(_a); |
|||
} |
|||
|
|||
bool QEthereum::isContractAt(QVariant _a) const |
|||
{ |
|||
return client()->postState().isContractAddress(to<Address>(_a)); |
|||
} |
|||
|
|||
bool QEthereum::isContractAt(Address _a) const |
|||
{ |
|||
return client()->postState().isContractAddress(_a); |
|||
} |
|||
|
|||
bool QEthereum::isMining() const |
|||
{ |
|||
return client()->isMining(); |
|||
} |
|||
|
|||
bool QEthereum::isListening() const |
|||
{ |
|||
return client()->haveNetwork(); |
|||
} |
|||
|
|||
void QEthereum::setMining(bool _l) |
|||
{ |
|||
if (_l) |
|||
client()->startMining(); |
|||
else |
|||
client()->stopMining(); |
|||
} |
|||
|
|||
void QEthereum::setListening(bool _l) |
|||
{ |
|||
if (_l) |
|||
client()->startNetwork(); |
|||
else |
|||
client()->stopNetwork(); |
|||
} |
|||
|
|||
double QEthereum::txCountAt(QVariant _a) const |
|||
{ |
|||
return (double)client()->postState().transactionsFrom(to<Address>(_a)); |
|||
} |
|||
|
|||
double QEthereum::txCountAt(Address _a) const |
|||
{ |
|||
return (double)client()->postState().transactionsFrom(_a); |
|||
} |
|||
|
|||
unsigned QEthereum::peerCount() const |
|||
{ |
|||
return (unsigned)client()->peerCount(); |
|||
} |
|||
|
|||
QVariant QEthereum::create(QVariant _secret, QVariant _amount, QByteArray _code, QByteArray _init, QVariant _gas, QVariant _gasPrice) |
|||
{ |
|||
return toQJS(client()->transact(to<Secret>(_secret), to<u256>(_amount), bytes(_code.data(), _code.data() + _code.size()), bytes(_init.data(), _init.data() + _init.size()), to<u256>(_gas), to<u256>(_gasPrice))); |
|||
} |
|||
|
|||
void QEthereum::transact(QVariant _secret, QVariant _amount, QVariant _dest, QByteArray _data, QVariant _gas, QVariant _gasPrice) |
|||
{ |
|||
client()->transact(to<Secret>(_secret), to<u256>(_amount), to<Address>(_dest), bytes(_data.data(), _data.data() + _data.size()), to<u256>(_gas), to<u256>(_gasPrice)); |
|||
} |
@ -0,0 +1,339 @@ |
|||
#pragma once |
|||
|
|||
#include <QtCore/QAbstractListModel> |
|||
#include <libethereum/CommonEth.h> |
|||
#include <libethereum/CommonIO.h> |
|||
|
|||
namespace eth { |
|||
class Client; |
|||
class State; |
|||
} |
|||
|
|||
class QQmlEngine; |
|||
class QJSEngine; |
|||
|
|||
class QEthereum; |
|||
class QmlAccount; |
|||
class QmlEthereum; |
|||
|
|||
extern eth::Client* g_qmlClient; |
|||
extern QObject* g_qmlMain; |
|||
|
|||
Q_DECLARE_METATYPE(eth::u256) |
|||
Q_DECLARE_METATYPE(eth::Address) |
|||
Q_DECLARE_METATYPE(eth::Secret) |
|||
Q_DECLARE_METATYPE(eth::KeyPair) |
|||
Q_DECLARE_METATYPE(QEthereum*) |
|||
Q_DECLARE_METATYPE(QmlAccount*) |
|||
Q_DECLARE_METATYPE(QmlEthereum*) |
|||
|
|||
class QmlU256Helper: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
QmlU256Helper(QObject* _p = nullptr): QObject(_p) {} |
|||
|
|||
Q_INVOKABLE eth::u256 add(eth::u256 _a, eth::u256 _b) const { return _a + _b; } |
|||
Q_INVOKABLE eth::u256 sub(eth::u256 _a, eth::u256 _b) const { return _a - _b; } |
|||
Q_INVOKABLE eth::u256 mul(eth::u256 _a, int _b) const { return _a * _b; } |
|||
Q_INVOKABLE eth::u256 mul(int _a, eth::u256 _b) const { return _a * _b; } |
|||
Q_INVOKABLE eth::u256 div(eth::u256 _a, int _b) const { return _a / _b; } |
|||
|
|||
Q_INVOKABLE eth::u256 wei(double _s) const { return (eth::u256)_s; } |
|||
Q_INVOKABLE eth::u256 szabo(double _s) const { return (eth::u256)(_s * (double)eth::szabo); } |
|||
Q_INVOKABLE eth::u256 finney(double _s) const { return (eth::u256)(_s * (double)eth::finney); } |
|||
Q_INVOKABLE eth::u256 ether(double _s) const { return (eth::u256)(_s * (double)eth::ether); } |
|||
Q_INVOKABLE eth::u256 wei(unsigned _s) const { return (eth::u256)_s; } |
|||
Q_INVOKABLE eth::u256 szabo(unsigned _s) const { return (eth::u256)(_s * eth::szabo); } |
|||
Q_INVOKABLE eth::u256 finney(unsigned _s) const { return (eth::u256)(_s * eth::finney); } |
|||
Q_INVOKABLE eth::u256 ether(unsigned _s) const { return (eth::u256)(_s * eth::ether); } |
|||
Q_INVOKABLE double toWei(eth::u256 _t) const { return (double)_t; } |
|||
Q_INVOKABLE double toSzabo(eth::u256 _t) const { return toWei(_t) / (double)eth::szabo; } |
|||
Q_INVOKABLE double toFinney(eth::u256 _t) const { return toWei(_t) / (double)eth::finney; } |
|||
Q_INVOKABLE double toEther(eth::u256 _t) const { return toWei(_t) / (double)eth::ether; } |
|||
|
|||
Q_INVOKABLE double value(eth::u256 _t) const { return (double)_t; } |
|||
|
|||
Q_INVOKABLE QString stringOf(eth::u256 _t) const { return QString::fromStdString(eth::formatBalance(_t)); } |
|||
}; |
|||
|
|||
class QmlKeyHelper: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
QmlKeyHelper(QObject* _p = nullptr): QObject(_p) {} |
|||
|
|||
Q_INVOKABLE eth::KeyPair create() const { return eth::KeyPair::create(); } |
|||
Q_INVOKABLE eth::Address address(eth::KeyPair _p) const { return _p.address(); } |
|||
Q_INVOKABLE eth::Secret secret(eth::KeyPair _p) const { return _p.secret(); } |
|||
Q_INVOKABLE eth::KeyPair keypair(eth::Secret _k) const { return eth::KeyPair(_k); } |
|||
|
|||
Q_INVOKABLE bool isNull(eth::Address _a) const { return !_a; } |
|||
|
|||
Q_INVOKABLE eth::Address addressOf(QString _s) const { return eth::Address(_s.toStdString()); } |
|||
Q_INVOKABLE QString stringOf(eth::Address _a) const { return QString::fromStdString(eth::toHex(_a.asArray())); } |
|||
Q_INVOKABLE QString toAbridged(eth::Address _a) const { return QString::fromStdString(_a.abridged()); } |
|||
}; |
|||
|
|||
class QmlAccount: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
QmlAccount(QObject* _p = nullptr); |
|||
virtual ~QmlAccount(); |
|||
|
|||
Q_INVOKABLE QmlEthereum* ethereum() const { return m_eth; } |
|||
Q_INVOKABLE eth::u256 balance() const; |
|||
Q_INVOKABLE double txCount() const; |
|||
Q_INVOKABLE bool isContract() const; |
|||
|
|||
// TODO: past transactions models.
|
|||
|
|||
public slots: |
|||
void setEthereum(QmlEthereum* _eth); |
|||
|
|||
signals: |
|||
void changed(); |
|||
void ethChanged(); |
|||
|
|||
private: |
|||
QmlEthereum* m_eth = nullptr; |
|||
eth::Address m_address; |
|||
|
|||
Q_PROPERTY(eth::u256 balance READ balance NOTIFY changed STORED false) |
|||
Q_PROPERTY(double txCount READ txCount NOTIFY changed STORED false) |
|||
Q_PROPERTY(bool isContract READ isContract NOTIFY changed STORED false) |
|||
Q_PROPERTY(eth::Address address MEMBER m_address NOTIFY changed) |
|||
Q_PROPERTY(QmlEthereum* ethereum READ ethereum WRITE setEthereum NOTIFY ethChanged) |
|||
}; |
|||
|
|||
class QmlEthereum: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
QmlEthereum(QObject* _p = nullptr); |
|||
virtual ~QmlEthereum(); |
|||
|
|||
eth::Client* client() const; |
|||
|
|||
static QObject* constructU256Helper(QQmlEngine*, QJSEngine*) { return new QmlU256Helper; } |
|||
static QObject* constructKeyHelper(QQmlEngine*, QJSEngine*) { return new QmlKeyHelper; } |
|||
|
|||
Q_INVOKABLE eth::Address coinbase() const; |
|||
|
|||
Q_INVOKABLE bool isListening() const; |
|||
Q_INVOKABLE bool isMining() const; |
|||
|
|||
Q_INVOKABLE eth::u256 balanceAt(eth::Address _a) const; |
|||
Q_INVOKABLE double txCountAt(eth::Address _a) const; |
|||
Q_INVOKABLE bool isContractAt(eth::Address _a) const; |
|||
|
|||
Q_INVOKABLE unsigned peerCount() const; |
|||
|
|||
Q_INVOKABLE QmlEthereum* self() { return this; } |
|||
|
|||
public slots: |
|||
void transact(eth::Secret _secret, eth::Address _dest, eth::u256 _amount, eth::u256 _gasPrice, eth::u256 _gas, QByteArray _data); |
|||
void transact(eth::Secret _secret, eth::u256 _amount, eth::u256 _gasPrice, eth::u256 _gas, QByteArray _code, QByteArray _init); |
|||
void setCoinbase(eth::Address); |
|||
void setMining(bool _l); |
|||
|
|||
void setListening(bool _l); |
|||
|
|||
signals: |
|||
void changed(); |
|||
// void netChanged();
|
|||
// void miningChanged();
|
|||
|
|||
private: |
|||
Q_PROPERTY(eth::Address coinbase READ coinbase WRITE setCoinbase NOTIFY changed) |
|||
Q_PROPERTY(bool listening READ isListening WRITE setListening) |
|||
Q_PROPERTY(bool mining READ isMining WRITE setMining) |
|||
}; |
|||
|
|||
template <class T> T to(QVariant const& _s) { if (_s.type() != QVariant::String) return T(); auto s = _s.toString().toLatin1(); assert(s.size() == sizeof(T)); return *(T*)s.data(); } |
|||
template <class T> QVariant toQJS(T const& _s) { QLatin1String ret((char*)&_s, sizeof(T)); assert(QVariant(QString(ret)).toString().toLatin1().size() == sizeof(T)); assert(*(T*)(QVariant(QString(ret)).toString().toLatin1().data()) == _s); return QVariant(QString(ret)); } |
|||
|
|||
class U256Helper: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
U256Helper(QObject* _p = nullptr): QObject(_p) {} |
|||
|
|||
static eth::u256 in(QVariant const& _s) { return to<eth::u256>(_s); } |
|||
static QVariant out(eth::u256 const& _s) { return toQJS(_s); } |
|||
|
|||
Q_INVOKABLE QVariant add(QVariant _a, QVariant _b) const { return out(in(_a) + in(_b)); } |
|||
Q_INVOKABLE QVariant sub(QVariant _a, QVariant _b) const { return out(in(_a) - in(_b)); } |
|||
Q_INVOKABLE QVariant mul(QVariant _a, int _b) const { return out(in(_a) * in(_b)); } |
|||
Q_INVOKABLE QVariant mul(int _a, QVariant _b) const { return out(in(_a) * in(_b)); } |
|||
Q_INVOKABLE QVariant div(QVariant _a, int _b) const { return out(in(_a) / in(_b)); } |
|||
|
|||
Q_INVOKABLE QVariant wei(double _s) const { return out(eth::u256(_s)); } |
|||
Q_INVOKABLE QVariant szabo(double _s) const { return out(eth::u256(_s * (double)eth::szabo)); } |
|||
Q_INVOKABLE QVariant finney(double _s) const { return out(eth::u256(_s * (double)eth::finney)); } |
|||
Q_INVOKABLE QVariant ether(double _s) const { return out(eth::u256(_s * (double)eth::ether)); } |
|||
Q_INVOKABLE QVariant wei(unsigned _s) const { return value(_s); } |
|||
Q_INVOKABLE QVariant szabo(unsigned _s) const { return out(eth::u256(_s) * eth::szabo); } |
|||
Q_INVOKABLE QVariant finney(unsigned _s) const { return out(eth::u256(_s) * eth::finney); } |
|||
Q_INVOKABLE QVariant ether(unsigned _s) const { return out(eth::u256(_s) * eth::ether); } |
|||
Q_INVOKABLE double toWei(QVariant _t) const { return toValue(_t); } |
|||
Q_INVOKABLE double toSzabo(QVariant _t) const { return toWei(_t) / (double)eth::szabo; } |
|||
Q_INVOKABLE double toFinney(QVariant _t) const { return toWei(_t) / (double)eth::finney; } |
|||
Q_INVOKABLE double toEther(QVariant _t) const { return toWei(_t) / (double)eth::ether; } |
|||
|
|||
Q_INVOKABLE QVariant value(unsigned _s) const { return out(eth::u256(_s)); } |
|||
Q_INVOKABLE double toValue(QVariant _t) const { return (double)in(_t); } |
|||
|
|||
Q_INVOKABLE QString ethOf(QVariant _t) const { return QString::fromStdString(eth::formatBalance(in(_t))); } |
|||
Q_INVOKABLE QString stringOf(QVariant _t) const { return QString::fromStdString(eth::toString(in(_t))); } |
|||
|
|||
Q_INVOKABLE QByteArray bytesOf(QVariant _t) const { eth::h256 b = in(_t); return QByteArray((char const*)&b, sizeof(eth::h256)); } |
|||
|
|||
Q_INVOKABLE QVariant fromAddress(QVariant/*eth::Address*/ _a) const { return out((eth::u160)to<eth::Address>(_a)); } |
|||
Q_INVOKABLE QVariant toAddress(QVariant/*eth::Address*/ _a) const { return toQJS<eth::Address>((eth::u160)in(_a)); } |
|||
|
|||
Q_INVOKABLE bool isNull(QVariant/*eth::Address*/ _a) const { return !in(_a); } |
|||
}; |
|||
|
|||
class KeyHelper: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
KeyHelper(QObject* _p = nullptr): QObject(_p) {} |
|||
|
|||
static eth::Address in(QVariant const& _s) { return to<eth::Address>(_s); } |
|||
static QVariant out(eth::Address const& _s) { return toQJS(_s); } |
|||
|
|||
Q_INVOKABLE QVariant/*eth::KeyPair*/ create() const { return toQJS(eth::KeyPair::create()); } |
|||
Q_INVOKABLE QVariant/*eth::Address*/ address(QVariant/*eth::KeyPair*/ _p) const { return out(to<eth::KeyPair>(_p).address()); } |
|||
Q_INVOKABLE QVariant/*eth::Secret*/ secret(QVariant/*eth::KeyPair*/ _p) const { return toQJS(to<eth::KeyPair>(_p).secret()); } |
|||
Q_INVOKABLE QVariant/*eth::KeyPair*/ keypair(QVariant/*eth::Secret*/ _k) const { return toQJS(eth::KeyPair(to<eth::Secret>(_k))); } |
|||
|
|||
Q_INVOKABLE bool isNull(QVariant/*eth::Address*/ _a) const { return !in(_a); } |
|||
|
|||
Q_INVOKABLE QVariant/*eth::Address*/ addressOf(QString _s) const { return out(eth::Address(_s.toStdString())); } |
|||
Q_INVOKABLE QString stringOf(QVariant/*eth::Address*/ _a) const { return QString::fromStdString(eth::toHex(in(_a).asArray())); } |
|||
Q_INVOKABLE QString toAbridged(QVariant/*eth::Address*/ _a) const { return QString::fromStdString(in(_a).abridged()); } |
|||
|
|||
}; |
|||
|
|||
class BytesHelper: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
BytesHelper(QObject* _p = nullptr): QObject(_p) {} |
|||
|
|||
Q_INVOKABLE QByteArray concat(QVariant _v, QVariant _w) const |
|||
{ |
|||
QByteArray ba; |
|||
if (_v.type() == QVariant::ByteArray) |
|||
ba = _v.toByteArray(); |
|||
else |
|||
ba = _v.toString().toLatin1(); |
|||
QByteArray ba2; |
|||
if (_w.type() == QVariant::ByteArray) |
|||
ba2 = _w.toByteArray(); |
|||
else |
|||
ba2 = _w.toString().toLatin1(); |
|||
ba.append(ba2); |
|||
return QByteArray(ba); |
|||
} |
|||
Q_INVOKABLE QByteArray concat(QByteArray _v, QByteArray _w) const |
|||
{ |
|||
_v.append(_w); |
|||
return _v; |
|||
} |
|||
Q_INVOKABLE QByteArray fromString(QString _s) const |
|||
{ |
|||
return _s.toLatin1(); |
|||
} |
|||
Q_INVOKABLE QByteArray fromString(QString _s, unsigned _padding) const |
|||
{ |
|||
QByteArray b = _s.toLatin1(); |
|||
for (unsigned i = b.size(); i < _padding; ++i) |
|||
b.append((char)0); |
|||
b.resize(_padding); |
|||
return b; |
|||
} |
|||
Q_INVOKABLE QString toString(QByteArray _b) const |
|||
{ |
|||
while (_b.size() && !_b[_b.size() - 1]) |
|||
_b.resize(_b.size() - 1); |
|||
return QString::fromLatin1(_b); |
|||
} |
|||
Q_INVOKABLE QVariant u256of(QByteArray _s) const |
|||
{ |
|||
while (_s.size() < 32) |
|||
_s.append((char)0); |
|||
eth::h256 ret((uint8_t const*)_s.data(), eth::h256::ConstructFromPointer); |
|||
return toQJS<eth::u256>(ret); |
|||
} |
|||
}; |
|||
|
|||
class QEthereum: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
QEthereum(QObject* _p, eth::Client* _c, QList<eth::KeyPair> _accounts); |
|||
virtual ~QEthereum(); |
|||
|
|||
eth::Client* client() const; |
|||
|
|||
Q_INVOKABLE QVariant/*eth::Address*/ coinbase() const; |
|||
|
|||
Q_INVOKABLE bool isListening() const; |
|||
Q_INVOKABLE bool isMining() const; |
|||
|
|||
Q_INVOKABLE QVariant/*eth::u256*/ balanceAt(QVariant/*eth::Address*/ _a) const; |
|||
Q_INVOKABLE QVariant/*eth::u256*/ storageAt(QVariant/*eth::Address*/ _a, QVariant/*eth::u256*/ _p) const; |
|||
Q_INVOKABLE double txCountAt(QVariant/*eth::Address*/ _a) const; |
|||
Q_INVOKABLE bool isContractAt(QVariant/*eth::Address*/ _a) const; |
|||
|
|||
Q_INVOKABLE QVariant gasPrice() const { return toQJS(10 * eth::szabo); } |
|||
|
|||
Q_INVOKABLE QString ethTest() const { return "Hello world!"; } |
|||
|
|||
Q_INVOKABLE QVariant/*eth::KeyPair*/ key() const; |
|||
Q_INVOKABLE QList<QVariant/*eth::KeyPair*/> keys() const; |
|||
Q_INVOKABLE QVariant/*eth::Address*/ account() const; |
|||
Q_INVOKABLE QList<QVariant/*eth::Address*/> accounts() const; |
|||
|
|||
Q_INVOKABLE unsigned peerCount() const; |
|||
|
|||
Q_INVOKABLE QEthereum* self() { return this; } |
|||
|
|||
Q_INVOKABLE QVariant create(QVariant _secret, QVariant _amount, QByteArray _code, QByteArray _init, QVariant _gas, QVariant _gasPrice); |
|||
Q_INVOKABLE void transact(QVariant _secret, QVariant _amount, QVariant _dest, QByteArray _data, QVariant _gas, QVariant _gasPrice); |
|||
|
|||
eth::u256 balanceAt(eth::Address _a) const; |
|||
double txCountAt(eth::Address _a) const; |
|||
bool isContractAt(eth::Address _a) const; |
|||
|
|||
public slots: |
|||
void setCoinbase(QVariant/*eth::Address*/); |
|||
void setMining(bool _l); |
|||
|
|||
void setListening(bool _l); |
|||
|
|||
signals: |
|||
void changed(); |
|||
// void netChanged();
|
|||
// void miningChanged();
|
|||
|
|||
private: |
|||
// Q_PROPERTY(QVariant coinbase READ coinbase WRITE setCoinbase NOTIFY changed)
|
|||
// Q_PROPERTY(bool listening READ isListening WRITE setListening)
|
|||
// Q_PROPERTY(bool mining READ isMining WRITE setMining)
|
|||
|
|||
eth::Client* m_client; |
|||
QList<eth::KeyPair> m_accounts; |
|||
}; |
@ -0,0 +1,48 @@ |
|||
cmake_policy(SET CMP0015 NEW) |
|||
|
|||
aux_source_directory(. SRC_LIST) |
|||
|
|||
include_directories(../libethereum) |
|||
link_directories(../libethereum) |
|||
|
|||
add_executable(neth ${SRC_LIST}) |
|||
|
|||
if (${TARGET_PLATFORM} STREQUAL "w64") |
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") |
|||
target_link_libraries(neth gcc) |
|||
target_link_libraries(neth gdi32) |
|||
target_link_libraries(neth ws2_32) |
|||
target_link_libraries(neth mswsock) |
|||
target_link_libraries(neth shlwapi) |
|||
target_link_libraries(neth iphlpapi) |
|||
target_link_libraries(neth cryptopp) |
|||
target_link_libraries(neth ncurses) |
|||
target_link_libraries(neth form) |
|||
target_link_libraries(neth boost_system-mt-s) |
|||
target_link_libraries(neth boost_filesystem-mt-s) |
|||
target_link_libraries(neth boost_thread_win32-mt-s) |
|||
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) |
|||
elseif (UNIX) |
|||
target_link_libraries(neth ncurses) |
|||
target_link_libraries(neth form) |
|||
else () |
|||
target_link_libraries(neth ${CRYPTOPP_LIBRARIES}) |
|||
target_link_libraries(neth boost_system) |
|||
target_link_libraries(neth boost_filesystem) |
|||
target_link_libraries(neth ncurses) |
|||
target_link_libraries(neth form) |
|||
find_package(Threads REQUIRED) |
|||
target_link_libraries(neth ${CMAKE_THREAD_LIBS_INIT}) |
|||
endif () |
|||
|
|||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") |
|||
include_directories(/usr/local/include) |
|||
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") |
|||
|
|||
target_link_libraries(neth ethereum) |
|||
target_link_libraries(neth miniupnpc) |
|||
target_link_libraries(neth leveldb) |
|||
target_link_libraries(neth gmp) |
|||
|
|||
install( TARGETS neth DESTINATION bin ) |
|||
|
File diff suppressed because it is too large
Loading…
Reference in new issue