Commit 04bc8b69 authored by cryptonotefoundation's avatar cryptonotefoundation

Initial commit

parents
.DS_Store
/build
/tags
cmake_minimum_required(VERSION 2.8)
include(CryptoNoteWallet.cmake)
project(${CN_PROJECT_NAME})
execute_process(COMMAND git log -1 --pretty=format:%h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_REVISION)
set(CRYPTONOTE_LIB cryptonote)
include_directories(${CMAKE_BINARY_DIR}
src
cryptonote/external
cryptonote/include
cryptonote/src
cryptonote/contrib/epee/include)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Widgets REQUIRED)
set(Boost_USE_STATIC_LIBS ON)
if(WIN32)
set(Boost_USE_STATIC_RUNTIME OFF)
else(WIN32)
set(Boost_USE_STATIC_RUNTIME ON)
endif(WIN32)
find_package(Boost 1.55 REQUIRED COMPONENTS date_time filesystem program_options regex serialization system thread chrono)
if ((${Boost_MAJOR_VERSION} EQUAL 1) AND (${Boost_MINOR_VERSION} EQUAL 54))
message(SEND_ERROR "Boost version 1.54 is unsupported, more details are available here http://goo.gl/RrCFmA")
endif ()
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
set(VERSION "")
configure_file("cryptonote/src/version.h.in" "version.h")
configure_file("src/CryptoNoteWalletConfig.h.in" "CryptoNoteWalletConfig.h")
add_definitions(-DGIT_REVISION=\"${GIT_REVISION}\")
set(CMAKE_AUTOMOC ON)
set(CRYPTONOTE_SOURCES
cryptonote/contrib/epee/include/misc_log_ex.cpp
cryptonote/contrib/epee/include/misc_os_dependent.cpp
cryptonote/contrib/epee/include/string_tools.cpp
cryptonote/external/miniupnpc/connecthostport.c
cryptonote/external/miniupnpc/igd_desc_parse.c
cryptonote/external/miniupnpc/minisoap.c
cryptonote/external/miniupnpc/miniupnpc.c
cryptonote/external/miniupnpc/miniwget.c
cryptonote/external/miniupnpc/minixml.c
cryptonote/external/miniupnpc/portlistingparse.c
cryptonote/external/miniupnpc/receivedata.c
cryptonote/external/miniupnpc/upnpcommands.c
cryptonote/external/miniupnpc/upnpreplyparse.c
cryptonote/src/common/base58.cpp
cryptonote/src/common/command_line.cpp
cryptonote/src/common/util.cpp
cryptonote/src/crypto/blake256.c
cryptonote/src/crypto/chacha8.c
cryptonote/src/crypto/crypto-ops-data.c
cryptonote/src/crypto/crypto-ops.c
cryptonote/src/crypto/crypto.cpp
cryptonote/src/crypto/groestl.c
cryptonote/src/crypto/hash-extra-blake.c
cryptonote/src/crypto/hash-extra-groestl.c
cryptonote/src/crypto/hash-extra-jh.c
cryptonote/src/crypto/hash-extra-skein.c
cryptonote/src/crypto/hash.c
cryptonote/src/crypto/jh.c
cryptonote/src/crypto/keccak.c
cryptonote/src/crypto/oaes_lib.c
cryptonote/src/crypto/random.c
cryptonote/src/crypto/skein.c
cryptonote/src/crypto/slow-hash.c
cryptonote/src/crypto/slow-hash.cpp
cryptonote/src/crypto/tree-hash.c
cryptonote/src/cryptonote_core/BlockIndex.cpp
cryptonote/src/cryptonote_core/CoreConfig.cpp
cryptonote/src/cryptonote_core/Currency.cpp
cryptonote/src/cryptonote_core/MinerConfig.cpp
cryptonote/src/cryptonote_core/Transaction.cpp
cryptonote/src/cryptonote_core/account.cpp
cryptonote/src/cryptonote_core/blockchain_storage.cpp
cryptonote/src/cryptonote_core/checkpoints.cpp
cryptonote/src/cryptonote_core/cryptonote_basic_impl.cpp
cryptonote/src/cryptonote_core/cryptonote_core.cpp
cryptonote/src/cryptonote_core/cryptonote_format_utils.cpp
cryptonote/src/cryptonote_core/cryptonote_serialization.cpp
cryptonote/src/cryptonote_core/difficulty.cpp
cryptonote/src/cryptonote_core/miner.cpp
cryptonote/src/cryptonote_core/tx_pool.cpp
cryptonote/src/inprocess_node/InProcessNode.cpp
cryptonote/src/inprocess_node/InProcessNodeErrors.cpp
cryptonote/src/node_rpc_proxy/NodeErrors.cpp
cryptonote/src/node_rpc_proxy/NodeRpcProxy.cpp
cryptonote/src/p2p/NetNodeConfig.cpp
cryptonote/src/serialization/BinaryInputStreamSerializer.cpp
cryptonote/src/serialization/BinaryOutputStreamSerializer.cpp
cryptonote/src/transfers/BlockchainSynchronizer.cpp
cryptonote/src/transfers/SynchronizationState.cpp
cryptonote/src/transfers/TransfersConsumer.cpp
cryptonote/src/transfers/TransfersContainer.cpp
cryptonote/src/transfers/TransfersSubscription.cpp
cryptonote/src/transfers/TransfersSynchronizer.cpp
cryptonote/src/wallet/KeysStorage.cpp
cryptonote/src/wallet/Wallet.cpp
cryptonote/src/wallet/WalletAsyncContextCounter.cpp
cryptonote/src/wallet/WalletErrors.cpp
cryptonote/src/wallet/WalletSerializer.cpp
cryptonote/src/wallet/WalletSerialization.cpp
cryptonote/src/wallet/WalletTransactionSender.cpp
cryptonote/src/wallet/WalletUnconfirmedTransactions.cpp
cryptonote/src/wallet/WalletUserTransactionsCache.cpp
cryptonote/src/wallet/LegacyKeysImporter.cpp
)
file(GLOB_RECURSE SOURCES src/*.cpp)
file(GLOB_RECURSE HEADERS src/*.h)
file(GLOB_RECURSE FORMS src/gui/ui/*.ui)
set(QRC src/resources.qrc)
qt5_wrap_ui(UIS ${FORMS})
qt5_add_resources(RCC ${QRC})
if (WIN32)
if (NOT MSVC)
message(FATAL_ERROR "Only MSVC is supported on this platform")
endif ()
add_definitions(/D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600 /DSTATICLIB)
include_directories(cryptonote/src/platform/msc)
set(PLATFORM_DIR Windows)
set(BUILD_PLATFORM WIN32)
set(BUILD_RESOURCES src/cryptonotewallet.rc)
set(QTMAIN Qt5::WinMain)
elseif (UNIX)
set(CRYPTONOTE_SOURCES ${CRYPTONOTE_SOURCES} cryptonote/external/miniupnpc/minissdpc.c)
if (APPLE)
enable_language(ASM)
file(GLOB_RECURSE OBJC_SOURCES src/*.mm)
set(SOURCES ${SOURCES} ${OBJC_SOURCES})
set(PLATFORM_DIR OSX)
set(MACOSX_BUNDLE_INFO_STRING "Cryptonote GUI wallet")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${VERSION_VERSION}.${VERSION_MINOR}.${VERSION_PATCH}")
set(MACOSX_BUNDLE_BUNDLE_NAME CryptonoteWallet)
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VERSION_VERSION}.${VERSION_MINOR}.${VERSION_PATCH}")
set(MACOSX_BUNDLE_BUNDLE_VERSION "$${VERSION_VERSION}.${VERSION_MINOR}.${VERSION_PATCH}")
find_package(Qt5PrintSupport REQUIRED)
include_directories(/usr/include/malloc)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -std=c++11 -stdlib=libc++")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -maes -D_DARWIN_C_SOURCE")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Cocoa -framework OpenGL -framework CoreFoundation -framework Carbon -framework IOKit -L/usr/lib")
set(MACOSX_BUNDLE_ICON_FILE cryptonote.icns)
set(APPLICATION_ICON src/images/cryptonote.icns)
set_source_files_properties(${APPLICATION_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set(BUILD_PLATFORM MACOSX_BUNDLE)
set(BUILD_RESOURCES ${APPLICATION_ICON})
GET_TARGET_PROPERTY(QT_LIB_DIR "${Qt5Widgets_LIBRARIES}" LOCATION)
GET_FILENAME_COMPONENT(QT_LIB_DIR "${QT_LIB_DIR}" PATH)
else(APPLE)
set(PLATFORM_DIR Linux)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -std=c++11")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -std=c11")
endif (APPLE)
endif ()
include_directories(cryptonote/src/Platform/${PLATFORM_DIR})
file(GLOB PLATFORM_SOURCES cryptonote/src/Platform/${PLATFORM_DIR}/System/*)
set(CRYPTONOTE_SOURCES ${CRYPTONOTE_SOURCES} ${PLATFORM_SOURCES})
add_library(${CRYPTONOTE_LIB} STATIC ${CRYPTONOTE_SOURCES})
set_target_properties(${CRYPTONOTE_LIB} PROPERTIES COMPILE_DEFINITIONS _GNU_SOURCE)
target_link_libraries(${CRYPTONOTE_LIB} ${Boost_LIBRARIES})
add_executable(${PROJECT_NAME} ${BUILD_PLATFORM} ${BUILD_RESOURCES} ${SOURCES} ${HEADERS} ${UIS} ${RCC})
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS _GNU_SOURCE)
target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} ${QTMAIN} ${CRYPTONOTE_LIB})
if (APPLE)
qt5_use_modules(${PROJECT_NAME} PrintSupport)
elseif (UNIX)
target_link_libraries(${PROJECT_NAME} -lpthread)
elseif (WIN32)
target_link_libraries(${PROJECT_NAME} Imm32 Iphlpapi Winmm)
endif (APPLE)
qt5_use_modules(${PROJECT_NAME} Widgets Gui)
set(CN_PROJECT_NAME "")
set(CN_CURRENCY_DISPLAY_NAME "")
set(CN_CURRENCY_TICKER "")
// Copyright (c) 2011-2015 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <QCoreApplication>
#include <common/util.h>
#include "CommandLineParser.h"
#include "CurrencyAdapter.h"
namespace WalletGui {
CommandLineParser::CommandLineParser() : QObject(), m_parser(), m_help_option(m_parser.addHelpOption()),
m_version_option(m_parser.addVersionOption()),
m_data_dir_option("data-dir", tr("Specify data directory"), tr("directory"), QString::fromStdString(tools::get_default_data_dir())) {
m_parser.setApplicationDescription(QString(tr("%1 wallet")).arg(CurrencyAdapter::instance().getCurrencyDisplayName()));
m_parser.addHelpOption();
m_parser.addVersionOption();
m_parser.addOption(m_data_dir_option);
}
CommandLineParser::~CommandLineParser() {
}
bool CommandLineParser::process() {
#ifdef Q_OS_WIN
return m_parser.parse(QCoreApplication::arguments());
#else
m_parser.process(*QCoreApplication::instance());
return true;
#endif
}
bool CommandLineParser::hasHelpOption() const {
return m_parser.isSet(m_help_option);
}
bool CommandLineParser::hasVersionOption() const {
return m_parser.isSet(m_version_option);
}
QString CommandLineParser::errorText() const {
return m_parser.errorText();
}
QString CommandLineParser::helpText() const {
return m_parser.helpText();
}
QString CommandLineParser::getDataDir() const {
return m_parser.value(m_data_dir_option);
}
}
// Copyright (c) 2011-2015 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <QCommandLineParser>
#include <QObject>
namespace WalletGui {
class CommandLineParser : public QObject {
Q_OBJECT
Q_DISABLE_COPY(CommandLineParser)
public:
CommandLineParser();
~CommandLineParser();
bool process();
bool hasHelpOption() const;
bool hasVersionOption() const;
QString errorText() const;
QString helpText() const;
QString getDataDir() const;
private:
QCommandLineParser m_parser;
QCommandLineOption m_help_option;
QCommandLineOption m_version_option;
QCommandLineOption m_data_dir_option;
};
}
// Copyright (c) 2011-2015 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "CryptoNote.h"
#include "cryptonote_core/cryptonote_basic_impl.h"
#include "cryptonote_core/cryptonote_format_utils.h"
#include "cryptonote_core/Currency.h"
#include "node_rpc_proxy/NodeRpcProxy.h"
#include "cryptonote_core/CoreConfig.h"
#include "cryptonote_core/cryptonote_core.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
#include "inprocess_node/InProcessNode.h"
#include "p2p/net_node.h"
#include "wallet/Wallet.h"
namespace WalletGui {
namespace {
bool parsePaymentId(const std::string& payment_id_str, crypto::hash& payment_id) {
cryptonote::blobdata payment_id_data;
if (!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data)) {
return false;
}
if (sizeof(crypto::hash) != payment_id_data.size()) {
return false;
}
payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_data.data());
return true;
}
std::string convertPaymentId(const std::string& paymentIdString) {
if (paymentIdString.empty()) {
return "";
}
crypto::hash paymentId;
if (!parsePaymentId(paymentIdString, paymentId)) {
std::stringstream errorStr;
errorStr << "Payment id has invalid format: \"" + paymentIdString + "\", expected 64-character string";
throw std::runtime_error(errorStr.str());
}
std::vector<uint8_t> extra;
std::string extra_nonce;
cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, paymentId);
if (!cryptonote::add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
std::stringstream errorStr;
errorStr << "Something went wrong with payment_id. Please check its format: \"" + paymentIdString + "\", expected 64-character string";
throw std::runtime_error(errorStr.str());
}
return std::string(extra.begin(), extra.end());
}
std::string extractPaymentId(const std::string& extra) {
std::vector<cryptonote::tx_extra_field> extraFields;
std::vector<uint8_t> extraVector;
std::copy(extra.begin(), extra.end(), std::back_inserter(extraVector));
if (!cryptonote::parse_tx_extra(extraVector, extraFields)) {
throw std::runtime_error("Can't parse extra");
}
std::string result;
cryptonote::tx_extra_nonce extra_nonce;
if (cryptonote::find_tx_extra_field_by_type(extraFields, extra_nonce)) {
crypto::hash paymentIdHash;
if (cryptonote::get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, paymentIdHash)) {
unsigned char* buff = reinterpret_cast<unsigned char *>(&paymentIdHash);
for (size_t i = 0; i < sizeof(paymentIdHash); ++i) {
result.push_back("0123456789ABCDEF"[buff[i] >> 4]);
result.push_back("0123456789ABCDEF"[buff[i] & 15]);
}
}
}
return result;
}
}
Node::~Node() {
}
class RpcNode : CryptoNote::INodeObserver, public Node {
public:
RpcNode(const cryptonote::Currency& currency, INodeCallback& callback, const std::string& nodeHost, unsigned short nodePort) :
m_callback(callback),
m_currency(currency),
m_node(nodeHost, nodePort) {
m_node.addObserver(this);
}
~RpcNode() override {
}
void init(const std::function<void(std::error_code)>& callback) override {
m_node.init(callback);
}
void deinit() override {
}
std::string convertPaymentId(const std::string& paymentIdString) override {
return WalletGui::convertPaymentId(paymentIdString);
}
std::string extractPaymentId(const std::string& extra) override {
return WalletGui::extractPaymentId(extra);
}
uint64_t getLastKnownBlockHeight() const override {
return m_node.getLastKnownBlockHeight();
}
uint64_t getLastLocalBlockHeight() const override {
return m_node.getLastLocalBlockHeight();
}
uint64_t getLastLocalBlockTimestamp() const override {
return m_node.getLastLocalBlockTimestamp();
}
uint64_t getPeerCount() const override {
return m_node.getPeerCount();
}
CryptoNote::IWallet* createWallet() override {
return new CryptoNote::Wallet(m_currency, m_node);
}
private:
INodeCallback& m_callback;
const cryptonote::Currency& m_currency;
cryptonote::NodeRpcProxy m_node;
void peerCountUpdated(size_t count) {
m_callback.peerCountUpdated(*this, count);
}
void localBlockchainUpdated(uint64_t height) {
m_callback.localBlockchainUpdated(*this, height);
}
void lastKnownBlockHeightUpdated(uint64_t height) {
m_callback.lastKnownBlockHeightUpdated(*this, height);
}
};
class InprocessNode : CryptoNote::INodeObserver, public Node {
public:
InprocessNode(const cryptonote::Currency& currency, INodeCallback& callback, const cryptonote::CoreConfig& coreConfig) :
m_callback(callback),
m_currency(currency),
m_coreConfig(coreConfig),
m_core(m_currency, nullptr),
m_protocolHandler(m_core, nullptr),
m_nodeServer(m_protocolHandler),
m_node(m_core, m_protocolHandler) {
m_core.set_cryptonote_protocol(&m_protocolHandler);
m_protocolHandler.set_p2p_endpoint(&m_nodeServer);
cryptonote::checkpoints checkpoints;
for (const cryptonote::CheckpointData& checkpoint : cryptonote::CHECKPOINTS) {
checkpoints.add_checkpoint(checkpoint.height, checkpoint.blockId);
}
m_core.set_checkpoints(std::move(checkpoints));
}
~InprocessNode() override {
}
void init(const std::function<void(std::error_code)>& callback) override {
if (!m_core.init(m_coreConfig, cryptonote::MinerConfig(), true)) {
callback(make_error_code(cryptonote::error::NOT_INITIALIZED));
return;
}
if (!m_nodeServer.init(nodetool::NetNodeConfig(), false)) {
m_core.deinit();
callback(make_error_code(cryptonote::error::NOT_INITIALIZED));
return;
}
m_node.init([this, callback](std::error_code ec) {
m_node.addObserver(this);
callback(ec);
});
m_nodeServer.run();
m_nodeServer.deinit();
m_core.deinit();
m_node.shutdown();
}
void deinit() override {
m_nodeServer.send_stop_signal();
}
std::string convertPaymentId(const std::string& paymentIdString) override {
return WalletGui::convertPaymentId(paymentIdString);
}
std::string extractPaymentId(const std::string& extra) override {
return WalletGui::extractPaymentId(extra);
}
uint64_t getLastKnownBlockHeight() const override {
return m_node.getLastKnownBlockHeight();
}
uint64_t getLastLocalBlockHeight() const override {
return m_node.getLastLocalBlockHeight();
}
uint64_t getLastLocalBlockTimestamp() const override {
return m_node.getLastLocalBlockTimestamp();
}
uint64_t getPeerCount() const override {
return m_node.getPeerCount();
}
CryptoNote::IWallet* createWallet() override {
return new CryptoNote::Wallet(m_currency, m_node);
}
private:
INodeCallback& m_callback;
const cryptonote::Currency& m_currency;
cryptonote::CoreConfig m_coreConfig;
cryptonote::core m_core;
cryptonote::t_cryptonote_protocol_handler<cryptonote::core> m_protocolHandler;
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core>> m_nodeServer;
CryptoNote::InProcessNode m_node;
std::future<bool> m_nodeServerFuture;
void peerCountUpdated(size_t count) {
m_callback.peerCountUpdated(*this, count);
}
void localBlockchainUpdated(uint64_t height) {
m_callback.localBlockchainUpdated(*this, height);
}
void lastKnownBlockHeightUpdated(uint64_t height) {
m_callback.lastKnownBlockHeightUpdated(*this, height);
}
};
Node* createRpcNode(const cryptonote::Currency& currency, INodeCallback& callback, const std::string& nodeHost, unsigned short nodePort) {
return new RpcNode(currency, callback, nodeHost, nodePort);
}
Node* createInprocessNode(const cryptonote::Currency& currency, INodeCallback& callback, const cryptonote::CoreConfig& coreConfig) {
return new InprocessNode(currency, callback, coreConfig);
}
}
// Copyright (c) 2011-2015 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <functional>
#include <memory>
#include <string>
#include <system_error>
#include <cryptonote_core/CoreConfig.h>
namespace cryptonote {
class Currency;
}
namespace CryptoNote {
class INode;
class IWallet;
}
namespace WalletGui {
class Node {
public:
virtual ~Node() = 0;
virtual void init(const std::function<void(std::error_code)>& callback) = 0;
virtual void deinit() = 0;
virtual std::string convertPaymentId(const std::string& paymentIdString) = 0;
virtual std::string extractPaymentId(const std::string& extra) = 0;
virtual uint64_t getLastKnownBlockHeight() const = 0;
virtual uint64_t getLastLocalBlockHeight() const = 0;
virtual uint64_t getLastLocalBlockTimestamp() const = 0;
virtual uint64_t getPeerCount() const = 0;
virtual CryptoNote::IWallet* createWallet() = 0;
};
class INodeCallback {
public:
virtual void peerCountUpdated(Node& node, size_t count) = 0;
virtual void localBlockchainUpdated(Node& node, uint64_t height) = 0;
virtual void lastKnownBlockHeightUpdated(Node& node, uint64_t height) = 0;
};
Node* createRpcNode(const cryptonote::Currency& currency, INodeCallback& callback, const std::string& nodeHost, unsigned short nodePort);
Node* createInprocessNode(const cryptonote::Currency& currency, INodeCallback& callback, const cryptonote::CoreConfig& coreConfig);
}
#pragma once
namespace WalletGui {
const char WALLET_CURRENCY_DISPLAY_NAME[] = "@CN_CURRENCY_DISPLAY_NAME@";
const char WALLET_CURRENCY_TICKER[] = "@CN_CURRENCY_TICKER@";
}
// Copyright (c) 2011-2015 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "CurrencyAdapter.h"
#include "CryptoNoteWalletConfig.h"
namespace WalletGui {
CurrencyAdapter& CurrencyAdapter::instance() {
static CurrencyAdapter inst;
return inst;
}
CurrencyAdapter::CurrencyAdapter() : m_currency(cryptonote::CurrencyBuilder().currency()) {
}
CurrencyAdapter::~CurrencyAdapter() {
}
const cryptonote::Currency& CurrencyAdapter::getCurrency() {
return m_currency;
}
quintptr CurrencyAdapter::getNumberOfDecimalPlaces() const {
return m_currency.numberOfDecimalPlaces();
}
QString CurrencyAdapter::getCurrencyDisplayName() const {
return WALLET_CURRENCY_DISPLAY_NAME;
}
QString CurrencyAdapter::getCurrencyName() const {
return cryptonote::CRYPTONOTE_NAME;
}
QString CurrencyAdapter::getCurrencyTicker() const {
return WALLET_CURRENCY_TICKER;
}
QString CurrencyAdapter::formatAmount(quint64 _amount) const {
QString result = QString::number(_amount);
if (result.length() < getNumberOfDecimalPlaces() + 1) {
result = result.rightJustified(getNumberOfDecimalPlaces() + 1, '0');
}
quint32 dot_pos = result.length() - getNumberOfDecimalPlaces();
for (quint32 pos = result.length() - 1; pos > dot_pos + 1; --pos) {
if (result[pos] == '0') {
result.remove(pos, 1);
} else {
break;
}
}
result.insert(dot_pos, ".");
for (qint32 pos = dot_pos - 3; pos > 0; pos -= 3) {
if (result[pos - 1].isDigit()) {
result.insert(pos, ','