Electroneum
Loading...
Searching...
No Matches
transaction_history.cpp
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2// Copyrights(c) 2014-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31
32
33#include "transaction_history.h"
34#include "transaction_info.h"
35#include "wallet.h"
36
37#include "crypto/hash.h"
38#include "wallet/wallet2.h"
39
40
41#include <string>
42#include <list>
43
44using namespace epee;
45
46namespace Electroneum {
47
49
50
52 : m_wallet(wallet)
53{
54
55}
56
58{
59 for (auto t : m_history)
60 delete t;
61}
62
64{
65 boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
66 int result = m_history.size();
67 return result;
68}
69
71{
72 boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
73 // sanity check
74 if (index < 0)
75 return nullptr;
76 unsigned index_ = static_cast<unsigned>(index);
77 return index_ < m_history.size() ? m_history[index_] : nullptr;
78}
79
81{
82 boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
83 auto itr = std::find_if(m_history.begin(), m_history.end(),
84 [&](const TransactionInfo * ti) {
85 return ti->hash() == id;
86 });
87 return itr != m_history.end() ? *itr : nullptr;
88}
89
90std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const
91{
92 boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
93 return m_history;
94}
95
97{
98 // multithreaded access:
99 // boost::lock_guard<boost::mutex> guarg(m_historyMutex);
100 // for "write" access, locking exclusively
101 boost::unique_lock<boost::shared_mutex> lock(m_historyMutex);
102
103 // TODO: configurable values;
104 uint64_t min_height = 0;
105 uint64_t max_height = (uint64_t)-1;
106 uint64_t wallet_height = m_wallet->blockChainHeight();
107
108 // delete old transactions;
109 for (auto t : m_history)
110 delete t;
111 m_history.clear();
112
113 // transactions are stored in wallet2:
114 // - confirmed_transfer_details - out transfers
115 // - unconfirmed_transfer_details - pending out transfers
116 // - payment_details - input transfers
117
118 // payments are "input transactions";
119 // one input transaction contains only one transfer. e.g. <transaction_id> - <100ETN>
120
121 std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> in_payments;
122 m_wallet->m_wallet->get_payments(in_payments, min_height, max_height);
123 for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = in_payments.begin(); i != in_payments.end(); ++i) {
124 const tools::wallet2::payment_details &pd = i->second;
125 std::string payment_id = string_tools::pod_to_hex(i->first);
126 if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
127 payment_id = payment_id.substr(0,16);
129 ti->m_paymentid = payment_id;
130 ti->m_amount = pd.m_amount;
131 ti->m_direction = TransactionInfo::Direction_In;
132 ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
133 ti->m_blockheight = pd.m_block_height;
134 ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
135 ti->m_subaddrAccount = pd.m_subaddr_index.major;
136 ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index);
137 ti->m_timestamp = pd.m_timestamp;
138 ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
139 ti->m_unlock_time = pd.m_unlock_time;
140 m_history.push_back(ti);
141
142 }
143
144 // confirmed output transactions
145 // one output transaction may contain more than one etn transfer, e.g.
146 // <transaction_id>:
147 // transfer1: 100ETN to <address_1>
148 // transfer2: 50ETN to <address_2>
149 // fee: fee charged per transaction
150 //
151
152 std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> out_payments;
153 m_wallet->m_wallet->get_payments_out(out_payments, min_height, max_height);
154
155 for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = out_payments.begin();
156 i != out_payments.end(); ++i) {
157
158 const crypto::hash &hash = i->first;
159 const tools::wallet2::confirmed_transfer_details &pd = i->second;
160
161 uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known
162 uint64_t fee = pd.m_amount_in - pd.m_amount_out;
163
164
165 std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
166 if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
167 payment_id = payment_id.substr(0,16);
168
169
171 ti->m_paymentid = payment_id;
172 ti->m_amount = pd.m_amount_in - change - fee;
173 ti->m_fee = fee;
174 ti->m_direction = TransactionInfo::Direction_Out;
175 ti->m_hash = string_tools::pod_to_hex(hash);
176 ti->m_blockheight = pd.m_block_height;
177 ti->m_subaddrIndex = pd.m_subaddr_indices;
178 ti->m_subaddrAccount = pd.m_subaddr_account;
179 ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
180 ti->m_timestamp = pd.m_timestamp;
181 ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
182
183 // single output transaction might contain multiple transfers
184 for (const auto &d: pd.m_dests) {
185 ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->nettype(), d.is_subaddress, d.addr)});
186 }
187 m_history.push_back(ti);
188 }
189
190 // unconfirmed output transactions
191 std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments_out;
192 m_wallet->m_wallet->get_unconfirmed_payments_out(upayments_out);
193 for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments_out.begin(); i != upayments_out.end(); ++i) {
195 const crypto::hash &hash = i->first;
196 uint64_t amount = pd.m_amount_in;
197 uint64_t fee = amount - pd.m_amount_out;
198 std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
199 if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
200 payment_id = payment_id.substr(0,16);
202
204 ti->m_paymentid = payment_id;
205 ti->m_amount = amount - pd.m_change - fee;
206 ti->m_fee = fee;
207 ti->m_direction = TransactionInfo::Direction_Out;
208 ti->m_failed = is_failed;
209 ti->m_pending = true;
210 ti->m_hash = string_tools::pod_to_hex(hash);
211 ti->m_subaddrIndex = pd.m_subaddr_indices;
212 ti->m_subaddrAccount = pd.m_subaddr_account;
213 ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
214 ti->m_timestamp = pd.m_timestamp;
215 ti->m_confirmations = 0;
216 m_history.push_back(ti);
217 }
218
219
220 // unconfirmed payments (tx pool)
221 std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> upayments;
222 m_wallet->m_wallet->get_unconfirmed_payments(upayments);
223 for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) {
224 const tools::wallet2::payment_details &pd = i->second.m_pd;
225 std::string payment_id = string_tools::pod_to_hex(i->first);
226 if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
227 payment_id = payment_id.substr(0,16);
229 ti->m_paymentid = payment_id;
230 ti->m_amount = pd.m_amount;
231 ti->m_direction = TransactionInfo::Direction_In;
232 ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
233 ti->m_blockheight = pd.m_block_height;
234 ti->m_pending = true;
235 ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
236 ti->m_subaddrAccount = pd.m_subaddr_index.major;
237 ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index);
238 ti->m_timestamp = pd.m_timestamp;
239 ti->m_confirmations = 0;
240 m_history.push_back(ti);
241
242 LOG_PRINT_L1(__FUNCTION__ << ": Unconfirmed payment found " << pd.m_amount);
243 }
244
245}
246
247} // namespace
248
249namespace Bitelectroneum = Electroneum;
virtual std::vector< TransactionInfo * > getAll() const
virtual TransactionInfo * transaction(int index) const
#define LOG_PRINT_L1(x)
POD_CLASS hash
Definition hash.h:50
std::string pod_to_hex(const t_pod_type &s)
unsigned __int64 uint64_t
Definition stdint.h:136
The TransactionInfo - interface for displaying transaction information.
std::vector< cryptonote::tx_destination_entry > m_dests
Definition wallet2.h:400
cryptonote::subaddress_index m_subaddr_index
Definition wallet2.h:362
enum tools::wallet2::unconfirmed_transfer_details::@320170243027143365014242201170062371014272002365 m_state