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