forked from wownero/wownero
Merge pull request #872
release-v0.4.0.1beb6d92
CMake: GPL 'libutils' script removed (Ilya Kitaev)4e5521d
PendingTransactionImpl: pointer->reference (Ilya Kitaev)7b7cf21
commented regex (Ilya Kitaev)eec0f57
Typo fixed (Ilya Kitaev)f1c4a37
Wallet::createTransaction: added mixin_count param (Ilya Kitaev)3318add
double/string to monero integer convertion methods (Ilya Kitaev)3ac20a4
wallet::default_mixin exposed to public interface as Wallet::setDefaultMixin, Wallet::defaultMixin; wallet::create_transaction_2 used in Wallet::createTransaction (Ilya Kitaev)c554055
Wallet::filename, Wallet::keysFilename, tests for move wallet (Ilya Kitaev)8f9d98b
removed unused "using" (Ilya Kitaev)2facbe7
Wallet API : WalletManager::findWallets() added (Ilya Kitaev)ec949c3
scripts for faster test wallets generation (Ilya Kitaev)7f3d28f
regenerated test wallets, basic functions got broken (Ilya Kitaev)4327548
installing wallet_api header (Ilya Kitaev)7ac1342
cmake: BUILD_TESTS as option explicitly; added missed dependency (Ilya Kitaev)1f0d016
cmake libutils dependency added (Ilya Kitaev)d43ad22
all wallet dependencies merged to single static lib (Ilya Kitaev)9ae4e87
WalletListener::moneyReceived test (Ilya Kitaev)40087a7
WalletListener::moneySpent test (Ilya Kitaev)27d86b7
WalletListener::moneySpent(), WalletListener::moneyReceived() (Ilya Kitaev)ff52c67
i_wallet_callback: virtual dtor (Ilya Kitaev)5dbd2b8
started WalletListener (Ilya Kitaev)71131a8
TransactionHistory continued (Ilya Kitaev)9311934
TransactionHistory continued (Ilya Kitaev)566166a
merged with upstream (Ilya Kitaev)53a97bd
Wallet API: transaction history in progress (Ilya Kitaev)02c9df5
Wallet API : transaction history in progress (Ilya Kitaev)a213887
transaction history api in progress (Ilya Kitaev)b6aaf53
transaction history api in progress (Ilya Kitaev)f83f3cb
api implementation splitted over separate files (Ilya Kitaev)4e1c2dc
TransactionInfo / TransactionHistory APIs design (Ilya Kitaev)1774d95
TODOs for Transaction/Transfer interface (Ilya Kitaev)d97e9ef
Transaction API continued (Ilya Kitaev)079fbd3
Wallet::createTransaction API introduced (Ilya Kitaev)ee5bb17
Wallet::transfer() continued (Ilya Kitaev)c37c856
Wallet::transfer in progress (Ilya Kitaev)830c19c
Wallet::refresh + tests (Ilya Kitaev)1ae9cdc
"testnet" is default parameter (Ilya Kitaev)2157a9a
testnet option, Wallet::balance(), Wallet::unlockedBalance() (Ilya Kitaev)8790904
- testnet option added to api; (Ilya Kitaev)2cce329
wallet2::store() implemented within wallet2::store_to (Ilya Kitaev)d608647
WalletManager::findWallets: searching by "keys" files instead of "address.txt" files (Ilya Kitaev)ca61153
Wallet: payment id and integrated address (Ilya Kitaev)23cbf6f
PendingTransactionImpl: pointer->reference (Ilya Kitaev)c1d9e7c
commented regex (Ilya Kitaev)563baf1
Typo fixed (Ilya Kitaev)2efec04
Wallet::createTransaction: added mixin_count param (Ilya Kitaev)85a6322
double/string to monero integer convertion methods (Ilya Kitaev)e7d8f2a
wallet::default_mixin exposed to public interface as Wallet::setDefaultMixin, Wallet::defaultMixin; wallet::create_transaction_2 used in Wallet::createTransaction (Ilya Kitaev)a537489
Wallet::filename, Wallet::keysFilename, tests for move wallet (Ilya Kitaev)a1eddcd
removed unused "using" (Ilya Kitaev)8390bfa
Wallet API : WalletManager::findWallets() added (Ilya Kitaev)44cc0ef
scripts for faster test wallets generation (Ilya Kitaev)2060bfe
regenerated test wallets, basic functions got broken (Ilya Kitaev)dbc0b03
installing wallet_api header (Ilya Kitaev)653c7e3
cmake: BUILD_TESTS as option explicitly; added missed dependency (Ilya Kitaev)ef9a74c
cmake libutils dependency added (Ilya Kitaev)191cb59
all wallet dependencies merged to single static lib (Ilya Kitaev)91eeeb8
WalletListener::moneyReceived test (Ilya Kitaev)64348a2
WalletListener::moneySpent test (Ilya Kitaev)060bb62
WalletListener::moneySpent(), WalletListener::moneyReceived() (Ilya Kitaev)214014c
i_wallet_callback: virtual dtor (Ilya Kitaev)3745770
started WalletListener (Ilya Kitaev)e6fdd5d
TransactionHistory continued (Ilya Kitaev)3dd4b4c
merged with upstream (Ilya Kitaev)d500272
Wallet API : transaction history in progress (Ilya Kitaev)663ed04
transaction history api in progress (Ilya Kitaev)12345d3
api implementation splitted over separate files (Ilya Kitaev)60508e6
TransactionInfo / TransactionHistory APIs design (Ilya Kitaev)951f3b5
Wallet::createTransaction API introduced (Ilya Kitaev)7c51227
Wallet::transfer in progress (Ilya Kitaev)e04c67a
Wallet::refresh + tests (Ilya Kitaev)9cdf0b7
"testnet" is default parameter (Ilya Kitaev)caf0e02
testnet option, Wallet::balance(), Wallet::unlockedBalance() (Ilya Kitaev)8df820b
- testnet option added to api; (Ilya Kitaev)94eaeb5
wallet2::store() implemented within wallet2::store_to (Ilya Kitaev)
commit
fc58069731
@ -0,0 +1,129 @@
|
||||
# Copyright (C) 2012 Modelon AB
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the BSD style license.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# FMILIB_License.txt file for more details.
|
||||
|
||||
# You should have received a copy of the FMILIB_License.txt file
|
||||
# along with this program. If not, contact Modelon AB <http://www.modelon.com>.
|
||||
|
||||
# Merge_static_libs(outlib lib1 lib2 ... libn) merges a number of static
|
||||
# libs into a single static library
|
||||
function(merge_static_libs outlib )
|
||||
set(libs ${ARGV})
|
||||
list(REMOVE_AT libs 0)
|
||||
# Create a dummy file that the target will depend on
|
||||
set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${outlib}_dummy.c)
|
||||
file(WRITE ${dummyfile} "const char * dummy = \"${dummyfile}\";")
|
||||
|
||||
add_library(${outlib} STATIC ${dummyfile})
|
||||
|
||||
if("${CMAKE_CFG_INTDIR}" STREQUAL ".")
|
||||
set(multiconfig FALSE)
|
||||
else()
|
||||
set(multiconfig TRUE)
|
||||
endif()
|
||||
|
||||
# First get the file names of the libraries to be merged
|
||||
foreach(lib ${libs})
|
||||
get_target_property(libtype ${lib} TYPE)
|
||||
if(NOT libtype STREQUAL "STATIC_LIBRARY")
|
||||
message(FATAL_ERROR "Merge_static_libs can only process static libraries")
|
||||
endif()
|
||||
if(multiconfig)
|
||||
foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
|
||||
get_target_property("libfile_${CONFIG_TYPE}" ${lib} "LOCATION_${CONFIG_TYPE}")
|
||||
list(APPEND libfiles_${CONFIG_TYPE} ${libfile_${CONFIG_TYPE}})
|
||||
endforeach()
|
||||
else()
|
||||
get_target_property(libfile ${lib} LOCATION)
|
||||
list(APPEND libfiles "${libfile}")
|
||||
endif(multiconfig)
|
||||
endforeach()
|
||||
message(STATUS "will be merging ${libfiles}")
|
||||
# Just to be sure: cleanup from duplicates
|
||||
if(multiconfig)
|
||||
foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
|
||||
list(REMOVE_DUPLICATES libfiles_${CONFIG_TYPE})
|
||||
set(libfiles ${libfiles} ${libfiles_${CONFIG_TYPE}})
|
||||
endforeach()
|
||||
endif()
|
||||
list(REMOVE_DUPLICATES libfiles)
|
||||
|
||||
# Now the easy part for MSVC and for MAC
|
||||
if(MSVC)
|
||||
# lib.exe does the merging of libraries just need to conver the list into string
|
||||
foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
|
||||
set(flags "")
|
||||
foreach(lib ${libfiles_${CONFIG_TYPE}})
|
||||
set(flags "${flags} ${lib}")
|
||||
endforeach()
|
||||
string(TOUPPER "STATIC_LIBRARY_FLAGS_${CONFIG_TYPE}" PROPNAME)
|
||||
set_target_properties(${outlib} PROPERTIES ${PROPNAME} "${flags}")
|
||||
endforeach()
|
||||
|
||||
elseif(APPLE)
|
||||
# Use OSX's libtool to merge archives
|
||||
if(multiconfig)
|
||||
message(FATAL_ERROR "Multiple configurations are not supported")
|
||||
endif()
|
||||
get_target_property(outfile ${outlib} LOCATION)
|
||||
add_custom_command(TARGET ${outlib} POST_BUILD
|
||||
COMMAND rm ${outfile}
|
||||
COMMAND /usr/bin/libtool -static -o ${outfile}
|
||||
${libfiles}
|
||||
)
|
||||
else()
|
||||
# general UNIX - need to "ar -x" and then "ar -ru"
|
||||
if(multiconfig)
|
||||
message(FATAL_ERROR "Multiple configurations are not supported")
|
||||
endif()
|
||||
get_target_property(outfile ${outlib} LOCATION)
|
||||
message(STATUS "outfile location is ${outfile}")
|
||||
foreach(lib ${libfiles})
|
||||
# objlistfile will contain the list of object files for the library
|
||||
set(objlistfile ${lib}.objlist)
|
||||
set(objdir ${lib}.objdir)
|
||||
set(objlistcmake ${objlistfile}.cmake)
|
||||
# we only need to extract files once
|
||||
if(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/cmake.check_cache IS_NEWER_THAN ${objlistcmake})
|
||||
#---------------------------------
|
||||
FILE(WRITE ${objlistcmake}
|
||||
"# Extract object files from the library
|
||||
message(STATUS \"Extracting object files from ${lib}\")
|
||||
EXECUTE_PROCESS(COMMAND ${CMAKE_AR} -x ${lib}
|
||||
WORKING_DIRECTORY ${objdir})
|
||||
# save the list of object files
|
||||
EXECUTE_PROCESS(COMMAND ls .
|
||||
OUTPUT_FILE ${objlistfile}
|
||||
WORKING_DIRECTORY ${objdir})")
|
||||
#---------------------------------
|
||||
file(MAKE_DIRECTORY ${objdir})
|
||||
add_custom_command(
|
||||
OUTPUT ${objlistfile}
|
||||
COMMAND ${CMAKE_COMMAND} -P ${objlistcmake}
|
||||
DEPENDS ${lib})
|
||||
endif()
|
||||
list(APPEND extrafiles "${objlistfile}")
|
||||
# relative path is needed by ar under MSYS
|
||||
file(RELATIVE_PATH objlistfilerpath ${objdir} ${objlistfile})
|
||||
add_custom_command(TARGET ${outlib} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running: ${CMAKE_AR} ru ${outfile} @${objlistfilerpath}"
|
||||
COMMAND ${CMAKE_AR} ru "${outfile}" @"${objlistfilerpath}"
|
||||
WORKING_DIRECTORY ${objdir})
|
||||
endforeach()
|
||||
add_custom_command(TARGET ${outlib} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running: ${CMAKE_RANLIB} ${outfile}"
|
||||
COMMAND ${CMAKE_RANLIB} ${outfile})
|
||||
endif()
|
||||
file(WRITE ${dummyfile}.base "const char* ${outlib}_sublibs=\"${libs}\";")
|
||||
add_custom_command(
|
||||
OUTPUT ${dummyfile}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${dummyfile}.base ${dummyfile}
|
||||
DEPENDS ${libs} ${extrafiles})
|
||||
|
||||
endfunction()
|
@ -0,0 +1,7 @@
|
||||
#ifndef WALLET_API_COMMON_DEFINES_H__
|
||||
#define WALLET_API_COMMON_DEFINES_H__
|
||||
|
||||
#define tr(x) (x)
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,138 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#include "pending_transaction.h"
|
||||
#include "wallet.h"
|
||||
#include "common_defines.h"
|
||||
|
||||
#include "cryptonote_core/cryptonote_format_utils.h"
|
||||
#include "cryptonote_core/cryptonote_basic_impl.h"
|
||||
#include "cryptonote_core/cryptonote_format_utils.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
PendingTransaction::~PendingTransaction() {}
|
||||
|
||||
|
||||
PendingTransactionImpl::PendingTransactionImpl(WalletImpl &wallet)
|
||||
: m_wallet(wallet)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PendingTransactionImpl::~PendingTransactionImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int PendingTransactionImpl::status() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
string PendingTransactionImpl::errorString() const
|
||||
{
|
||||
return m_errorString;
|
||||
}
|
||||
|
||||
bool PendingTransactionImpl::commit()
|
||||
{
|
||||
|
||||
LOG_PRINT_L0("m_pending_tx size: " << m_pending_tx.size());
|
||||
assert(m_pending_tx.size() == 1);
|
||||
try {
|
||||
while (!m_pending_tx.empty()) {
|
||||
auto & ptx = m_pending_tx.back();
|
||||
m_wallet.m_wallet->commit_tx(ptx);
|
||||
// success_msg_writer(true) << tr("Money successfully sent, transaction ") << get_transaction_hash(ptx.tx);
|
||||
// if no exception, remove element from vector
|
||||
m_pending_tx.pop_back();
|
||||
} // TODO: extract method;
|
||||
} catch (const tools::error::daemon_busy&) {
|
||||
// TODO: make it translatable with "tr"?
|
||||
m_errorString = tr("daemon is busy. Please try again later.");
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::no_connection_to_daemon&) {
|
||||
m_errorString = tr("no connection to daemon. Please make sure daemon is running.");
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::tx_rejected& e) {
|
||||
std::ostringstream writer(m_errorString);
|
||||
writer << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status();
|
||||
m_status = Status_Error;
|
||||
} catch (std::exception &e) {
|
||||
m_errorString = string(tr("Unknown exception: ")) + e.what();
|
||||
m_status = Status_Error;
|
||||
} catch (...) {
|
||||
m_errorString = tr("Unhandled exception");
|
||||
LOG_ERROR(m_errorString);
|
||||
m_status = Status_Error;
|
||||
}
|
||||
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
uint64_t PendingTransactionImpl::amount() const
|
||||
{
|
||||
uint64_t result = 0;
|
||||
for (const auto &ptx : m_pending_tx) {
|
||||
for (const auto &dest : ptx.dests) {
|
||||
result += dest.amount;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t PendingTransactionImpl::dust() const
|
||||
{
|
||||
uint32_t result = 0;
|
||||
for (const auto & ptx : m_pending_tx) {
|
||||
result += ptx.dust;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t PendingTransactionImpl::fee() const
|
||||
{
|
||||
uint32_t result = 0;
|
||||
for (const auto ptx : m_pending_tx) {
|
||||
result += ptx.fee;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#include "wallet/wallet2_api.h"
|
||||
#include "wallet/wallet2.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
class WalletImpl;
|
||||
class PendingTransactionImpl : public PendingTransaction
|
||||
{
|
||||
public:
|
||||
PendingTransactionImpl(WalletImpl &wallet);
|
||||
~PendingTransactionImpl();
|
||||
int status() const;
|
||||
std::string errorString() const;
|
||||
bool commit();
|
||||
uint64_t amount() const;
|
||||
uint64_t dust() const;
|
||||
uint64_t fee() const;
|
||||
// TODO: continue with interface;
|
||||
|
||||
private:
|
||||
friend class WalletImpl;
|
||||
WalletImpl &m_wallet;
|
||||
|
||||
int m_status;
|
||||
std::string m_errorString;
|
||||
std::vector<tools::wallet2::pending_tx> m_pending_tx;
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
|
||||
#include "transaction_history.h"
|
||||
#include "transaction_info.h"
|
||||
#include "wallet.h"
|
||||
|
||||
#include "crypto/hash.h"
|
||||
#include "wallet/wallet2.h"
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
using namespace epee;
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
TransactionHistory::~TransactionHistory() {}
|
||||
|
||||
|
||||
TransactionHistoryImpl::TransactionHistoryImpl(WalletImpl *wallet)
|
||||
: m_wallet(wallet)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TransactionHistoryImpl::~TransactionHistoryImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int TransactionHistoryImpl::count() const
|
||||
{
|
||||
return m_history.size();
|
||||
}
|
||||
|
||||
TransactionInfo *TransactionHistoryImpl::transaction(const std::string &id) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const
|
||||
{
|
||||
return m_history;
|
||||
}
|
||||
|
||||
void TransactionHistoryImpl::refresh()
|
||||
{
|
||||
// TODO: configurable values;
|
||||
uint64_t min_height = 0;
|
||||
uint64_t max_height = (uint64_t)-1;
|
||||
|
||||
// delete old transactions;
|
||||
for (auto t : m_history)
|
||||
delete t;
|
||||
m_history.clear();
|
||||
|
||||
|
||||
|
||||
// transactions are stored in wallet2:
|
||||
// - confirmed_transfer_details - out transfers
|
||||
// - unconfirmed_transfer_details - pending out transfers
|
||||
// - payment_details - input transfers
|
||||
|
||||
// payments are "input transactions";
|
||||
// one input transaction contains only one transfer. e.g. <transaction_id> - <100XMR>
|
||||
|
||||
std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> in_payments;
|
||||
m_wallet->m_wallet->get_payments(in_payments, min_height, max_height);
|
||||
for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = in_payments.begin(); i != in_payments.end(); ++i) {
|
||||
const tools::wallet2::payment_details &pd = i->second;
|
||||
std::string payment_id = string_tools::pod_to_hex(i->first);
|
||||
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||
payment_id = payment_id.substr(0,16);
|
||||
// TODO
|
||||
TransactionInfoImpl * ti = new TransactionInfoImpl();
|
||||
ti->m_paymentid = payment_id;
|
||||
ti->m_amount = pd.m_amount;
|
||||
ti->m_direction = TransactionInfo::Direction_In;
|
||||
ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
|
||||
ti->m_blockheight = pd.m_block_height;
|
||||
// TODO:
|
||||
// ti->m_timestamp = pd.m_timestamp;
|
||||
m_history.push_back(ti);
|
||||
|
||||
/* output.insert(std::make_pair(pd.m_block_height, std::make_pair(true, (boost::format("%20.20s %s %s %s")
|
||||
% print_money(pd.m_amount)
|
||||
% string_tools::pod_to_hex(pd.m_tx_hash)
|
||||
% payment_id % "-").str()))); */
|
||||
}
|
||||
|
||||
// confirmed output transactions
|
||||
// one output transaction may contain more than one money transfer, e.g.
|
||||
// <transaction_id>:
|
||||
// transfer1: 100XMR to <address_1>
|
||||
// transfer2: 50XMR to <address_2>
|
||||
// fee: fee charged per transaction
|
||||
//
|
||||
|
||||
std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> out_payments;
|
||||
m_wallet->m_wallet->get_payments_out(out_payments, min_height, max_height);
|
||||
|
||||
for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = out_payments.begin();
|
||||
i != out_payments.end(); ++i) {
|
||||
|
||||
const crypto::hash &hash = i->first;
|
||||
const tools::wallet2::confirmed_transfer_details &pd = i->second;
|
||||
|
||||
uint64_t fee = pd.m_amount_in - pd.m_amount_out;
|
||||
uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known
|
||||
|
||||
|
||||
std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
|
||||
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||
payment_id = payment_id.substr(0,16);
|
||||
|
||||
|
||||
TransactionInfoImpl * ti = new TransactionInfoImpl();
|
||||
ti->m_paymentid = payment_id;
|
||||
ti->m_amount = pd.m_amount_in - change - fee;
|
||||
ti->m_fee = fee;
|
||||
ti->m_direction = TransactionInfo::Direction_Out;
|
||||
ti->m_hash = string_tools::pod_to_hex(hash);
|
||||
ti->m_blockheight = pd.m_block_height;
|
||||
|
||||
// single output transaction might contain multiple transfers
|
||||
for (const auto &d: pd.m_dests) {
|
||||
ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->testnet(), d.addr)});
|
||||
}
|
||||
m_history.push_back(ti);
|
||||
}
|
||||
|
||||
// unconfirmed output transactions
|
||||
std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments;
|
||||
m_wallet->m_wallet->get_unconfirmed_payments_out(upayments);
|
||||
for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) {
|
||||
const tools::wallet2::unconfirmed_transfer_details &pd = i->second;
|
||||
const crypto::hash &hash = i->first;
|
||||
uint64_t amount = 0;
|
||||
cryptonote::get_inputs_money_amount(pd.m_tx, amount);
|
||||
uint64_t fee = amount - get_outs_money_amount(pd.m_tx);
|
||||
std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
|
||||
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||
payment_id = payment_id.substr(0,16);
|
||||
bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
|
||||
|
||||
TransactionInfoImpl * ti = new TransactionInfoImpl();
|
||||
ti->m_paymentid = payment_id;
|
||||
ti->m_amount = amount - pd.m_change;
|
||||
ti->m_fee = fee;
|
||||
ti->m_direction = TransactionInfo::Direction_Out;
|
||||
ti->m_failed = is_failed;
|
||||
ti->m_pending = true;
|
||||
ti->m_hash = string_tools::pod_to_hex(hash);
|
||||
m_history.push_back(ti);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TransactionInfo *TransactionHistoryImpl::transaction(int index) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#include "wallet/wallet2_api.h"
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
class TransactionInfo;
|
||||
class WalletImpl;
|
||||
|
||||
class TransactionHistoryImpl : public TransactionHistory
|
||||
{
|
||||
public:
|
||||
TransactionHistoryImpl(WalletImpl * wallet);
|
||||
~TransactionHistoryImpl();
|
||||
virtual int count() const;
|
||||
virtual TransactionInfo * transaction(int index) const;
|
||||
virtual TransactionInfo * transaction(const std::string &id) const;
|
||||
virtual std::vector<TransactionInfo*> getAll() const;
|
||||
virtual void refresh();
|
||||
|
||||
private:
|
||||
|
||||
// TransactionHistory is responsible of memory management
|
||||
std::vector<TransactionInfo*> m_history;
|
||||
WalletImpl *m_wallet;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,112 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#include "transaction_info.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
TransactionInfo::~TransactionInfo() {}
|
||||
|
||||
TransactionInfo::Transfer::Transfer(uint64_t _amount, const string &_address)
|
||||
: amount(_amount), address(_address) {}
|
||||
|
||||
|
||||
TransactionInfoImpl::TransactionInfoImpl()
|
||||
: m_direction(Direction_Out)
|
||||
, m_pending(false)
|
||||
, m_failed(false)
|
||||
, m_amount(0)
|
||||
, m_fee(0)
|
||||
, m_blockheight(0)
|
||||
, m_timestamp(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TransactionInfoImpl::~TransactionInfoImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int TransactionInfoImpl::direction() const
|
||||
{
|
||||
return m_direction;
|
||||
}
|
||||
|
||||
|
||||
bool TransactionInfoImpl::isPending() const
|
||||
{
|
||||
return m_pending;
|
||||
}
|
||||
|
||||
bool TransactionInfoImpl::isFailed() const
|
||||
{
|
||||
return m_failed;
|
||||
}
|
||||
|
||||
uint64_t TransactionInfoImpl::amount() const
|
||||
{
|
||||
return m_amount;
|
||||
}
|
||||
|
||||
uint64_t TransactionInfoImpl::fee() const
|
||||
{
|
||||
return m_fee;
|
||||
}
|
||||
|
||||
uint64_t TransactionInfoImpl::blockHeight() const
|
||||
{
|
||||
return m_blockheight;
|
||||
}
|
||||
|
||||
string TransactionInfoImpl::hash() const
|
||||
{
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
std::time_t TransactionInfoImpl::timestamp() const
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
string TransactionInfoImpl::paymentId() const
|
||||
{
|
||||
return m_paymentid;
|
||||
}
|
||||
|
||||
const std::vector<TransactionInfo::Transfer> &TransactionInfoImpl::transfers() const
|
||||
{
|
||||
return m_transfers;
|
||||
}
|
||||
|
||||
} // namespace
|
@ -0,0 +1,75 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#include "wallet/wallet2_api.h"
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
class TransactionHistoryImpl;
|
||||
|
||||
class TransactionInfoImpl : public TransactionInfo
|
||||
{
|
||||
public:
|
||||
TransactionInfoImpl();
|
||||
~TransactionInfoImpl();
|
||||
//! in/out
|
||||
virtual int direction() const;
|
||||
//! true if hold
|
||||
virtual bool isPending() const;
|
||||
virtual bool isFailed() const;
|
||||
virtual uint64_t amount() const;
|
||||
//! always 0 for incoming txes
|
||||
virtual uint64_t fee() const;
|
||||
virtual uint64_t blockHeight() const;
|
||||
|
||||
virtual std::string hash() const;
|
||||
virtual std::time_t timestamp() const;
|
||||
virtual std::string paymentId() const;
|
||||
virtual const std::vector<Transfer> &transfers() const;
|
||||
|
||||
private:
|
||||
int m_direction;
|
||||
bool m_pending;
|
||||
bool m_failed;
|
||||
uint64_t m_amount;
|
||||
uint64_t m_fee;
|
||||
uint64_t m_blockheight;
|
||||
std::string m_hash;
|
||||
std::time_t m_timestamp;
|
||||
std::string m_paymentid;
|
||||
std::vector<Transfer> m_transfers;
|
||||
|
||||
friend class TransactionHistoryImpl;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
|
||||
|
||||
#include "include_base_utils.h" // LOG_PRINT_x
|
||||
#include "net/http_client.h" // epee::net_utils::...
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Bitmonero {
|
||||
namespace Utils {
|
||||
|
||||
|
||||
// copy-pasted from simplewallet.
|
||||
|
||||
bool isAddressLocal(const std::string &address)
|
||||
{
|
||||
// extract host
|
||||
epee::net_utils::http::url_content u_c;
|
||||
if (!epee::net_utils::parse_url(address, u_c))
|
||||
{
|
||||
LOG_PRINT_L1("Failed to determine whether daemon is local, assuming not");
|
||||
return false;
|
||||
}
|
||||
if (u_c.host.empty())
|
||||
{
|
||||
LOG_PRINT_L1("Failed to determine whether daemon is local, assuming not");
|
||||
return false;
|
||||
}
|
||||
|
||||
// resolve to IP
|
||||
boost::asio::io_service io_service;
|
||||
boost::asio::ip::tcp::resolver resolver(io_service);
|
||||
boost::asio::ip::tcp::resolver::query query(u_c.host, "");
|
||||
boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query);
|
||||
while (i != boost::asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
const boost::asio::ip::tcp::endpoint &ep = *i;
|
||||
if (ep.address().is_loopback())
|
||||
return true;
|
||||
++i;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
@ -0,0 +1,588 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
|
||||
#include "wallet.h"
|
||||
#include "pending_transaction.h"
|
||||
#include "transaction_history.h"
|
||||
#include "common_defines.h"
|
||||
|
||||
#include "mnemonics/electrum-words.h"
|
||||
#include <boost/format.hpp>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace cryptonote;
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
namespace {
|
||||
// copy-pasted from simplewallet
|
||||
static const size_t DEFAULT_MIXIN = 4;
|
||||
}
|
||||
|
||||
struct Wallet2CallbackImpl : public tools::i_wallet2_callback
|
||||
{
|
||||
|
||||
Wallet2CallbackImpl()
|
||||
: m_listener(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~Wallet2CallbackImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void setListener(WalletListener * listener)
|
||||
{
|
||||
m_listener = listener;
|
||||
}
|
||||
|
||||
WalletListener * getListener() const
|
||||
{
|
||||
return m_listener;
|
||||
}
|
||||
|
||||
virtual void on_new_block(uint64_t height, const cryptonote::block& block)
|
||||
{
|
||||
// TODO;
|
||||
LOG_PRINT_L3(__FUNCTION__ << ": new block. height: " << height);
|
||||
}
|
||||
|
||||
virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, size_t out_index)
|
||||
{
|
||||
|
||||
std::string tx_hash = epee::string_tools::pod_to_hex(get_transaction_hash(tx));
|
||||
uint64_t amount = tx.vout[out_index].amount;
|
||||
|
||||
LOG_PRINT_L3(__FUNCTION__ << ": money received. height: " << height
|
||||
<< ", tx: " << tx_hash
|
||||
<< ", amount: " << print_money(amount));
|
||||
if (m_listener) {
|
||||
m_listener->moneyReceived(tx_hash, amount);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, size_t out_index,
|
||||
const cryptonote::transaction& spend_tx)
|
||||
{
|
||||
// TODO;
|
||||
std::string tx_hash = epee::string_tools::pod_to_hex(get_transaction_hash(spend_tx));
|
||||
uint64_t amount = in_tx.vout[out_index].amount;
|
||||
LOG_PRINT_L3(__FUNCTION__ << ": money spent. height: " << height
|
||||
<< ", tx: " << tx_hash
|
||||
<< ", amount: " << print_money(amount));
|
||||
if (m_listener) {
|
||||
m_listener->moneySpent(tx_hash, amount);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void on_skip_transaction(uint64_t height, const cryptonote::transaction& tx)
|
||||
{
|
||||
// TODO;
|
||||
}
|
||||
|
||||
WalletListener * m_listener;
|
||||
};
|
||||
|
||||
Wallet::~Wallet() {}
|
||||
|
||||
WalletListener::~WalletListener() {}
|
||||
|
||||
string Wallet::displayAmount(uint64_t amount)
|
||||
{
|
||||
return cryptonote::print_money(amount);
|
||||
}
|
||||
|
||||
uint64_t Wallet::amountFromString(const string &amount)
|
||||
{
|
||||
uint64_t result;
|
||||
cryptonote::parse_amount(result, amount);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t Wallet::amountFromDouble(double amount)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(CRYPTONOTE_DISPLAY_DECIMAL_POINT) << amount;
|
||||
return amountFromString(ss.str());
|
||||
}
|
||||
|
||||
std::string Wallet::genPaymentId()
|
||||
{
|
||||
crypto::hash8 payment_id = crypto::rand<crypto::hash8>();
|
||||
return epee::string_tools::pod_to_hex(payment_id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
///////////////////////// WalletImpl implementation ////////////////////////
|
||||
WalletImpl::WalletImpl(bool testnet)
|
||||
:m_wallet(nullptr), m_status(Wallet::Status_Ok), m_trustedDaemon(false),
|
||||
m_wallet2Callback(nullptr)
|
||||
{
|
||||
m_wallet = new tools::wallet2(testnet);
|
||||
m_history = new TransactionHistoryImpl(this);
|
||||
m_wallet2Callback = new Wallet2CallbackImpl;
|
||||
}
|
||||
|
||||
WalletImpl::~WalletImpl()
|
||||
{
|
||||
delete m_wallet2Callback;
|
||||
delete m_history;
|
||||
delete m_wallet;
|
||||
}
|
||||
|
||||
bool WalletImpl::create(const std::string &path, const std::string &password, const std::string &language)
|
||||
{
|
||||
|
||||
clearStatus();
|
||||
|
||||
bool keys_file_exists;
|
||||
bool wallet_file_exists;
|
||||
tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists);
|
||||
// TODO: figure out how to setup logger;
|
||||
LOG_PRINT_L3("wallet_path: " << path << "");
|
||||
LOG_PRINT_L3("keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha
|
||||
<< " wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha);
|
||||
|
||||
|
||||
// add logic to error out if new wallet requested but named wallet file exists
|
||||
if (keys_file_exists || wallet_file_exists) {
|
||||
m_errorString = "attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting.";
|
||||
LOG_ERROR(m_errorString);
|
||||
m_status = Status_Error;
|
||||
return false;
|
||||
}
|
||||
// TODO: validate language
|
||||
m_wallet->set_seed_language(language);
|
||||
crypto::secret_key recovery_val, secret_key;
|
||||
try {
|
||||
recovery_val = m_wallet->generate(path, password, secret_key, false, false);
|
||||
m_password = password;
|
||||
m_status = Status_Ok;
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Error creating wallet: " << e.what());
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalletImpl::open(const std::string &path, const std::string &password)
|
||||
{
|
||||
clearStatus();
|
||||
try {
|
||||
// TODO: handle "deprecated"
|
||||
m_wallet->load(path, password);
|
||||
|
||||
m_password = password;
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Error opening wallet: " << e.what());
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
bool WalletImpl::recover(const std::string &path, const std::string &seed)
|
||||
{
|
||||
clearStatus();
|
||||
m_errorString.clear();
|
||||
if (seed.empty()) {
|
||||
m_errorString = "Electrum seed is empty";
|
||||
LOG_ERROR(m_errorString);
|
||||
m_status = Status_Error;
|
||||
return false;
|
||||
}
|
||||
|
||||
crypto::secret_key recovery_key;
|
||||
std::string old_language;
|
||||
if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) {
|
||||
m_errorString = "Electrum-style word list failed verification";
|
||||
m_status = Status_Error;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
m_wallet->set_seed_language(old_language);
|
||||
m_wallet->generate(path, "", recovery_key, true, false);
|
||||
// TODO: wallet->init(daemon_address);
|
||||
} catch (const std::exception &e) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
bool WalletImpl::close()
|
||||
{
|
||||
clearStatus();
|
||||
bool result = false;
|
||||
try {
|
||||
m_wallet->store();
|
||||
m_wallet->stop();
|
||||
result = true;
|
||||
} catch (const std::exception &e) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
LOG_ERROR("Error closing wallet: " << e.what());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string WalletImpl::seed() const
|
||||
{
|
||||
std::string seed;
|
||||
if (m_wallet)
|
||||
m_wallet->get_seed(seed);
|
||||
return seed;
|
||||
}
|
||||
|
||||
std::string WalletImpl::getSeedLanguage() const
|
||||
{
|
||||
return m_wallet->get_seed_language();
|
||||
}
|
||||
|
||||
void WalletImpl::setSeedLanguage(const std::string &arg)
|
||||
{
|
||||
m_wallet->set_seed_language(arg);
|
||||
}
|
||||
|
||||
int WalletImpl::status() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
std::string WalletImpl::errorString() const
|
||||
{
|
||||
return m_errorString;
|
||||
}
|
||||
|
||||
bool WalletImpl::setPassword(const std::string &password)
|
||||
{
|
||||
clearStatus();
|
||||
try {
|
||||
m_wallet->rewrite(m_wallet->get_wallet_file(), password);
|
||||
m_password = password;
|
||||
} catch (const std::exception &e) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
std::string WalletImpl::address() const
|
||||
{
|
||||
return m_wallet->get_account().get_public_address_str(m_wallet->testnet());
|
||||
}
|
||||
|
||||
std::string WalletImpl::integratedAddress(const std::string &payment_id) const
|
||||
{
|
||||
crypto::hash8 pid;
|
||||
if (!tools::wallet2::parse_short_payment_id(payment_id, pid)) {
|
||||
pid = crypto::rand<crypto::hash8>();
|
||||
}
|
||||
return m_wallet->get_account().get_public_integrated_address_str(pid, m_wallet->testnet());
|
||||
}
|
||||
|
||||
bool WalletImpl::store(const std::string &path)
|
||||
{
|
||||
clearStatus();
|
||||
try {
|
||||
if (path.empty()) {
|
||||
m_wallet->store();
|
||||
} else {
|
||||
m_wallet->store_to(path, m_password);
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Error storing wallet: " << e.what());
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
string WalletImpl::filename() const
|
||||
{
|
||||
return m_wallet->get_wallet_file();
|
||||
}
|
||||
|
||||
string WalletImpl::keysFilename() const
|
||||
{
|
||||
return m_wallet->get_keys_file();
|
||||
}
|
||||
|
||||
bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit)
|
||||
{
|
||||
clearStatus();
|
||||
try {
|
||||
m_wallet->init(daemon_address, upper_transaction_size_limit);
|
||||
if (Utils::isAddressLocal(daemon_address)) {
|
||||
this->setTrustedDaemon(true);
|
||||
}
|
||||
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Error initializing wallet: " << e.what());
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
uint64_t WalletImpl::balance() const
|
||||
{
|
||||
return m_wallet->balance();
|
||||
}
|
||||
|
||||
uint64_t WalletImpl::unlockedBalance() const
|
||||
{
|
||||
return m_wallet->unlocked_balance();
|
||||
}
|
||||
|
||||
|
||||
bool WalletImpl::refresh()
|
||||
{
|
||||
clearStatus();
|
||||
try {
|
||||
m_wallet->refresh();
|
||||
} catch (const std::exception &e) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// 1 - properly handle payment id (add another menthod with explicit 'payment_id' param)
|
||||
// 2 - check / design how "Transaction" can be single interface
|
||||
// (instead of few different data structures within wallet2 implementation:
|
||||
// - pending_tx;
|
||||
// - transfer_details;
|
||||
// - payment_details;
|
||||
// - unconfirmed_transfer_details;
|
||||
// - confirmed_transfer_details)
|
||||
|
||||
PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, uint64_t amount, uint32_t mixin_count)
|
||||
{
|
||||
clearStatus();
|
||||
vector<cryptonote::tx_destination_entry> dsts;
|
||||
cryptonote::tx_destination_entry de;
|
||||
|
||||
// indicates if dst_addr is integrated address (address + payment_id)
|
||||
bool has_payment_id;
|
||||
crypto::hash8 payment_id_short;
|
||||
// TODO: (https://bitcointalk.org/index.php?topic=753252.msg9985441#msg9985441)
|
||||
size_t fake_outs_count = mixin_count > 0 ? mixin_count : m_wallet->default_mixin();
|
||||
if (fake_outs_count == 0)
|
||||
fake_outs_count = DEFAULT_MIXIN;
|
||||
|
||||
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
|
||||
|
||||
do {
|
||||
if(!cryptonote::get_account_integrated_address_from_str(de.addr, has_payment_id, payment_id_short, m_wallet->testnet(), dst_addr)) {
|
||||
// TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
|
||||
m_status = Status_Error;
|
||||
m_errorString = "Invalid destination address";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint8_t> extra;
|
||||
// if dst_addr is not an integrated address, parse payment_id
|
||||
if (!has_payment_id && !payment_id.empty()) {
|
||||
// copy-pasted from simplewallet.cpp:2212
|
||||
crypto::hash payment_id_long;
|
||||
bool r = tools::wallet2::parse_long_payment_id(payment_id, payment_id_long);
|
||||
if (r) {
|
||||
std::string extra_nonce;
|
||||
cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id_long);
|
||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
} else {
|
||||
r = tools::wallet2::parse_short_payment_id(payment_id, payment_id_short);
|
||||
if (r) {
|
||||
std::string extra_nonce;
|
||||
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id_short);
|
||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
}
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = tr("payment id has invalid format, expected 16 or 64 character hex string: ") + payment_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
de.amount = amount;
|
||||
if (de.amount <= 0) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = "Invalid amount";
|
||||
break;
|
||||
}
|
||||
|
||||
dsts.push_back(de);
|
||||
//std::vector<tools::wallet2::pending_tx> ptx_vector;
|
||||
|
||||
try {
|
||||
transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
|
||||
0 /* unused fee arg*/, extra, m_trustedDaemon);
|
||||
|
||||
} catch (const tools::error::daemon_busy&) {
|
||||
// TODO: make it translatable with "tr"?
|
||||
m_errorString = tr("daemon is busy. Please try again later.");
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::no_connection_to_daemon&) {
|
||||
m_errorString = tr("no connection to daemon. Please make sure daemon is running.");
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::wallet_rpc_error& e) {
|
||||
m_errorString = tr("RPC error: ") + e.to_string();
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::get_random_outs_error&) {
|
||||
m_errorString = tr("failed to get random outputs to mix");
|
||||
m_status = Status_Error;
|
||||
|
||||
} catch (const tools::error::not_enough_money& e) {
|
||||
m_status = Status_Error;
|
||||
std::ostringstream writer;
|
||||
|
||||
writer << boost::format(tr("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)")) %
|
||||
print_money(e.available()) %
|
||||
print_money(e.tx_amount() + e.fee()) %
|
||||
print_money(e.tx_amount()) %
|
||||
print_money(e.fee());
|
||||
m_errorString = writer.str();
|
||||
|
||||
} catch (const tools::error::not_enough_outs_to_mix& e) {
|
||||
std::ostringstream writer;
|
||||
writer << tr("not enough outputs for specified mixin_count") << " = " << e.mixin_count() << ":";
|
||||
for (const cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& outs_for_amount : e.scanty_outs()) {
|
||||
writer << "\n" << tr("output amount") << " = " << print_money(outs_for_amount.amount) << ", " << tr("found outputs to mix") << " = " << outs_for_amount.outs.size();
|
||||
}
|
||||
m_errorString = writer.str();
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::tx_not_constructed&) {
|
||||
m_errorString = tr("transaction was not constructed");
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::tx_rejected& e) {
|
||||
std::ostringstream writer;
|
||||
writer << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status();
|
||||
m_errorString = writer.str();
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::tx_sum_overflow& e) {
|
||||
m_errorString = e.what();
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::zero_destination&) {
|
||||
m_errorString = tr("one of destinations is zero");
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::tx_too_big& e) {
|
||||
m_errorString = tr("failed to find a suitable way to split transactions");
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::transfer_error& e) {
|
||||
m_errorString = string(tr("unknown transfer error: ")) + e.what();
|
||||
m_status = Status_Error;
|
||||
} catch (const tools::error::wallet_internal_error& e) {
|
||||
m_errorString = string(tr("internal error: ")) + e.what();
|
||||
m_status = Status_Error;
|
||||
} catch (const std::exception& e) {
|
||||
m_errorString = string(tr("unexpected error: ")) + e.what();
|
||||
m_status = Status_Error;
|
||||
} catch (...) {
|
||||
m_errorString = tr("unknown error");
|
||||
m_status = Status_Error;
|
||||
}
|
||||
} while (false);
|
||||
|
||||
transaction->m_status = m_status;
|
||||
transaction->m_errorString = m_errorString;
|
||||
return transaction;
|
||||
}
|
||||
|
||||
void WalletImpl::disposeTransaction(PendingTransaction *t)
|
||||
{
|
||||
delete t;
|
||||
}
|
||||
|
||||
TransactionHistory *WalletImpl::history() const
|
||||
{
|
||||
return m_history;
|
||||
}
|
||||
|
||||
void WalletImpl::setListener(WalletListener *l)
|
||||
{
|
||||
// TODO thread synchronization;
|
||||
m_wallet2Callback->setListener(l);
|
||||
}
|
||||
|
||||
uint32_t WalletImpl::defaultMixin() const
|
||||
{
|
||||
return m_wallet->default_mixin();
|
||||
}
|
||||
|
||||
void WalletImpl::setDefaultMixin(uint32_t arg)
|
||||
{
|
||||
m_wallet->default_mixin(arg);
|
||||
}
|
||||
|
||||
|
||||
bool WalletImpl::connectToDaemon()
|
||||
{
|
||||
bool result = m_wallet->check_connection();
|
||||
m_status = result ? Status_Ok : Status_Error;
|
||||
if (!result) {
|
||||
m_errorString = "Error connecting to daemon at " + m_wallet->get_daemon_address();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void WalletImpl::setTrustedDaemon(bool arg)
|
||||
{
|
||||
m_trustedDaemon = arg;
|
||||
}
|
||||
|
||||
bool WalletImpl::trustedDaemon() const
|
||||
{
|
||||
return m_trustedDaemon;
|
||||
}
|
||||
|
||||
void WalletImpl::clearStatus()
|
||||
{
|
||||
m_status = Status_Ok;
|
||||
m_errorString.clear();
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#ifndef WALLET_IMPL_H
|
||||
#define WALLET_IMPL_H
|
||||
|
||||
#include "wallet/wallet2_api.h"
|
||||
#include "wallet/wallet2.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace Bitmonero {
|
||||
class TransactionHistoryImpl;
|
||||
class PendingTransactionImpl;
|
||||
struct Wallet2CallbackImpl;
|
||||
|
||||
class WalletImpl : public Wallet
|
||||
{
|
||||
public:
|
||||
WalletImpl(bool testnet = false);
|
||||
~WalletImpl();
|
||||
bool create(const std::string &path, const std::string &password,
|
||||
const std::string &language);
|
||||
bool open(const std::string &path, const std::string &password);
|
||||
bool recover(const std::string &path, const std::string &seed);
|
||||
bool close();
|
||||
std::string seed() const;
|
||||
std::string getSeedLanguage() const;
|
||||
void setSeedLanguage(const std::string &arg);
|
||||
// void setListener(Listener *) {}
|
||||
int status() const;
|
||||
std::string errorString() const;
|
||||
bool setPassword(const std::string &password);
|
||||
std::string address() const;
|
||||
std::string integratedAddress(const std::string &payment_id) const;
|
||||
bool store(const std::string &path);
|
||||
std::string filename() const;
|
||||
std::string keysFilename() const;
|
||||
bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit);
|
||||
bool connectToDaemon();
|
||||
void setTrustedDaemon(bool arg);
|
||||
bool trustedDaemon() const;
|
||||
uint64_t balance() const;
|
||||
uint64_t unlockedBalance() const;
|
||||
bool refresh();
|
||||
PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
|
||||
uint64_t amount, uint32_t mixin_count);
|
||||
virtual void disposeTransaction(PendingTransaction * t);
|
||||
virtual TransactionHistory * history() const;
|
||||
virtual void setListener(WalletListener * l);
|
||||
virtual uint32_t defaultMixin() const;
|
||||
virtual void setDefaultMixin(uint32_t arg);
|
||||
|
||||
private:
|
||||
void clearStatus();
|
||||
|
||||
private:
|
||||
friend class PendingTransactionImpl;
|
||||
friend class TransactionHistoryImpl;
|
||||
|
||||
tools::wallet2 * m_wallet;
|
||||
int m_status;
|
||||
std::string m_errorString;
|
||||
std::string m_password;
|
||||
TransactionHistoryImpl * m_history;
|
||||
bool m_trustedDaemon;
|
||||
WalletListener * m_walletListener;
|
||||
Wallet2CallbackImpl * m_wallet2Callback;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,142 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
|
||||
#include "wallet_manager.h"
|
||||
#include "wallet.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
|
||||
namespace epee {
|
||||
unsigned int g_test_dbg_lock_sleep = 0;
|
||||
}
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
|
||||
const std::string &language, bool testnet)
|
||||
{
|
||||
WalletImpl * wallet = new WalletImpl(testnet);
|
||||
wallet->create(path, password, language);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, bool testnet)
|
||||
{
|
||||
WalletImpl * wallet = new WalletImpl(testnet);
|
||||
wallet->open(path, password);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &memo, bool testnet)
|
||||
{
|
||||
WalletImpl * wallet = new WalletImpl(testnet);
|
||||
wallet->recover(path, memo);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
bool WalletManagerImpl::closeWallet(Wallet *wallet)
|
||||
{
|
||||
WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet);
|
||||
bool result = wallet_->close();
|
||||
if (!result) {
|
||||
m_errorString = wallet_->errorString();
|
||||
} else {
|
||||
delete wallet_;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool WalletManagerImpl::walletExists(const std::string &path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
const boost::regex wallet_rx("(.*)\\.(keys)$"); // searching for <wallet_name>.keys files
|
||||
boost::filesystem::recursive_directory_iterator end_itr; // Default ctor yields past-the-end
|
||||
boost::filesystem::path work_dir(path);
|
||||
|
||||
for (boost::filesystem::recursive_directory_iterator itr(path); itr != end_itr; ++itr) {
|
||||
// Skip if not a file
|
||||
if (!boost::filesystem::is_regular_file(itr->status()))
|
||||
continue;
|
||||
boost::smatch what;
|
||||
std::string filename = itr->path().filename().string();
|
||||
|
||||
LOG_PRINT_L3("Checking filename: " << filename);
|
||||
|
||||
bool matched = boost::regex_match(filename, what, wallet_rx);
|
||||
if (matched) {
|
||||
// if keys file found, checking if there's wallet file itself
|
||||
std::string wallet_file = (itr->path().parent_path() /= what[1]).string();
|
||||
if (boost::filesystem::exists(wallet_file)) {
|
||||
LOG_PRINT_L3("Found wallet: " << wallet_file);
|
||||
result.push_back(wallet_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string WalletManagerImpl::errorString() const
|
||||
{
|
||||
return m_errorString;
|
||||
}
|
||||
|
||||
void WalletManagerImpl::setDaemonHost(const std::string &hostname)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////// WalletManagerFactory implementation //////////////////////
|
||||
WalletManager *WalletManagerFactory::getWalletManager()
|
||||
{
|
||||
|
||||
static WalletManagerImpl * g_walletManager = nullptr;
|
||||
|
||||
if (!g_walletManager) {
|
||||
epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_MAX);
|
||||
g_walletManager = new WalletManagerImpl();
|
||||
}
|
||||
|
||||
return g_walletManager;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
|
||||
#include "wallet/wallet2_api.h"
|
||||
#include <string>
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
class WalletManagerImpl : public WalletManager
|
||||
{
|
||||
public:
|
||||
Wallet * createWallet(const std::string &path, const std::string &password,
|
||||
const std::string &language, bool testnet);
|
||||
Wallet * openWallet(const std::string &path, const std::string &password, bool testnet);
|
||||
virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet);
|
||||
virtual bool closeWallet(Wallet *wallet);
|
||||
bool walletExists(const std::string &path);
|
||||
std::vector<std::string> findWallets(const std::string &path);
|
||||
std::string errorString() const;
|
||||
void setDaemonHost(const std::string &hostname);
|
||||
|
||||
private:
|
||||
WalletManagerImpl() {}
|
||||
friend struct WalletManagerFactory;
|
||||
std::string m_errorString;
|
||||
};
|
||||
|
||||
} // namespace
|
@ -1,346 +0,0 @@
|
||||
// Copyright (c) 2014-2016, The Monero Project
|
||||
//
|
||||
// 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. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#include "wallet2_api.h"
|
||||
#include "wallet2.h"
|
||||
#include "mnemonics/electrum-words.h"
|
||||
#include <memory>
|
||||
|
||||
namespace epee {
|
||||
unsigned int g_test_dbg_lock_sleep = 0;
|
||||
}
|
||||
|
||||
namespace Bitmonero {
|
||||
|
||||
struct WalletManagerImpl;
|
||||
|
||||
namespace {
|
||||
static WalletManagerImpl * g_walletManager = nullptr;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Wallet::~Wallet() {}
|
||||
|
||||
///////////////////////// Wallet implementation ////////////////////////////////
|
||||
class WalletImpl : public Wallet
|
||||
{
|
||||
public:
|
||||
WalletImpl();
|
||||
~WalletImpl();
|
||||
bool create(const std::string &path, const std::string &password,
|
||||
const std::string &language);
|
||||
bool open(const std::string &path, const std::string &password);
|
||||
bool recover(const std::string &path, const std::string &seed);
|
||||
bool close();
|
||||
std::string seed() const;
|
||||
std::string getSeedLanguage() const;
|
||||
void setSeedLanguage(const std::string &arg);
|
||||
void setListener(Listener *) {}
|
||||
int status() const;
|
||||
std::string errorString() const;
|
||||
bool setPassword(const std::string &password);
|
||||
std::string address() const;
|
||||
bool store(const std::string &path);
|
||||
|
||||
private:
|
||||
void clearStatus();
|
||||
|
||||
private:
|
||||
//std::unique_ptr<tools::wallet2> m_wallet;
|
||||
tools::wallet2 * m_wallet;
|
||||
int m_status;
|
||||
std::string m_errorString;
|
||||
std::string m_password;
|
||||
};
|
||||
|
||||
WalletImpl::WalletImpl()
|
||||
:m_wallet(nullptr), m_status(Wallet::Status_Ok)
|
||||
{
|
||||
m_wallet = new tools::wallet2();
|
||||
}
|
||||
|
||||
WalletImpl::~WalletImpl()
|
||||
{
|
||||
delete m_wallet;
|
||||
}
|
||||
|
||||
bool WalletImpl::create(const std::string &path, const std::string &password, const std::string &language)
|
||||
{
|
||||
|
||||
clearStatus();
|
||||
|
||||
bool keys_file_exists;
|
||||
bool wallet_file_exists;
|
||||
tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists);
|
||||
// TODO: figure out how to setup logger;
|
||||
LOG_PRINT_L3("wallet_path: " << path << "");
|
||||
LOG_PRINT_L3("keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha
|
||||
<< " wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha);
|
||||
|
||||
|
||||
// add logic to error out if new wallet requested but named wallet file exists
|
||||
if (keys_file_exists || wallet_file_exists) {
|
||||
m_errorString = "attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting.";
|
||||
LOG_ERROR(m_errorString);
|
||||
m_status = Status_Error;
|
||||
return false;
|
||||
}
|
||||
// TODO: validate language
|
||||
m_wallet->set_seed_language(language);
|
||||
crypto::secret_key recovery_val, secret_key;
|
||||
try {
|
||||
recovery_val = m_wallet->generate(path, password, secret_key, false, false);
|
||||
m_password = password;
|
||||
m_status = Status_Ok;
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Error creating wallet: " << e.what());
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalletImpl::open(const std::string &path, const std::string &password)
|
||||
{
|
||||
clearStatus();
|
||||
try {
|
||||
// TODO: handle "deprecated"
|
||||
m_wallet->load(path, password);
|
||||
|
||||
m_password = password;
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Error opening wallet: " << e.what());
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
bool WalletImpl::recover(const std::string &path, const std::string &seed)
|
||||
{
|
||||
clearStatus();
|
||||
m_errorString.clear();
|
||||
if (seed.empty()) {
|
||||
m_errorString = "Electrum seed is empty";
|
||||
LOG_ERROR(m_errorString);
|
||||
m_status = Status_Error;
|
||||
return false;
|
||||
}
|
||||
|
||||
crypto::secret_key recovery_key;
|
||||
std::string old_language;
|
||||
if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) {
|
||||
m_errorString = "Electrum-style word list failed verification";
|
||||
m_status = Status_Error;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
m_wallet->set_seed_language(old_language);
|
||||
m_wallet->generate(path, "", recovery_key, true, false);
|
||||
// TODO: wallet->init(daemon_address);
|
||||
} catch (const std::exception &e) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
bool WalletImpl::close()
|
||||
{
|
||||
clearStatus();
|
||||
bool result = false;
|
||||
try {
|
||||
m_wallet->store();
|
||||
m_wallet->stop();
|
||||
result = true;
|
||||
} catch (const std::exception &e) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
LOG_ERROR("Error closing wallet: " << e.what());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string WalletImpl::seed() const
|
||||
{
|
||||
std::string seed;
|
||||
if (m_wallet)
|
||||
m_wallet->get_seed(seed);
|
||||
return seed;
|
||||
}
|
||||
|
||||
std::string WalletImpl::getSeedLanguage() const
|
||||
{
|
||||
return m_wallet->get_seed_language();
|
||||
}
|
||||
|
||||
void WalletImpl::setSeedLanguage(const std::string &arg)
|
||||
{
|
||||
m_wallet->set_seed_language(arg);
|
||||
}
|
||||
|
||||
int WalletImpl::status() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
std::string WalletImpl::errorString() const
|
||||
{
|
||||
return m_errorString;
|
||||
}
|
||||
|
||||
bool WalletImpl::setPassword(const std::string &password)
|
||||
{
|
||||
clearStatus();
|
||||
try {
|
||||
m_wallet->rewrite(m_wallet->get_wallet_file(), password);
|
||||
m_password = password;
|
||||
} catch (const std::exception &e) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
std::string WalletImpl::address() const
|
||||
{
|
||||
return m_wallet->get_account().get_public_address_str(m_wallet->testnet());
|
||||
}
|
||||
|
||||
bool WalletImpl::store(const std::string &path)
|
||||
{
|
||||
clearStatus();
|
||||
try {
|
||||
if (path.empty()) {
|
||||
m_wallet->store();
|
||||
} else {
|
||||
m_wallet->store_to(path, m_password);
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Error storing wallet: " << e.what());
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
|
||||
return m_status == Status_Ok;
|
||||
}
|
||||
|
||||
void WalletImpl::clearStatus()
|
||||
{
|
||||
m_status = Status_Ok;
|
||||
m_errorString.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////// WalletManager implementation /////////////////////////
|
||||
class WalletManagerImpl : public WalletManager
|
||||
{
|
||||
public:
|
||||
Wallet * createWallet(const std::string &path, const std::string &password,
|
||||
const std::string &language);
|
||||
Wallet * openWallet(const std::string &path, const std::string &password);
|
||||
virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo);
|
||||
virtual bool closeWallet(Wallet *wallet);
|
||||
bool walletExists(const std::string &path);
|
||||
std::string errorString() const;
|
||||
|
||||
|
||||
private:
|
||||
WalletManagerImpl() {}
|
||||
friend struct WalletManagerFactory;
|
||||
|
||||
std::string m_errorString;
|
||||
};
|
||||
|
||||
Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
|
||||
const std::string &language)
|
||||
{
|
||||
WalletImpl * wallet = new WalletImpl();
|
||||
wallet->create(path, password, language);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password)
|
||||
{
|
||||
WalletImpl * wallet = new WalletImpl();
|
||||
wallet->open(path, password);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &memo)
|
||||
{
|
||||
WalletImpl * wallet = new WalletImpl();
|
||||
wallet->recover(path, memo);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
bool WalletManagerImpl::closeWallet(Wallet *wallet)
|
||||
{
|
||||
WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet);
|
||||
bool result = wallet_->close();
|
||||
if (!result) {
|
||||
m_errorString = wallet_->errorString();
|
||||
} else {
|
||||
delete wallet_;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool WalletManagerImpl::walletExists(const std::string &path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string WalletManagerImpl::errorString() const
|
||||
{
|
||||
return m_errorString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////// WalletManagerFactory implementation //////////////////////
|
||||
WalletManager *WalletManagerFactory::getWalletManager()
|
||||
{
|
||||
|
||||
if (!g_walletManager) {
|
||||
epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_0);
|
||||
g_walletManager = new WalletManagerImpl();
|
||||
}
|
||||
|
||||
return g_walletManager;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
function create_wallet {
|
||||
wallet_name=$1
|
||||
echo 0 | simplewallet --testnet --trusted-daemon --daemon-address localhost:38081 --generate-new-wallet $wallet_name --password "" --restore-height=1
|
||||
}
|
||||
|
||||
|
||||
|
||||
create_wallet wallet_01.bin
|
||||
create_wallet wallet_02.bin
|
||||
create_wallet wallet_03.bin
|
||||
create_wallet wallet_04.bin
|
||||
create_wallet wallet_05.bin
|
||||
create_wallet wallet_06.bin
|
||||
|
||||
|
||||
#create_wallet wallet_m
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
rlwrap simplewallet --wallet-file wallet_m --password "" --testnet --trusted-daemon --daemon-address localhost:38081 --log-file wallet_m.log start_mining
|
||||
|
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
rlwrap simplewallet --wallet-file wallet_m --password "" --testnet --trusted-daemon --daemon-address localhost:38081 --log-file wallet_miner.log stop_mining
|
||||
|
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
rlwrap simplewallet --wallet-file wallet_01.bin --password "" --testnet --trusted-daemon --daemon-address localhost:38081 --log-file wallet_01.log
|
||||
|
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
rlwrap simplewallet --wallet-file wallet_02.bin --password "" --testnet --trusted-daemon --daemon-address localhost:38081 --log-file wallet_01.log
|
||||
|
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
rlwrap simplewallet --wallet-file wallet_03.bin --password "" --testnet --trusted-daemon --daemon-address localhost:38081 --log-file wallet_03.log
|
||||
|
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
rlwrap simplewallet --wallet-file wallet_04.bin --password "" --testnet --trusted-daemon --daemon-address localhost:38081 --log-file wallet_04.log
|
||||
|
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
rlwrap simplewallet --wallet-file wallet_05.bin --password "" --testnet --trusted-daemon --daemon-address localhost:38081 --log-file wallet_05.log
|
||||
|
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
rlwrap simplewallet --wallet-file wallet_m --password "" --testnet --trusted-daemon --daemon-address 127.0.0.1:38081 --log-file wallet_m.log
|
||||
|
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
|
||||
function send_funds {
|
||||
local amount=$1
|
||||
local dest=$(cat "$2.address.txt")
|
||||
|
||||
simplewallet --wallet-file wallet_m --password "" \
|
||||
--testnet --trusted-daemon --daemon-address localhost:38081 --log-file wallet_m.log \
|
||||
--command transfer $dest $amount
|
||||
}
|
||||
|
||||
|
||||
send_funds 100 wallet_01.bin
|
||||
send_funds 100 wallet_02.bin
|
||||
send_funds 100 wallet_03.bin
|
||||
send_funds 100 wallet_04.bin
|
||||
send_funds 100 wallet_05.bin
|
||||
send_funds 100 wallet_06.bin
|
||||
|
||||
|
Loading…
Reference in new issue