Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTRecordList.cpp
Go to the documentation of this file.
1 /************************************************************
2 *
3 * OTRecordList.cpp
4 *
5 */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "../core/stdafx.hpp"
134 
135 #include "OTRecordList.hpp"
136 #include "OpenTransactions.hpp"
137 #include "OT_ME.hpp"
138 #include "OTAPI.hpp"
139 #include "OTAPI_Exec.hpp"
140 #include "Helpers.hpp"
141 #include "OTWallet.hpp"
142 
143 #include "../ext/OTPayment.hpp"
144 
145 #include "../core/OTAccount.hpp"
146 #include "../core/OTAssetContract.hpp"
147 #include "../core/OTLedger.hpp"
148 #include "../core/OTLog.hpp"
149 #include "../core/OTMessage.hpp"
150 #include "../core/OTPseudonym.hpp"
151 
152 #include <memory>
153 #include <algorithm>
154 
155 namespace
156 {
157 
158 const std::string Instrument_TypeStrings[] = {
159  // OTCheque is derived from OTTrackable, which is derived from OTInstrument,
160  // which is
161  // derived from OTScriptable, which is derived from OTContract.
162  "cheque", // A cheque drawn on a user's account.
163  "voucher", // A cheque drawn on a server account (cashier's cheque aka
164  // banker's cheque)
165  "invoice", // A cheque with a negative amount. (Depositing this causes a
166  // payment out, instead of a deposit in.)
167  "payment plan", // An OTCronItem-derived OTPaymentPlan, related to a
168  // recurring payment plan.
169  "smart contract", // An OTCronItem-derived OTSmartContract, related to a
170  // smart contract.
171  "cash", // An OTContract-derived OTPurse containing a list of cash OTTokens.
172  "ERROR_STATE"};
173 
174 const std::string& GetTypeString(int theType)
175 {
176  return Instrument_TypeStrings[theType];
177 }
178 
179 } // namespace
180 
181 namespace opentxs
182 {
183 
184 #define MC_UI_TEXT_TO "To: %s"
185 #define MC_UI_TEXT_FROM "From: %s"
186 
187 //#define MC_UI_TEXT_TO "<font color='grey'>To:</font> %s"
188 //#define MC_UI_TEXT_FROM "<font color='grey'>From:</font> %s"
189 
190 bool OT_API_Set_AddrBookCallback(OTLookupCaller& theCaller) // OTLookupCaller
191  // must have
192  // OTNameLookup
193  // attached already.
194 {
195  if (!theCaller.isCallbackSet()) {
196  otErr << __FUNCTION__
197  << ": ERROR:\nOTLookupCaller::setCallback() "
198  "MUST be called first, with an OTNameLookup-extended "
199  "class passed to it,\n"
200  "before then invoking this function (and passing that "
201  "OTLookupCaller as a parameter "
202  "into this function.)\n";
203  return false;
204  }
205 
206  otWarn << __FUNCTION__
207  << ": FYI, calling "
208  "OTRecordList::setAddrBookCaller(theCaller) now... "
209  "(which is where "
210  "OT internally sets its pointer to the Java caller "
211  "object, which must have been passed in as a "
212  "parameter to this function.\n";
213 
214  const bool bSuccess = OTRecordList::setAddrBookCaller(theCaller);
215 
216  otWarn << __FUNCTION__
217  << ": RESULT of call to OTRecordList::setAddrBookCaller: "
218  << (bSuccess ? "SUCCESS" : "FAILURE") << "";
219 
220  return bSuccess;
221 }
222 
223 // OTNameLookup CLASS
224 
226 {
227  // Note: Though the Java app will instantiate NameLookup once (its own
228  // version/subclass of it)
229  // and pass that instance to C++ so that OTRecordList can make calls to it
230  // from inside OT, that
231  // doesn't mean that C++ apps like Moneychanger won't make as many instances
232  // as they want. Bottom
233  // line? No error message necessary here as we have with the password
234  // callback.
235  //
236  // otErr << "OTNameLookup::~OTNameLookup: (This should only happen ONCE
237  // ONLY -- as the application is closing.)\n";
238  // std::cout << "OTNameLookup::~OTNameLookup()" << std:: endl;
239 }
240 
241 // virtual
242 std::string OTNameLookup::GetNymName(const std::string& str_id,
243  const std::string*) const
244 {
245  if (str_id.empty()) return "";
246 
247  return OTAPI_Wrap::GetNym_Name(str_id);
248 }
249 
250 // virtual
251 std::string OTNameLookup::GetAcctName(const std::string& str_id,
252  const std::string*, const std::string*,
253  const std::string*) const
254 {
255  if (str_id.empty()) return "";
256 
257  return OTAPI_Wrap::GetAccountWallet_Name(str_id);
258 }
259 
260 // virtual
261 std::string OTNameLookup::GetAddressName(const std::string&) const
262 {
263  return ""; // There are no native OT lookups for a Bitmessage address. (Only
264  // useful when overriding.)
265 }
266 
267 // OTLookupCaller CLASS
268 
270 {
271  otOut << "OTLookupCaller::~OTLookupCaller: (This should only "
272  "happen as the application is closing.)\n";
273 
274  delCallback();
275 }
276 
278 {
279  // if (nullptr != _callback) // TODO this may be a memory leak.
280  // delete _callback; // But I know we're currently crashing from
281  // deleting same object twice.
282  // And since the object comes from Java, who am I to delete it? Let Java
283  // clean it up.
284  if (isCallbackSet())
285  otOut << "OTLookupCaller::delCallback: WARNING: setting existing "
286  "callback object pointer to nullptr. "
287  "(This message doesn't trigger if it was already nullptr.)\n";
288  _callback = nullptr;
289 }
290 
292 {
293  otOut << "OTLookupCaller::setCallback: Attempting to set the "
294  "OTNameLookup pointer...\n";
295 
296  if (nullptr == cb) {
297  otOut << "OTLookupCaller::setCallback: ERROR: nullptr "
298  "OTNameLookup object passed in. (Returning.)\n";
299  return;
300  }
301 
302  delCallback(); // Sets _callback to nullptr, but LOGS first, if it was
303  // already
304  // set.
305  _callback = cb;
306  otOut << "OTLookupCaller::setCallback: FYI, the OTNameLookup "
307  "pointer was set.\n";
308 }
309 
311 {
312  return (nullptr == _callback) ? false : true;
313 }
314 
315 std::string OTLookupCaller::GetNymName(const std::string& str_id, // NymID
316  const std::string* p_server_id) const
317 {
318  if (isCallbackSet()) {
319  otWarn << "OTLookupCaller::GetNymName: FYI, Executing address "
320  "book callback...\n";
321  return _callback->GetNymName(str_id, p_server_id);
322  }
323  else {
324  otOut << "OTLookupCaller::GetNymName: "
325  "WARNING: Failed attempt to trigger address book "
326  "callback, due to \"it hasn't been set yet.\"\n";
327  }
328  return "";
329 }
330 
331 std::string OTLookupCaller::GetAcctName(const std::string& str_id, // AcctID
332  const std::string* p_nym_id,
333  const std::string* p_server_id,
334  const std::string* p_asset_id) const
335 {
336  if (isCallbackSet()) {
337  otWarn << "OTLookupCaller::GetAcctName: FYI, Executing address "
338  "book callback...\n";
339  return _callback->GetAcctName(str_id, p_nym_id, p_server_id,
340  p_asset_id);
341  }
342  else {
343  otOut << "OTLookupCaller::GetAcctName: "
344  "WARNING: Failed attempt to trigger address book "
345  "callback, due to \"it hasn't been set yet.\"\n";
346  }
347  return "";
348 }
349 
350 std::string OTLookupCaller::GetAddressName(const std::string& str_address) const
351 {
352  if (isCallbackSet()) {
353  otWarn << "OTLookupCaller::GetAddressName: FYI, Executing "
354  "address book callback...\n";
355  return _callback->GetAddressName(str_address);
356  }
357  else {
358  otOut << "OTLookupCaller::GetAddressName: "
359  "WARNING: Failed attempt to trigger address book "
360  "callback, due to \"it hasn't been set yet.\"\n";
361  }
362  return "";
363 }
364 
365 // static
366 
367 const std::string OTRecordList::s_blank("");
368 const std::string OTRecordList::s_message_type("message");
369 
370 std::string OTRecordList::s_strTextTo(MC_UI_TEXT_TO); // "To: %s"
371 std::string OTRecordList::s_strTextFrom(MC_UI_TEXT_FROM); // "From: %s"
372 
374 
375 // Takes ownership. UPDATE: doesn't, since he assumes the Java side
376 // created it and will therefore delete it when the time comes.
377 // I keep a pointer, but I don't delete the thing. Let Java do it.
378 //
379 // static
381 {
382  otLog3 << __FUNCTION__
383  << ": Attempting to set the address book caller... \n";
384 
385  if (!theCaller.isCallbackSet()) {
386  otErr << __FUNCTION__
387  << ": ERROR: OTLookupCaller::setCallback() "
388  "MUST be called first, with an OTNameLookup-extended "
389  "object passed to it,\n"
390  "BEFORE calling this function with that OTLookupCaller. "
391  "(Returning false.)\n";
392  return false;
393  }
394 
395  if (nullptr != s_pCaller) {
396  otErr
397  << __FUNCTION__
398  << ": WARNING: Setting the address book caller again, even though "
399  "it was apparently ALREADY set... (Meaning Java has probably "
400  "erroneously called this twice, "
401  "possibly passing the same OTLookupCaller both times.)\n";
402  // delete s_pCaller; // Let Java delete it.
403  }
404 
405  s_pCaller = &theCaller;
406  otWarn << __FUNCTION__
407  << ": FYI, Successfully set the address book caller object from "
408  "Java (or from another SWIG language.) Returning true.\n";
409 
410  return true;
411 }
412 // static
414 {
415  return s_pCaller;
416 }
417 
418 // SETUP:
419 
420 // Set the default server here.
421 
422 void OTRecordList::SetServerID(std::string str_id)
423 {
424  ClearServers();
425  AddServerID(str_id);
426 }
427 
428 // Unless you have many servers, then use this.
429 
430 void OTRecordList::AddServerID(std::string str_id)
431 {
432  m_servers.insert(m_servers.end(), str_id);
433 }
434 
435 // Also clears m_contents
436 
438 {
439  ClearContents();
440  m_servers.clear();
441 }
442 
443 void OTRecordList::SetAssetID(std::string str_id)
444 {
445  ClearAssets();
446  AddAssetID(str_id);
447 }
448 
449 void OTRecordList::AddAssetID(std::string str_id)
450 {
451  OTWallet* pWallet = OTAPI_Wrap::OTAPI()->GetWallet(
452  __FUNCTION__); // This logs and ASSERTs already.
453  OT_ASSERT_MSG(nullptr != pWallet,
454  "Wallet was nullptr. Should never happen.");
455  const OTString strAssetTypeID(str_id);
456  const OTIdentifier theAssetTypeID(strAssetTypeID);
457  std::string str_asset_name;
458  // Name is dollars, fraction is cents, TLA is USD and
459  // Symbol is $ (for example.) Here, we're grabbing the TLA.
460  //
461  OTAssetContract* pAssetContract = pWallet->GetAssetContract(theAssetTypeID);
462  if (nullptr != pAssetContract) {
463  str_asset_name =
464  pAssetContract->GetCurrencyTLA().Get(); // This might be "USD" --
465  // preferable that this
466  // works.
467  if (str_asset_name.empty())
468  str_asset_name =
469  pAssetContract->GetCurrencySymbol().Get(); // This might be "$".
470  if (str_asset_name.empty())
471  str_asset_name =
472  pAssetContract->GetCurrencyName().Get(); // This might be
473  // "dollars".
474  }
475  if (str_asset_name.empty())
476  str_asset_name = OTAPI_Wrap::GetAssetType_Name(
477  str_id); // Otherwise we try to grab the name.
478  // (Otherwise we just leave it blank. The ID is too big to cram in here.)
479  m_assets.insert(
480  std::pair<std::string, std::string>(str_id, str_asset_name));
481 }
482 
484 {
485  ClearContents();
486  m_assets.clear();
487 }
488 
489 void OTRecordList::SetNymID(std::string str_id)
490 {
491  ClearNyms();
492  AddNymID(str_id);
493 }
494 
495 void OTRecordList::AddNymID(std::string str_id)
496 {
497  m_nyms.insert(m_nyms.end(), str_id);
498 }
499 
501 {
502  ClearContents();
503  m_nyms.clear();
504 }
505 
506 void OTRecordList::SetAccountID(std::string str_id)
507 {
508  ClearAccounts();
509  AddAccountID(str_id);
510 }
511 
512 void OTRecordList::AddAccountID(std::string str_id)
513 {
514  m_accounts.insert(m_accounts.end(), str_id);
515 }
516 
518 {
519  ClearContents();
520  m_accounts.clear();
521 }
522 
524 {
525  m_bAutoAcceptCheques = bVal;
526 }
528 {
529  m_bAutoAcceptReceipts = bVal;
530 }
532 {
533  m_bAutoAcceptTransfers = bVal;
534 }
536 {
537  m_bAutoAcceptCash = bVal;
538 }
539 
541 {
542  return m_bAutoAcceptCheques;
543 }
545 {
546  return m_bAutoAcceptReceipts;
547 }
549 {
550  return m_bAutoAcceptTransfers;
551 }
553 {
554  return m_bAutoAcceptCash;
555 }
556 
557 typedef std::map<int32_t, OTPayment*> mapOfPayments;
558 
560 {
561  OTWallet* pWallet = OTAPI_Wrap::OTAPI()->GetWallet(
562  __FUNCTION__); // This logs and ASSERTs already.
563  if (nullptr == pWallet) {
564  otErr << "OTRecordList::" << __FUNCTION__
565  << ": Error: Wallet is nullptr.\n";
566  return false;
567  }
568  // LOOP NYMS
569  //
570  if (m_bAutoAcceptCheques || m_bAutoAcceptCash) {
571  int32_t nNymIndex = -1;
572  for (auto& it_nym : m_nyms) {
573  ++nNymIndex;
574  if (0 == nNymIndex)
575  otOut << "======================================\n "
576  << __FUNCTION__ << ": Beginning auto-accept loop through "
577  "Nyms...\n";
578  const std::string& str_nym_id(it_nym);
579  const OTIdentifier theNymID(str_nym_id);
580  const OTString strNymID(theNymID);
581  OTPseudonym* pNym = pWallet->GetNymByID(theNymID);
582  if (nullptr == pNym) continue;
583  // LOOP SERVERS
584  //
585  // For each nym, for each server, loop through its payments inbox
586  //
587  int32_t nServerIndex = -1;
588  for (auto& it_server : m_servers) {
589  ++nServerIndex;
590  const std::string& str_server_id(it_server);
591  const OTIdentifier theServerID(str_server_id);
592  OTServerContract* pServer =
593  pWallet->GetServerContract(theServerID);
594  OT_ASSERT(nullptr != pServer);
595  const OTString strServerID(theServerID);
596  otOut << __FUNCTION__ << ": Server " << nServerIndex
597  << ", ID: " << strServerID.Get() << "\n";
598  mapOfPayments thePaymentMap;
599  // OPTIMIZE FYI:
600  // The "NoVerify" version is much faster, but you will lose the
601  // ability to get the
602  // sender/recipient name from the receipts in the box. The code
603  // will, however, work
604  // either way.
605  //
606  OTLedger* pInbox =
607  m_bRunFast
609  theServerID, theNymID)
610  : OTAPI_Wrap::OTAPI()->LoadPaymentInbox(theServerID,
611  theNymID);
612  std::unique_ptr<OTLedger> theInboxAngel(pInbox);
613 
614  // It loaded up, so let's loop through it.
615  if (nullptr != pInbox) {
616  int32_t nIndex = (-1);
617  for (auto& it : pInbox->GetTransactionMap()) {
618  OTTransaction* pBoxTrans = it.second;
619  OT_ASSERT(nullptr != pBoxTrans);
620  ++nIndex; // 0 on first iteration.
621  otOut << __FUNCTION__
622  << ": Incoming payment: " << nIndex << "\n";
623  const std::string* p_str_asset_type =
624  &OTRecordList::s_blank; // <========== ASSET TYPE
625  const std::string* p_str_asset_name =
626  &OTRecordList::s_blank; // asset type display name.
627  std::string str_type; // Instrument type.
628  OTPayment* pPayment =
629  GetInstrument(*pNym, nIndex, *pInbox);
630  // ===> Returns financial instrument by index.
631  std::unique_ptr<OTPayment> thePaymentAngel(pPayment);
632  if (nullptr ==
633  pPayment) // then we treat it like it's abbreviated.
634  {
635  otErr << __FUNCTION__
636  << ": Payment retrieved from payments "
637  "inbox was nullptr. (It's abbreviated?) "
638  "Skipping.\n";
639  }
640  // We have pPayment, the instrument accompanying the
641  // receipt in the payments inbox.
642  //
643  else if (pPayment->IsValid() &&
644  pPayment->SetTempValues()) {
645  OTIdentifier theAssetTypeID;
646 
647  if (pPayment->GetAssetTypeID(theAssetTypeID)) {
648  OTString strTemp(theAssetTypeID);
649  const std::string str_inpmt_asset(
650  strTemp.Get()); // The asset type we found
651  // on the payment (if we
652  // found anything.)
653  auto it_asset = m_assets.find(str_inpmt_asset);
654  if (it_asset != m_assets.end()) // Found it on
655  // the map of
656  // asset types
657  // we care
658  // about.
659  {
660  p_str_asset_type =
661  &(it_asset->first); // Set the asset
662  // type ID.
663  p_str_asset_name =
664  &(it_asset->second); // The CurrencyTLA.
665  // Examples: USD,
666  // BTC, etc.
667  }
668  else {
669  // There was definitely an asset type on the
670  // instrument, and it definitely
671  // did not match any of the assets that we
672  // care about.
673  // Therefore, skip.
674  //
675  otErr << __FUNCTION__
676  << ": Skipping: Incoming payment (we "
677  "don't care about asset "
678  << str_inpmt_asset.c_str() << ")\n";
679  continue;
680  }
681  }
682  // By this point, p_str_asset_type and
683  // p_str_asset_name are definitely set.
684  OT_ASSERT(nullptr != p_str_asset_type); // and it's
685  // either
686  // blank, or
687  // it's one of
688  // the asset
689  // types we
690  // care about.
691  OT_ASSERT(nullptr != p_str_asset_name); // and it's
692  // either
693  // blank, or
694  // it's one of
695  // the asset
696  // types we
697  // care about.
698  // Instrument type (cheque, voucher, etc)
699  int32_t nType =
700  static_cast<int32_t>(pPayment->GetType());
701 
702  str_type = GetTypeString(nType);
703  // For now, we only accept cash, cheques and
704  // vouchers.
705  //
706  if ((m_bAutoAcceptCheques &&
707  ((0 == str_type.compare("cheque")) ||
708  (0 == str_type.compare("voucher")))) ||
709  (m_bAutoAcceptCash &&
710  (0 == str_type.compare("cash")))) {
711  otOut << __FUNCTION__
712  << ": Adding to acceptance "
713  "list: pending incoming "
714  << str_type.c_str() << ".\n";
715  thePaymentMap.insert(
716  std::pair<int32_t, OTPayment*>(
717  nIndex, thePaymentAngel.release()));
718  }
719  else
720  otOut << __FUNCTION__
721  << ": Unknown instrument type: "
722  << str_type.c_str() << "\n";
723  }
724  else
725  otOut << __FUNCTION__
726  << ": Failed in pPayment->IsValid "
727  "or pPayment->SetTempValues()\n";
728  }
729  } // looping through payments inbox.
730  else
731  otWarn << __FUNCTION__
732  << ": Failed loading payments inbox. "
733  "(Probably just doesn't exist yet.)\n";
734  // Above we compiled a list of purses, cheques / vouchers to
735  // accept.
736  // If there are any on that list, then ACCEPT them here.
737  //
738  if (!thePaymentMap.empty()) {
739  for (mapOfPayments::reverse_iterator it =
740  thePaymentMap.rbegin();
741  it != thePaymentMap.rend();
742  ++it) // backwards since we are processing (removing)
743  // payments by index.
744  {
745  int32_t lIndex = it->first;
746  OTPayment* pPayment = it->second;
747  if (nullptr == pPayment) {
748  otErr << __FUNCTION__
749  << ": Error: payment pointer was "
750  "nullptr! (Should never happen.) "
751  "Skipping.\n";
752  continue;
753  }
754  OTString payment;
755  if (!pPayment->GetPaymentContents(payment)) {
756  otErr << __FUNCTION__
757  << ": Error: Failed while trying to "
758  "get payment string contents. "
759  "(Skipping.)\n";
760  continue;
761  }
762  OTIdentifier paymentAssetType;
763  bool bGotAsset =
764  pPayment->GetAssetTypeID(paymentAssetType);
765 
766  std::string str_asset_type_id;
767 
768  if (bGotAsset) {
769  const OTString strAssetTypeID(paymentAssetType);
770  str_asset_type_id = strAssetTypeID.Get();
771  }
772  if (str_asset_type_id.empty()) {
773  otErr << __FUNCTION__
774  << ": Error: Failed while trying to "
775  "get asset type ID from payment. "
776  "(Skipping.)\n";
777  continue;
778  }
779  // pick an account to deposit the cheque into.
780  for (auto& it_acct : m_accounts) {
781  const std::string& str_account_id(it_acct);
782  const OTIdentifier theAccountID(str_account_id);
783  OTAccount* pAccount =
784  pWallet->GetAccount(theAccountID);
785  OT_ASSERT(nullptr != pAccount);
786  const OTIdentifier& theAcctNymID =
787  pAccount->GetUserID();
788  const OTIdentifier& theAcctServerID =
789  pAccount->GetPurportedServerID();
790  const OTIdentifier& theAcctAssetID =
791  pAccount->GetAssetTypeID();
792  const std::string str_acct_type =
793  pAccount->GetTypeString();
794  // const OTString
795  // strAcctNymID (theAcctNymID);
796  const OTString strAcctServerID(theAcctServerID);
797  const OTString strAcctAssetID(theAcctAssetID);
798  // If the current account is owned by the Nym, AND
799  // it has the same asset type ID
800  // as the cheque being deposited, then let's deposit
801  // the cheque into that account.
802  //
803  // TODO: we should first just see if the default
804  // account matches, instead of doing
805  // this loop in the first place.
806  //
807  if ((theNymID == theAcctNymID) &&
808  (strAcctServerID.Compare(
809  str_server_id.c_str())) &&
810  (strAcctAssetID.Compare(
811  str_asset_type_id.c_str())) &&
812  (0 ==
813  str_acct_type.compare("simple"))) // No issuer
814  // accounts
815  // allowed here. Only
816  // simple accounts.
817  {
818  // Accept it.
819  //
820  OTString strIndices;
821  strIndices.Format("%d", lIndex);
822  const std::string str_indices(strIndices.Get());
823 
824  OT_ME madeEasy;
825  if (!madeEasy.accept_from_paymentbox(
826  str_account_id, str_indices, "ANY")) {
827  otErr << __FUNCTION__
828  << ": Error while trying to "
829  "accept this instrument.\n";
830  }
831  break;
832  }
833  } // loop through accounts to find one to deposit cheque
834  // into.
835  } // Loop through payments to deposit.
836  // Empty the list and delete the payments inside.
837  //
838  for (auto& it : thePaymentMap) {
839  OTPayment* pPayment = it.second;
840  if (nullptr != pPayment) delete pPayment;
841  pPayment = nullptr;
842  }
843  thePaymentMap.clear();
844  } // if (!thePaymentMap.empty())
845  }
846  }
847  }
848 
849  // ASSET ACCOUNT -- INBOX
850  //
851  // Loop through the Accounts.
852  //
853  if (m_bAutoAcceptReceipts || m_bAutoAcceptTransfers) {
854  int32_t nAccountIndex = -1;
855  for (auto& it_acct : m_accounts) {
856  ++nAccountIndex; // (0 on first iteration.)
857  if (0 == nAccountIndex)
858  otOut << "---------------------------------\n " << __FUNCTION__
859  << ": "
860  "Beginning auto-accept loop through the "
861  "accounts in the wallet...\n";
862  // For each account, loop through its inbox, outbox, and record box.
863  const std::string& str_account_id(it_acct);
864  const OTIdentifier theAccountID(str_account_id);
865  OTAccount* pAccount = pWallet->GetAccount(theAccountID);
866  OT_ASSERT(nullptr != pAccount);
867  const OTIdentifier& theNymID = pAccount->GetUserID();
868  const OTIdentifier& theServerID = pAccount->GetPurportedServerID();
869  const OTIdentifier& theAssetID = pAccount->GetAssetTypeID();
870  const OTString strNymID(theNymID);
871  const OTString strServerID(theServerID);
872  const OTString strAssetID(theAssetID);
873  otOut << "------------\n" << __FUNCTION__
874  << ": Account: " << nAccountIndex
875  << ", ID: " << str_account_id.c_str() << "\n";
876  const std::string str_nym_id(strNymID.Get());
877  const std::string str_server_id(strServerID.Get());
878  const std::string str_asset_id(strAssetID.Get());
879  // NOTE: Since this account is already on my "care about" list for
880  // accounts,
881  // I wouldn't bother double-checking my "care about" lists for
882  // servers, nyms,
883  // and asset types. But I still look up the appropriate string for
884  // each, since
885  // I have to pass a reference to it into the constructor for
886  // OTRecord. (To a version
887  // that won't be deleted, since the OTRecord will reference it. And
888  // the "care about"
889  // list definitely contains a copy of the string that won't be
890  // deleted.)
891  //
892  auto it_nym = std::find(m_nyms.begin(), m_nyms.end(), str_nym_id);
893  auto it_server =
894  std::find(m_servers.begin(), m_servers.end(), str_server_id);
895  auto it_asset = m_assets.find(str_asset_id);
896  if ((m_nyms.end() == it_nym) || (m_servers.end() == it_server) ||
897  (m_assets.end() == it_asset)) {
898  otOut << __FUNCTION__ << ": Skipping an account ("
899  << str_account_id.c_str()
900  << ") since its Nym, or Server, "
901  "or Asset Type wasn't on my list.\n";
902  continue;
903  }
904  // Loop through asset account INBOX.
905  //
906  // OPTIMIZE FYI:
907  // NOTE: LoadInbox is much SLOWER than LoadInboxNoVerify, but it
908  // also lets you get
909  // the NAME off of the box receipt. So if you are willing to GIVE UP
910  // the NAME, in
911  // return for FASTER PERFORMANCE, then call SetFastMode() before
912  // Populating.
913  //
914  OTLedger* pInbox = m_bRunFast
916  theServerID, theNymID, theAccountID)
918  theServerID, theNymID, theAccountID);
919  std::unique_ptr<OTLedger> theInboxAngel(pInbox);
920  if (nullptr == pInbox) {
921  otOut << __FUNCTION__ << ": Skipping an account ("
922  << str_account_id.c_str()
923  << ") since its "
924  "inbox failed to load (have you downloaded "
925  "the latest one?)\n";
926  continue;
927  }
928  const OTString strInbox(*pInbox);
929  const std::string str_inbox(strInbox.Get());
930  bool bFoundAnyToAccept = false;
931  std::string strResponseLedger;
932  int32_t nInboxIndex = -1;
933  // It loaded up, so let's loop through it.
934  for (auto& it : pInbox->GetTransactionMap()) {
935  ++nInboxIndex; // (0 on first iteration.)
936  if (0 == nInboxIndex)
937  otOut
938  << __FUNCTION__
939  << ": Beginning loop through asset account INBOX...\n";
940  OTTransaction* pBoxTrans = it.second;
941  OT_ASSERT(nullptr != pBoxTrans);
942  otOut << __FUNCTION__ << ": Inbox index: " << nInboxIndex
943  << "\n";
944  const std::string str_type(
945  pBoxTrans->GetTypeString()); // pending, chequeReceipt, etc.
946  const bool bIsTransfer =
947  (OTTransaction::pending == pBoxTrans->GetType());
948  const bool bIsReceipt = !bIsTransfer;
949  if ((m_bAutoAcceptReceipts && bIsReceipt) ||
950  (m_bAutoAcceptTransfers && bIsTransfer)) {
951  otOut << __FUNCTION__ << ": Auto-accepting: incoming "
952  << (bIsTransfer ? "pending transfer" : "receipt")
953  << " (str_type: " << str_type.c_str() << ")\n";
954  // If we haven't found any yet, then this must be the first
955  // one!
956  //
957  if (!bFoundAnyToAccept) {
958  bFoundAnyToAccept = true;
959  OT_ME madeEasy;
960 
961  int32_t nNumberNeeded = 20;
962  if (!madeEasy.make_sure_enough_trans_nums(
963  nNumberNeeded, // I'm just hardcoding: "Make
964  // sure I have at least 20
965  // transaction numbers."
966  str_server_id, str_nym_id)) {
967  otOut << "\n\nFailure: "
968  "make_sure_enough_trans_nums: "
969  "returned false. (Skipping inbox "
970  "for account " << str_account_id.c_str()
971  << ")\n";
972  continue;
973  }
974  strResponseLedger =
976  str_server_id, str_nym_id, str_account_id,
977  str_inbox);
978 
979  if (strResponseLedger.empty()) {
980  otOut << "\n\nFailure: "
981  "OT_API_Ledger_CreateResponse "
982  "returned nullptr. (Skipping inbox "
983  "for account " << str_account_id.c_str()
984  << ")\n";
985  continue;
986  }
987  }
988  const OTString strTrans(*pBoxTrans);
989  const std::string str_trans(strTrans.Get());
990  std::string strNEW_ResponseLEDGER =
992  str_server_id, str_nym_id, str_account_id,
993  strResponseLedger, str_trans,
994  true); // accept = true (versus rejecting a pending
995  // transfer, for example.)
996 
997  if (strNEW_ResponseLEDGER.empty()) {
998  otOut << "\n\nFailure: "
999  "OT_API_Transaction_CreateResponse "
1000  "returned nullptr. (Skipping inbox for "
1001  "account " << str_account_id.c_str() << ")\n";
1002  continue;
1003  }
1004  strResponseLedger = strNEW_ResponseLEDGER;
1005  }
1006  }
1007  // Okay now we have the response ledger all ready to go, let's
1008  // process it!
1009  //
1010  if (bFoundAnyToAccept && !strResponseLedger.empty()) {
1011  std::string strFinalizedResponse =
1013  str_server_id, str_nym_id, str_account_id,
1014  strResponseLedger);
1015 
1016  if (strFinalizedResponse.empty()) {
1017  otOut << "\n\nFailure: "
1018  "OT_API_Ledger_FinalizeResponse returned "
1019  "nullptr. (Skipping inbox for account "
1020  << str_account_id.c_str() << ")\n";
1021  continue;
1022  }
1023  // Instantiate the "OT Made Easy" object.
1024  //
1025  OT_ME madeEasy;
1026 
1027  // Server communications are handled here...
1028  //
1029  std::string strResponse = madeEasy.process_inbox(
1030  str_server_id, str_nym_id, str_account_id,
1031  strFinalizedResponse);
1032  std::string strAttempt = "process_inbox";
1033 
1034  int32_t nInterpretReply = madeEasy.InterpretTransactionMsgReply(
1035  str_server_id, str_nym_id, str_account_id, strAttempt,
1036  strResponse);
1037 
1038  if (1 == nInterpretReply) {
1039  // Download all the intermediary files (account balance,
1040  // inbox, outbox, etc)
1041  // since they have probably changed from this operation.
1042  //
1043  bool bRetrieved = madeEasy.retrieve_account(
1044  str_server_id, str_nym_id, str_account_id,
1045  true); // bForceDownload defaults to false.
1046 
1047  otOut << "\n\nServer response (" << strAttempt.c_str()
1048  << "): SUCCESS "
1049  "processing/accepting inbox.\n";
1050  otOut << (bRetrieved ? "Success" : "Failed")
1051  << " retrieving intermediary files for account.\n";
1052  }
1053  }
1054  }
1055  }
1056  return true;
1057 }
1058 
1060 {
1061  return j->operator<(*i);
1062 }
1063 
1064 // POPULATE:
1065 
1066 // Populates m_contents from OT API. Calls ClearContents().
1067 
1069 {
1070  OT_ASSERT(nullptr != m_pLookup);
1071  ClearContents();
1072  // Loop through all the accounts.
1073  //
1074  // From Open-Transactions.h:
1075  // OTAPI_Wrap::OTAPI()->GetServerCount()
1076  //
1077  // From OTAPI.h:
1078  // OTAPI_Wrap::GetServerCount() // wraps the above call.
1079  //
1080  OTWallet* pWallet = OTAPI_Wrap::OTAPI()->GetWallet(
1081  __FUNCTION__); // This logs and ASSERTs already.
1082  if (nullptr == pWallet) {
1083  otErr << "OTRecordList::" << __FUNCTION__
1084  << ": Error: Wallet is nullptr.\n";
1085  return false;
1086  }
1087  // Before populating, process out any items we're supposed to accept
1088  // automatically.
1089  //
1091  // OUTPAYMENTS, OUTMAIL, MAIL, PAYMENTS INBOX, and RECORD BOX (2 kinds.)
1092  // Loop through the Nyms.
1093  //
1094  int32_t nNymIndex = -1;
1095  for (auto& it_nym : m_nyms) {
1096  ++nNymIndex;
1097  if (0 == nNymIndex)
1098  otOut << "=============== " << __FUNCTION__
1099  << ": Beginning loop through Nyms...\n";
1100  const std::string& str_nym_id(it_nym);
1101  const OTIdentifier theNymID(str_nym_id);
1102  const OTString strNymID(theNymID);
1103  OTPseudonym* pNym = pWallet->GetNymByID(theNymID);
1104  if (nullptr == pNym) continue;
1105  // For each Nym, loop through his OUTPAYMENTS box.
1106  //
1107  const int32_t nOutpaymentsCount =
1109 
1110  otOut << "--------\n" << __FUNCTION__ << ": Nym " << nNymIndex
1111  << ", nOutpaymentsCount: " << nOutpaymentsCount
1112  << ", ID: " << strNymID.Get() << "\n";
1113  for (int32_t nCurrentOutpayment = 0;
1114  nCurrentOutpayment < nOutpaymentsCount; ++nCurrentOutpayment) {
1115  otOut << __FUNCTION__
1116  << ": Outpayment instrument: " << nCurrentOutpayment << "\n";
1117  const OTString strOutpayment(
1119  str_nym_id, nCurrentOutpayment));
1120  std::string str_memo;
1121  OTPayment theOutPayment(strOutpayment);
1122 
1123  if (!theOutPayment.IsValid() || !theOutPayment.SetTempValues()) {
1124  otErr << __FUNCTION__
1125  << ": Skipping: Unable to load outpayments "
1126  "instrument from string:\n" << strOutpayment.Get()
1127  << "\n";
1128  continue;
1129  }
1130  int64_t lAmount = 0;
1131  std::string str_amount; // <========== AMOUNT
1132 
1133  if (theOutPayment.GetAmount(lAmount)) {
1134  if (((OTPayment::CHEQUE == theOutPayment.GetType()) ||
1135  (OTPayment::PURSE == theOutPayment.GetType()) ||
1136  (OTPayment::VOUCHER == theOutPayment.GetType())) &&
1137  (lAmount > 0))
1138  lAmount *= (-1);
1139 
1140  if ((OTPayment::INVOICE == theOutPayment.GetType()) &&
1141  (lAmount < 0))
1142  lAmount *= (-1);
1143 
1144  OTString strTemp;
1145  strTemp.Format("%" PRId64 "", lAmount);
1146  str_amount = strTemp.Get();
1147  }
1148  OTIdentifier theAssetTypeID;
1149  const std::string* p_str_asset_type =
1150  &OTRecordList::s_blank; // <========== ASSET TYPE
1151  const std::string* p_str_asset_name =
1152  &OTRecordList::s_blank; // asset type display name.
1153  std::string str_outpmt_asset; // The asset type we found on the
1154  // payment (if we found anything.)
1155 
1156  if (theOutPayment.GetAssetTypeID(theAssetTypeID)) {
1157  OTString strTemp(theAssetTypeID);
1158  str_outpmt_asset = strTemp.Get();
1159  auto it_asset = m_assets.find(str_outpmt_asset);
1160  if (it_asset != m_assets.end()) // Found it on the map of asset
1161  // types we care about.
1162  {
1163  p_str_asset_type =
1164  &(it_asset->first); // Set the asset type ID.
1165  p_str_asset_name = &(it_asset->second); // The CurrencyTLA.
1166  // Examples: USD,
1167  // BTC, etc.
1168  }
1169  else {
1170  // There was definitely an asset type on the instrument, and
1171  // it definitely
1172  // did not match any of the assets that we care about.
1173  // Therefore, skip.
1174  //
1175  otOut << __FUNCTION__
1176  << ": Skipping outpayment (we don't care "
1177  "about asset type " << str_outpmt_asset.c_str()
1178  << ")\n";
1179  continue;
1180  }
1181  }
1182  // By this point, p_str_asset_type and p_str_asset_name are
1183  // definitely set.
1184  OT_ASSERT(nullptr != p_str_asset_type); // and it's either blank, or
1185  // it's one of the asset types
1186  // we care about.
1187  OT_ASSERT(nullptr != p_str_asset_name); // and it's either blank, or
1188  // it's one of the asset types
1189  // we care about.
1190  OTIdentifier theAccountID;
1191  const std::string* p_str_account =
1192  &OTRecordList::s_blank; // <========== ACCOUNT
1193  std::string str_outpmt_account; // The accountID we found on the
1194  // payment (if we found anything.)
1195 
1196  if (theOutPayment.GetSenderAcctIDForDisplay(
1197  theAccountID)) // Since Nym is ME, the Account must be MY
1198  // acct.
1199  { // (In Outpayments, the SENDER's account is MY acct.)
1200  OTString strTemp(theAccountID);
1201  str_outpmt_account = strTemp.Get();
1202  auto it_acct = std::find(m_accounts.begin(), m_accounts.end(),
1203  str_outpmt_account);
1204  if (it_acct != m_accounts.end()) // Found it on the list of
1205  // accounts we care about.
1206  {
1207  p_str_account = &(*it_acct);
1208  }
1209  // We don't skip vouchers since the sender account (e.g. the
1210  // server's account)
1211  // is definitely not one of my accounts -- so the voucher would
1212  // end up getting
1213  // skipped every single time.
1214  //
1215  // else if (OTPayment::VOUCHER !=
1216  // theOutPayment.GetType())
1217  else {
1218  // There was definitely an account on the instrument, and it
1219  // definitely
1220  // did not match any of the accounts that we care about.
1221  // Therefore, skip.
1222  //
1223  otOut << __FUNCTION__
1224  << ": Skipping outpayment (we don't care "
1225  "about account " << str_outpmt_account.c_str()
1226  << ")\n";
1227  continue;
1228  }
1229  }
1230  // By this point, p_str_account is definitely set.
1231  OT_ASSERT(nullptr !=
1232  p_str_account); // and it's either blank, or it's
1233  // one of the accounts we care
1234  // about.
1235  // strOutpayment contains the actual outgoing payment instrument.
1236  //
1237  const std::string str_outpmt_server =
1239  str_nym_id, nCurrentOutpayment);
1240  const std::string str_outpmt_recipientID =
1242  str_nym_id, nCurrentOutpayment);
1243  // str_outpmt_server is the server for this outpayment.
1244  // But is that server on our list of servers that we care about?
1245  // Let's see if that server is on m_servers (otherwise we can skip
1246  // it.)
1247  // Also, let's do the same for asset types.
1248  //
1249  auto it_server = std::find(m_servers.begin(), m_servers.end(),
1250  str_outpmt_server);
1251 
1252  if (it_server != m_servers.end()) // Found the serverID on the list
1253  // of servers we care about.
1254  {
1255  // TODO OPTIMIZE: instead of looking up the Nym's name every
1256  // time, look it
1257  // up ONCE when first adding the NymID. Add it to a map, instead
1258  // of a list,
1259  // and add the Nym's name as the second item in the map's pair.
1260  // (Just like I already did with the asset type.)
1261  //
1262  OTString strName(m_pLookup->GetNymName(str_outpmt_recipientID,
1263  &(*it_server))),
1264  strNameTemp;
1265  std::string str_name;
1266 
1267  if (strName.Exists())
1268  strNameTemp.Format(OTRecordList::textTo(), strName.Get());
1269  else
1270  strNameTemp.Format(OTRecordList::textTo(),
1271  str_outpmt_recipientID.c_str());
1272 
1273  str_name = strNameTemp.Get();
1274  OTString strMemo;
1275  if (theOutPayment.GetMemo(strMemo)) {
1276  str_memo = strMemo.Get();
1277  }
1278  // For the "date" on this record we're using the "valid from"
1279  // date on the instrument.
1280  std::string str_date = "0";
1281  time64_t tFrom = OT_TIME_ZERO;
1282  time64_t tTo = OT_TIME_ZERO;
1283 
1284  if (theOutPayment.GetValidFrom(tFrom)) {
1285  const uint64_t lFrom = OTTimeGetSecondsFromTime(tFrom);
1286  OTString strFrom;
1287  strFrom.Format("%" PRIu64 "", lFrom);
1288  str_date = strFrom.Get();
1289  }
1290  theOutPayment.GetValidTo(tTo);
1291  // Instrument type (cheque, voucher, etc)
1292  //
1293  int32_t nType = static_cast<int32_t>(theOutPayment.GetType());
1294 
1295  const std::string& str_type = GetTypeString(nType);
1296  // CREATE A OTRecord AND POPULATE IT...
1297  //
1298  otOut << __FUNCTION__
1299  << ": ADDED: pending outgoing instrument (str_type: "
1300  << str_type.c_str() << ")\n";
1301 
1302  shared_ptr_OTRecord sp_Record(new OTRecord(
1303  *it_server, *p_str_asset_type, *p_str_asset_name,
1304  str_nym_id, // This is the Nym WHOSE BOX IT IS.
1305  *p_str_account, // This is the Nym's account according to
1306  // the payment instrument, IF that account
1307  // was found on our list of accounts we care
1308  // about. Or it's blank if no account was
1309  // found on the payment instrument.
1310  // Everything above this line, it stores a reference to an
1311  // external string.
1312  // Everything below this line, it makes its own internal
1313  // copy of the string.
1314  str_name, // name of recipient (since its in outpayments
1315  // box.)
1316  str_date, // the "valid from" date on the instrument.
1317  str_amount,
1318  str_type, // cheque, voucher, smart contract, etc
1319  true, // bIsPending=true since its in the outpayments box.
1320  true, // bIsOutgoing=true. Otherwise it'd be in record box
1321  // already.
1322  false, // IsRecord
1323  false, // IsReceipt
1325  sp_Record->SetContents(strOutpayment.Get());
1326  sp_Record->SetOtherNymID(str_outpmt_recipientID);
1327  if (!str_memo.empty()) sp_Record->SetMemo(str_memo);
1328  sp_Record->SetDateRange(tFrom, tTo);
1329  sp_Record->SetBoxIndex(nCurrentOutpayment);
1330  int64_t lTransNum = 0;
1331  theOutPayment.GetOpeningNum(lTransNum, theNymID);
1332  sp_Record->SetTransactionNum(lTransNum);
1333  m_contents.push_back(sp_Record);
1334  }
1335  else // the server for this outpayment is not on the list of
1336  // servers we care about. Skip this outpayment.
1337  {
1338  otOut << __FUNCTION__
1339  << ": Skipping outgoing instrument (we don't "
1340  "care about server " << str_outpmt_server.c_str()
1341  << ")\n";
1342  continue;
1343  }
1344  } // for outpayments.
1345  // For each Nym, loop through his MAIL box.
1346  //
1347  const int32_t nMailCount = OTAPI_Wrap::GetNym_MailCount(str_nym_id);
1348  for (int32_t nCurrentMail = 0; nCurrentMail < nMailCount;
1349  ++nCurrentMail) {
1350  otOut << __FUNCTION__ << ": Mail index: " << nCurrentMail << "\n";
1351  OTMessage* pMsg = pNym->GetMailByIndex(nCurrentMail);
1352  OT_ASSERT(nullptr != pMsg);
1353  const std::string str_mail_server =
1355  nCurrentMail);
1356  const std::string str_mail_senderID =
1358  nCurrentMail);
1359  // str_mail_server is the server for this mail.
1360  // But is that server on our list of servers that we care about?
1361  // Let's see if that server is on m_servers (otherwise we can skip
1362  // it.)
1363  //
1364  auto it_server =
1365  std::find(m_servers.begin(), m_servers.end(), str_mail_server);
1366 
1367  if (it_server != m_servers.end()) // Found the serverID on the list
1368  // of servers we care about.
1369  {
1370  // TODO OPTIMIZE: instead of looking up the Nym's name every
1371  // time, look it
1372  // up ONCE when first adding the NymID. Add it to a map, instead
1373  // of a list,
1374  // and add the Nym's name as the second item in the map's pair.
1375  // (Just like I already did with the asset type.)
1376  //
1377  OTString strName(
1378  m_pLookup->GetNymName(str_mail_senderID, &(*it_server))),
1379  strNameTemp;
1380  std::string str_name;
1381 
1382  if (strName.Exists())
1383  strNameTemp.Format(OTRecordList::textFrom(), strName.Get());
1384  else
1385  strNameTemp.Format(OTRecordList::textFrom(),
1386  str_mail_senderID.c_str());
1387 
1388  str_name = strNameTemp.Get();
1389  const std::string* p_str_asset_type =
1390  &OTRecordList::s_blank; // <========== ASSET TYPE
1391  const std::string* p_str_asset_name =
1392  &OTRecordList::s_blank; // asset type display name.
1393  const std::string* p_str_account =
1394  &OTRecordList::s_blank; // <========== ACCOUNT
1395 
1396  std::string str_amount; // There IS NO amount, on mail. (So we
1397  // leave this empty.)
1398 
1399  uint64_t lDate = pMsg->m_lTime;
1400  OTString strDate;
1401  strDate.Format("%" PRIu64 "", lDate);
1402  const std::string str_date(strDate.Get());
1403  // CREATE A OTRecord AND POPULATE IT...
1404  //
1405  otOut << __FUNCTION__ << ": ADDED: incoming mail.\n";
1406 
1407  shared_ptr_OTRecord sp_Record(new OTRecord(
1408  *it_server, *p_str_asset_type, *p_str_asset_name,
1409  str_nym_id, // This is the Nym WHOSE BOX IT IS.
1410  *p_str_account, // This is the Nym's account according to
1411  // the payment instrument, IF that account
1412  // was found on our list of accounts we care
1413  // about. Or it's blank if no account was
1414  // found on the payment instrument.
1415  // Everything above this line, it stores a reference to an
1416  // external string.
1417  // Everything below this line, it makes its own internal
1418  // copy of the string.
1419  str_name, // name of sender (since its in incoming mail
1420  // box.)
1421  str_date, // How do we get the date from a mail?
1422  str_amount, OTRecordList::s_message_type, // "message"
1423  false, // bIsPending=false since its already received.
1424  false, // bIsOutgoing=false. It's incoming mail, not
1425  // outgoing mail.
1426  false, // IsRecord
1427  false, // IsReceipt
1428  OTRecord::Mail));
1430  str_nym_id, nCurrentMail));
1431  sp_Record->SetContents(strMail.Get());
1432  sp_Record->SetOtherNymID(str_mail_senderID);
1433  sp_Record->SetBoxIndex(nCurrentMail);
1434  sp_Record->SetDateRange(
1437  m_contents.push_back(sp_Record);
1438  }
1439  } // loop through incoming Mail.
1440  // Outmail
1441  //
1442  const int32_t nOutmailCount =
1443  OTAPI_Wrap::GetNym_OutmailCount(str_nym_id);
1444  for (int32_t nCurrentOutmail = 0; nCurrentOutmail < nOutmailCount;
1445  ++nCurrentOutmail) {
1446  otOut << __FUNCTION__ << ": Outmail index: " << nCurrentOutmail
1447  << "\n";
1448  OTMessage* pMsg = pNym->GetOutmailByIndex(nCurrentOutmail);
1449  OT_ASSERT(nullptr != pMsg);
1450  const std::string str_mail_server =
1452  nCurrentOutmail);
1453  const std::string str_mail_recipientID =
1455  nCurrentOutmail);
1456  // str_mail_server is the server for this mail.
1457  // But is that server on our list of servers that we care about?
1458  // Let's see if that server is on m_servers (otherwise we can skip
1459  // it.)
1460  //
1461  auto it_server =
1462  std::find(m_servers.begin(), m_servers.end(), str_mail_server);
1463 
1464  if (it_server != m_servers.end()) // Found the serverID on the list
1465  // of servers we care about.
1466  {
1467  // TODO OPTIMIZE: instead of looking up the Nym's name every
1468  // time, look it
1469  // up ONCE when first adding the NymID. Add it to a map, instead
1470  // of a list,
1471  // and add the Nym's name as the second item in the map's pair.
1472  // (Just like I already did with the asset type.)
1473  //
1474  OTString strName(
1475  m_pLookup->GetNymName(str_mail_recipientID, &(*it_server))),
1476  strNameTemp;
1477  std::string str_name;
1478 
1479  if (strName.Exists())
1480  strNameTemp.Format(OTRecordList::textTo(), strName.Get());
1481  else
1482  strNameTemp.Format(OTRecordList::textTo(),
1483  str_mail_recipientID.c_str());
1484 
1485  str_name = strNameTemp.Get();
1486  const std::string* p_str_asset_type =
1487  &OTRecordList::s_blank; // <========== ASSET TYPE
1488  const std::string* p_str_asset_name =
1489  &OTRecordList::s_blank; // asset type display name.
1490  const std::string* p_str_account =
1491  &OTRecordList::s_blank; // <========== ACCOUNT
1492 
1493  std::string str_amount; // There IS NO amount, on mail. (So we
1494  // leave this empty.)
1495 
1496  uint64_t lDate = pMsg->m_lTime;
1497  OTString strDate;
1498  strDate.Format("%" PRIu64 "", lDate);
1499  const std::string str_date(strDate.Get());
1500  // CREATE A OTRecord AND POPULATE IT...
1501  //
1502  otOut << __FUNCTION__ << ": ADDED: sent mail.\n";
1503 
1504  shared_ptr_OTRecord sp_Record(new OTRecord(
1505  *it_server, *p_str_asset_type, *p_str_asset_name,
1506  str_nym_id, // This is the Nym WHOSE BOX IT IS.
1507  *p_str_account, // This is the Nym's account according to
1508  // the payment instrument, IF that account
1509  // was found on our list of accounts we care
1510  // about. Or it's blank if no account was
1511  // found on the payment instrument.
1512  // Everything above this line, it stores a reference to an
1513  // external string.
1514  // Everything below this line, it makes its own internal
1515  // copy of the string.
1516  str_name, // name of recipient (since its in outgoing mail
1517  // box.)
1518  str_date, // How do we get the date from a mail?
1519  str_amount, OTRecordList::s_message_type, // "message"
1520  false, // bIsPending=false since its already sent.
1521  true, // bIsOutgoing=true. It's OUTGOING mail.
1522  false, // IsRecord (it's not in the record box.)
1523  false, // IsReceipt
1524  OTRecord::Mail));
1525  const OTString strOutmail(
1527  nCurrentOutmail));
1528  sp_Record->SetContents(strOutmail.Get());
1529  sp_Record->SetBoxIndex(nCurrentOutmail);
1530  sp_Record->SetOtherNymID(str_mail_recipientID);
1531  sp_Record->SetDateRange(
1534  m_contents.push_back(sp_Record);
1535  }
1536  } // loop through outgoing Mail.
1537  // For each nym, for each server, loop through its payments inbox and
1538  // record box.
1539  //
1540  int32_t nServerIndex = -1;
1541  for (auto& it_server : m_servers) {
1542  ++nServerIndex;
1543  const OTIdentifier theServerID(it_server);
1544  OTServerContract* pServer = pWallet->GetServerContract(theServerID);
1545  OT_ASSERT(nullptr != pServer);
1546  const OTString strServerID(theServerID);
1547  otOut << __FUNCTION__ << ": Server " << nServerIndex
1548  << ", ID: " << strServerID.Get() << "\n";
1549  // OPTIMIZE FYI:
1550  // The "NoVerify" version is much faster, but you will lose the
1551  // ability to get the
1552  // sender/recipient name from the receipts in the box. The code
1553  // will, however, work
1554  // either way.
1555  //
1556  OTLedger* pInbox =
1557  m_bRunFast
1559  theNymID)
1560  : OTAPI_Wrap::OTAPI()->LoadPaymentInbox(theServerID,
1561  theNymID);
1562  std::unique_ptr<OTLedger> theInboxAngel(pInbox);
1563 
1564  int32_t nIndex = (-1);
1565  // It loaded up, so let's loop through it.
1566  if (nullptr != pInbox) {
1567  for (auto& it : pInbox->GetTransactionMap()) {
1568  OTTransaction* pBoxTrans = it.second;
1569  OT_ASSERT(nullptr != pBoxTrans);
1570  ++nIndex; // 0 on first iteration.
1571  otOut << __FUNCTION__ << ": Incoming payment: " << nIndex
1572  << "\n";
1573  std::string str_name; // name of sender (since its in the
1574  // payments inbox.)
1575  std::string str_sender_nym_id;
1576  std::string str_sender_acct_id;
1577 
1578  if (!pBoxTrans->IsAbbreviated()) {
1579  OTIdentifier theSenderID;
1580 
1581  if (pBoxTrans->GetSenderUserIDForDisplay(theSenderID)) {
1582  const OTString strSenderID(theSenderID);
1583  str_sender_nym_id = strSenderID.Get();
1584 
1585  OTString strName(m_pLookup->GetNymName(
1586  str_sender_nym_id, &it_server)),
1587  strNameTemp;
1588 
1589  if (strName.Exists())
1590  strNameTemp.Format(OTRecordList::textFrom(),
1591  strName.Get());
1592  else
1593  strNameTemp.Format(OTRecordList::textFrom(),
1594  str_sender_nym_id.c_str());
1595 
1596  str_name = strNameTemp.Get();
1597  }
1598 
1599  theSenderID.Release();
1600 
1601  if (pBoxTrans->GetSenderAcctIDForDisplay(theSenderID)) {
1602  const OTString strSenderID(theSenderID);
1603  str_sender_acct_id = strSenderID.Get();
1604  }
1605  }
1606  time64_t tValidFrom = OT_TIME_ZERO, tValidTo = OT_TIME_ZERO;
1607  std::string str_date =
1608  "0"; // the "date signed" on the transaction receipt.
1609  time64_t tDateSigned = pBoxTrans->GetDateSigned();
1610 
1611  if (tDateSigned > OT_TIME_ZERO) {
1612  tValidFrom = tDateSigned;
1613  const uint64_t lDateSigned =
1614  OTTimeGetSecondsFromTime(tDateSigned);
1615  OTString strDateSigned;
1616  strDateSigned.Format("%" PRIu64 "", lDateSigned);
1617  str_date = strDateSigned.Get();
1618  }
1619  const std::string* p_str_asset_type =
1620  &OTRecordList::s_blank; // <========== ASSET TYPE
1621  const std::string* p_str_asset_name =
1622  &OTRecordList::s_blank; // asset type display name.
1623  std::string str_amount; // <========== AMOUNT
1624  std::string str_type; // Instrument type.
1625  std::string str_memo;
1626  OTString strContents; // Instrument contents.
1627 
1628  if (pBoxTrans->IsAbbreviated()) {
1629  str_type =
1630  pBoxTrans->GetTypeString(); // instrumentNotice,
1631  // etc.
1632  int64_t lAmount = pBoxTrans->GetAbbrevDisplayAmount();
1633 
1634  if (0 != lAmount) {
1635  OTString strTemp;
1636  strTemp.Format("%" PRId64 "", lAmount);
1637  str_amount = strTemp.Get();
1638  }
1639  }
1640  else // NOT abbreviated. (Full box receipt is already
1641  // loaded.)
1642  {
1643  OTPayment* pPayment =
1644  GetInstrument(*pNym, nIndex, *pInbox);
1645  // ===> Returns financial instrument by index.
1646  std::unique_ptr<OTPayment> thePaymentAngel(pPayment);
1647  if (nullptr ==
1648  pPayment) // then we treat it like it's abbreviated.
1649  {
1650  str_type =
1651  pBoxTrans->GetTypeString(); // instrumentNotice,
1652  // etc.
1653  int64_t lAmount =
1654  pBoxTrans->GetAbbrevDisplayAmount();
1655 
1656  if (0 == lAmount)
1657  lAmount = pBoxTrans->GetReceiptAmount();
1658  if (0 != lAmount) {
1659  OTString strTemp;
1660  strTemp.Format("%" PRId64 "", lAmount);
1661  str_amount = strTemp.Get();
1662  }
1663  }
1664  // We have pPayment, the instrument accompanying the
1665  // receipt in the payments inbox.
1666  //
1667  else if (pPayment->SetTempValues()) {
1668  pPayment->GetValidFrom(tValidFrom);
1669  pPayment->GetValidTo(tValidTo);
1670 
1671  if (tValidFrom > OT_TIME_ZERO) {
1672  const uint64_t lFrom =
1673  OTTimeGetSecondsFromTime(tValidFrom);
1674  OTString strFrom;
1675  strFrom.Format("%" PRIu64 "", lFrom);
1676  str_date = strFrom.Get();
1677  }
1678  OTString strMemo;
1679  if (pPayment->GetMemo(strMemo)) {
1680  str_memo = strMemo.Get();
1681  }
1682  pPayment->GetPaymentContents(strContents);
1683  OTIdentifier theAssetTypeID, theSenderAcctID;
1684 
1685  if (pPayment->GetAssetTypeID(theAssetTypeID)) {
1686  OTString strTemp(theAssetTypeID);
1687  const std::string str_inpmt_asset(
1688  strTemp.Get()); // The asset type we found
1689  // on the payment (if we
1690  // found anything.)
1691  auto it_asset = m_assets.find(str_inpmt_asset);
1692  if (it_asset != m_assets.end()) // Found it on
1693  // the map of
1694  // asset types
1695  // we care
1696  // about.
1697  {
1698  p_str_asset_type =
1699  &(it_asset->first); // Set the asset
1700  // type ID.
1701  p_str_asset_name =
1702  &(it_asset->second); // The CurrencyTLA.
1703  // Examples: USD,
1704  // BTC, etc.
1705  }
1706  else {
1707  // There was definitely an asset type on the
1708  // instrument, and it definitely
1709  // did not match any of the assets that we
1710  // care about.
1711  // Therefore, skip.
1712  //
1713  otErr << __FUNCTION__
1714  << ": Skipping: Incoming payment (we "
1715  "don't care about asset "
1716  << str_inpmt_asset.c_str() << ")\n";
1717  continue;
1718  }
1719  }
1720  if (str_sender_acct_id.empty() &&
1721  pPayment->GetSenderAcctIDForDisplay(
1722  theSenderAcctID)) {
1723  OTString strTemp(theSenderAcctID);
1724  str_sender_acct_id = strTemp.Get();
1725  }
1726  // By this point, p_str_asset_type and
1727  // p_str_asset_name are definitely set.
1728  OT_ASSERT(nullptr != p_str_asset_type); // and it's
1729  // either
1730  // blank, or
1731  // it's one of
1732  // the asset
1733  // types we
1734  // care about.
1735  OT_ASSERT(nullptr != p_str_asset_name); // and it's
1736  // either
1737  // blank, or
1738  // it's one of
1739  // the asset
1740  // types we
1741  // care about.
1742  // Instrument type (cheque, voucher, etc)
1743  int32_t nType =
1744  static_cast<int32_t>(pPayment->GetType());
1745 
1746  str_type = GetTypeString(nType);
1747  int64_t lAmount = 0;
1748 
1749  if (pPayment->GetAmount(lAmount)) {
1750  OTString strTemp;
1751  strTemp.Format("%" PRId64 "", lAmount);
1752  str_amount = strTemp.Get();
1753  }
1754  }
1755  }
1756  otOut << __FUNCTION__
1757  << ": ADDED: pending incoming payment (str_type: "
1758  << str_type.c_str() << ")\n";
1759 
1760  shared_ptr_OTRecord sp_Record(new OTRecord(
1761  it_server, *p_str_asset_type, *p_str_asset_name,
1762  str_nym_id, // This is the Nym WHOSE BOX IT IS.
1763  OTRecordList::s_blank, // This is the Nym's account for
1764  // this box. (Blank for payments
1765  // inbox.)
1766  // Everything above this line, it stores a reference to
1767  // an external string.
1768  // Everything below this line, it makes its own internal
1769  // copy of the string.
1770  str_name, // name of sender (since its in the inbox.)
1771  str_date, // the "valid from" date on the instrument.
1772  str_amount, str_type, // pending, chequeReceipt, etc.
1773  true, // I believe all incoming "payment inbox" items
1774  // are pending. (Cheques waiting to be cashed,
1775  // smart contracts waiting to be signed, etc.)
1776  false, // bIsOutgoing=false. (Since this is the payment
1777  // INbox, nothing is outgoing...)
1778  false, // bIsRecord
1779  false, // bIsReceipt
1781  if (strContents.Exists())
1782  sp_Record->SetContents(strContents.Get());
1783  sp_Record->SetDateRange(tValidFrom, tValidTo);
1784  sp_Record->SetBoxIndex(nIndex);
1785  if (!str_memo.empty()) sp_Record->SetMemo(str_memo);
1786  if (!str_sender_nym_id.empty())
1787  sp_Record->SetOtherNymID(str_sender_nym_id);
1788  if (!str_sender_acct_id.empty())
1789  sp_Record->SetOtherAccountID(str_sender_acct_id);
1790  sp_Record->SetTransNumForDisplay(
1791  pBoxTrans->GetReferenceNumForDisplay());
1792  sp_Record->SetTransactionNum(
1793  pBoxTrans->GetTransactionNum());
1794 
1795  m_contents.push_back(sp_Record);
1796 
1797  } // looping through inbox.
1798  }
1799  else
1800  otWarn << __FUNCTION__
1801  << ": Failed loading payments inbox. "
1802  "(Probably just doesn't exist yet.)\n";
1803  nIndex = (-1);
1804 
1805  // Also loop through its record box. For this record box, pass the
1806  // USER_ID twice,
1807  // since it's the recordbox for the Nym.
1808  // OPTIMIZE FYI: m_bRunFast impacts run speed here.
1809  OTLedger* pRecordbox =
1810  m_bRunFast
1812  theServerID, theNymID, theNymID)
1813  : // twice.
1814  OTAPI_Wrap::OTAPI()->LoadRecordBox(theServerID, theNymID,
1815  theNymID);
1816  std::unique_ptr<OTLedger> theRecordBoxAngel(pRecordbox);
1817 
1818  // It loaded up, so let's loop through it.
1819  if (nullptr != pRecordbox) {
1820  for (auto& it : pRecordbox->GetTransactionMap()) {
1821  OTTransaction* pBoxTrans = it.second;
1822  OT_ASSERT(nullptr != pBoxTrans);
1823  bool bOutgoing = false;
1824  ++nIndex; // 0 on first iteration.
1825  otOut << __FUNCTION__
1826  << ": Payment RECORD index: " << nIndex << "\n";
1827  std::string str_name; // name of sender OR recipient
1828  // (depending on whether it was
1829  // originally incoming or outgoing.)
1830  std::string str_other_nym_id;
1831  std::string str_other_acct_id;
1832 
1833  if (!pBoxTrans->IsAbbreviated()) {
1834  OTIdentifier theSenderID, theSenderAcctID;
1835  OTIdentifier theRecipientID, theRecipientAcctID;
1836 
1837  if (pBoxTrans->GetSenderUserIDForDisplay(theSenderID)) {
1838  const OTString strSenderID(theSenderID);
1839  const std::string str_sender_id(strSenderID.Get());
1840 
1841  // Usually, Nym is the RECIPIENT. Sometimes he's the
1842  // sender.
1843  // Either way, we want the OTHER ID (the other Nym)
1844  // for display.
1845  // So here, if Nym's CLEARLY the sender, then we
1846  // want the RECIPIENT.
1847  // Whereas if Nym were the recipient, then we'd want
1848  // the SENDER. (For display.)
1849  //
1850  if (0 ==
1851  str_nym_id.compare(str_sender_id)) // str_nym_id
1852  // IS
1853  // str_sender_id.
1854  // (Therefore we want
1855  // recipient.)
1856  {
1857  bOutgoing = true; // if Nym is the sender, then
1858  // it must have been outgoing.
1859 
1860  if (pBoxTrans->GetRecipientUserIDForDisplay(
1861  theRecipientID)) {
1862  const OTString strRecipientID(
1863  theRecipientID);
1864  const std::string str_recipient_id(
1865  strRecipientID.Get());
1866 
1867  OTString strName(m_pLookup->GetNymName(
1868  str_recipient_id, &it_server)),
1869  strNameTemp;
1870 
1871  if (strName.Exists())
1872  strNameTemp.Format(
1874  strName.Get());
1875  else
1876  strNameTemp.Format(
1878  str_recipient_id.c_str());
1879 
1880  str_name = strNameTemp.Get();
1881  str_other_nym_id = str_recipient_id;
1882  if (pBoxTrans->GetRecipientAcctIDForDisplay(
1883  theRecipientAcctID)) {
1884  const OTString strRecipientAcctID(
1885  theRecipientAcctID);
1886  str_other_acct_id =
1887  strRecipientAcctID.Get();
1888  }
1889  }
1890  }
1891  else // str_nym_id IS NOT str_sender_id.
1892  // (Therefore we want sender.)
1893  { // In this case, some OTHER Nym is the sender, so
1894  // it must have been incoming. (And bOutgoing is
1895  // already false.)
1896 
1897  OTString strName(m_pLookup->GetNymName(
1898  str_sender_id, &it_server)),
1899  strNameTemp;
1900 
1901  if (strName.Exists())
1902  strNameTemp.Format(OTRecordList::textFrom(),
1903  strName.Get());
1904  else
1905  strNameTemp.Format(OTRecordList::textFrom(),
1906  str_sender_id.c_str());
1907 
1908  str_name = strNameTemp.Get();
1909  str_other_nym_id = str_sender_id;
1910  if (pBoxTrans->GetSenderAcctIDForDisplay(
1911  theSenderAcctID)) {
1912  const OTString strSenderAcctID(
1913  theSenderAcctID);
1914  str_other_acct_id = strSenderAcctID.Get();
1915  }
1916  }
1917  }
1918  // In this block below, we already KNOW
1919  // GetSenderUserIDForDisplay is EMPTY.
1920  // (So it's "recipient or bust.")
1921  else if (pBoxTrans->GetRecipientUserIDForDisplay(
1922  theRecipientID)) {
1923  const OTString strRecipientID(theRecipientID);
1924  const std::string str_recipient_id(
1925  strRecipientID.Get());
1926 
1927  if (0 !=
1928  str_nym_id.compare(
1929  str_recipient_id)) // str_nym_id is NOT
1930  // str_recipient_id.
1931  // (Therefore we want
1932  // str_recipient_id.)
1933  {
1934  // If Nym is not the recipient, then he must be
1935  // the sender.
1936  // (Therefore it must be outgoing.)
1937  bOutgoing = true;
1938 
1939  OTString strName(m_pLookup->GetNymName(
1940  str_recipient_id, &it_server)),
1941  strNameTemp;
1942 
1943  if (strName.Exists())
1944  strNameTemp.Format(OTRecordList::textTo(),
1945  strName.Get());
1946  else
1947  strNameTemp.Format(
1949  str_recipient_id.c_str());
1950 
1951  str_name = strNameTemp.Get();
1952  str_other_nym_id = str_recipient_id;
1953  if (pBoxTrans->GetRecipientAcctIDForDisplay(
1954  theRecipientAcctID)) {
1955  const OTString strRecipientAcctID(
1956  theRecipientAcctID);
1957  str_other_acct_id =
1958  strRecipientAcctID.Get();
1959  }
1960  }
1961  }
1962  } // if not abbreviated.
1963  time64_t tValidFrom = OT_TIME_ZERO, tValidTo = OT_TIME_ZERO;
1964  std::string str_date =
1965  "0"; // the "date signed" on the transaction receipt.
1966  time64_t tDateSigned = pBoxTrans->GetDateSigned();
1967 
1968  if (tDateSigned > OT_TIME_ZERO) {
1969  tValidFrom = tDateSigned;
1970  const uint64_t lDateSigned =
1971  OTTimeGetSecondsFromTime(tDateSigned);
1972  OTString strDateSigned;
1973  strDateSigned.Format("%" PRIu64 "", lDateSigned);
1974  str_date = strDateSigned.Get();
1975  }
1976  const std::string* p_str_asset_type =
1977  &OTRecordList::s_blank; // <========== ASSET TYPE
1978  const std::string* p_str_asset_name =
1979  &OTRecordList::s_blank; // asset type display name.
1980  const std::string* p_str_account =
1981  &OTRecordList::s_blank; // <========== ACCOUNT
1982  std::string str_amount; // <========== AMOUNT
1983  std::string str_type; // Instrument type.
1984  std::string str_memo; // Instrument memo (if applicable.)
1985  OTString strContents; // Instrument contents.
1986 
1987  if (pBoxTrans->IsAbbreviated()) {
1988  str_type =
1989  pBoxTrans->GetTypeString(); // instrumentNotice,
1990  // etc.
1991  int64_t lAmount = pBoxTrans->GetAbbrevDisplayAmount();
1992 
1993  if (0 != lAmount) {
1994  OTString strTemp;
1995  strTemp.Format("%" PRId64 "", lAmount);
1996  str_amount = strTemp.Get();
1997  }
1998  }
1999  else // NOT abbreviated. (Full box receipt is already
2000  // loaded.)
2001  {
2002  OTPayment* pPayment = GetInstrument(
2003  *pNym, nIndex,
2004  *pRecordbox); // ===> Returns financial instrument
2005  // by index.
2006  std::unique_ptr<OTPayment> thePaymentAngel(pPayment);
2007  if (nullptr ==
2008  pPayment) // then we treat it like it's abbreviated.
2009  {
2010  str_type =
2011  pBoxTrans->GetTypeString(); // instrumentNotice,
2012  // etc.
2013  int64_t lAmount =
2014  pBoxTrans->GetAbbrevDisplayAmount();
2015 
2016  if (0 != lAmount) {
2017  OTString strTemp;
2018  strTemp.Format("%" PRId64 "", lAmount);
2019  str_amount = strTemp.Get();
2020  }
2021  }
2022  // We have pPayment, the instrument accompanying the
2023  // receipt in the payments recordbox.
2024  else if (pPayment->SetTempValues()) {
2025  pPayment->GetValidFrom(tValidFrom);
2026  pPayment->GetValidTo(tValidTo);
2027 
2028  if (tValidFrom > OT_TIME_ZERO) {
2029  const uint64_t lFrom =
2030  OTTimeGetSecondsFromTime(tValidFrom);
2031  OTString strFrom;
2032  strFrom.Format("%" PRIu64 "", lFrom);
2033  str_date = strFrom.Get();
2034  }
2035  pPayment->GetPaymentContents(strContents);
2036  OTIdentifier theAccountID;
2037 
2038  if (bOutgoing) // Nym is sender.
2039  {
2040  if (pPayment->GetSenderAcctIDForDisplay(
2041  theAccountID)) // Since Nym is ME, the
2042  // Account must be MY
2043  // acct.
2044  { // (If this record was originally OUTgoing,
2045  // then the SENDER's account is MY acct.)
2046  OTString strTemp(theAccountID);
2047  std::string str_outpmt_account =
2048  strTemp.Get(); // The accountID we found
2049  // on the payment (only
2050  // applies to outgoing
2051  // payments.)
2052  auto it_acct = std::find(
2053  m_accounts.begin(), m_accounts.end(),
2054  str_outpmt_account);
2055  if (it_acct !=
2056  m_accounts.end()) // Found it on the
2057  // list of accounts we
2058  // care about.
2059  {
2060  p_str_account = &(*it_acct);
2061  }
2062  else {
2063  // There was definitely an account on
2064  // the instrument, and it definitely
2065  // did not match any of the accounts
2066  // that we care about.
2067  // Therefore, skip.
2068  //
2069  otOut << __FUNCTION__
2070  << ": Skipping 'sent payment' "
2071  "record. (We don't care about "
2072  "account "
2073  << str_outpmt_account.c_str()
2074  << ")\n";
2075  continue;
2076  }
2077  }
2078  }
2079  else // Nym is recipient.
2080  {
2081  // Why is this here? Because if Nym is
2082  // recipient, let's say he received an
2083  // instrumentNotice containing
2084  // a sendUserInstrument message containing an
2085  // incoming cheque. Well... that incoming cheque
2086  // (the payload
2087  // on sendUserInstrument message) is ENCRYPTED.
2088  // Meaning the above calls to
2089  // pBoxReceipt->GetSenderAcctID
2090  // on the instrumentNotice transaction will
2091  // FAIL. One option is to pass pNym into
2092  // GetSenderAcctID so it
2093  // can decrypt the payload and return the value.
2094  // But since we already have the payload
2095  // decrypted here
2096  // (we already have the cheque loaded up here)
2097  // we can just grab the senderAcctID directly
2098  // from the cheque.
2099  // That's why this is here -- because this is
2100  // where we KNOW we have the account ID -- so we
2101  // grab it.
2102  //
2103  if (str_other_acct_id.empty() &&
2104  (pPayment->GetSenderAcctIDForDisplay(
2105  theAccountID))) {
2106  OTString strTemp(theAccountID);
2107  str_other_acct_id = strTemp.Get();
2108  }
2109  }
2110  // By this point, p_str_account is definitely set.
2111  OT_ASSERT(nullptr !=
2112  p_str_account); // and it's either
2113  // blank, or it's
2114  // one of the
2115  // accounts we
2116  // care about.
2117  OTIdentifier theAssetTypeID;
2118 
2119  if (pPayment->GetAssetTypeID(theAssetTypeID)) {
2120  OTString strTemp(theAssetTypeID);
2121  const std::string str_inpmt_asset(
2122  strTemp.Get()); // The asset type we found
2123  // on the payment (if we
2124  // found anything.)
2125  auto it_asset = m_assets.find(str_inpmt_asset);
2126  if (it_asset != m_assets.end()) // Found it on
2127  // the map of
2128  // asset types
2129  // we care
2130  // about.
2131  {
2132  p_str_asset_type =
2133  &(it_asset->first); // Set the asset
2134  // type ID.
2135  p_str_asset_name =
2136  &(it_asset->second); // The CurrencyTLA.
2137  // Examples: USD,
2138  // BTC, etc.
2139  }
2140  else {
2141  // There was definitely an asset type on the
2142  // instrument, and it definitely
2143  // did not match any of the assets that we
2144  // care about.
2145  // Therefore, skip.
2146  //
2147  otErr << __FUNCTION__
2148  << ": Skipping: Payment record (we "
2149  "don't care about asset type "
2150  << str_inpmt_asset.c_str() << ")\n";
2151  continue;
2152  }
2153  }
2154  // By this point, p_str_asset_type and
2155  // p_str_asset_name are definitely set.
2156  OT_ASSERT(nullptr != p_str_asset_type); // and it's
2157  // either
2158  // blank, or
2159  // it's one of
2160  // the asset
2161  // types we
2162  // care about.
2163  OT_ASSERT(nullptr != p_str_asset_name); // and it's
2164  // either
2165  // blank, or
2166  // it's one of
2167  // the asset
2168  // types we
2169  // care about.
2170  OTString strMemo;
2171  if (pPayment->GetMemo(strMemo)) {
2172  str_memo = strMemo.Get();
2173  }
2174  // Instrument type (cheque, voucher, etc)
2175  int32_t nType =
2176  static_cast<int32_t>(pPayment->GetType());
2177 
2178  str_type = GetTypeString(nType);
2179  int64_t lAmount = 0;
2180 
2181  if (pPayment->GetAmount(lAmount)) {
2182  OTString strTemp;
2183  strTemp.Format("%" PRId64 "", lAmount);
2184  str_amount = strTemp.Get();
2185  }
2186  }
2187  }
2188  otOut << __FUNCTION__ << ": ADDED: Payment record "
2189  << (bOutgoing ? "(sent)" : "(received)")
2190  << " (str_type: " << str_type.c_str() << ")\n";
2191 
2192  shared_ptr_OTRecord sp_Record(new OTRecord(
2193  it_server, *p_str_asset_type, *p_str_asset_name,
2194  str_nym_id, // This is the Nym WHOSE BOX IT IS.
2195  *p_str_account, // This is the Nym's account for this
2196  // box. (Blank for incoming, set for
2197  // outgoing.)
2198  // Everything above this line, it stores a reference to
2199  // an external string.
2200  // Everything below this line, it makes its own internal
2201  // copy of the string.
2202  str_name, // name of sender or recipient (since its in
2203  // the recordbox.)
2204  str_date, // the "date signed" on the receipt.
2205  str_amount, str_type, // pending, chequeReceipt, etc.
2206  false, // Everything in the recordbox is finished. (NOT
2207  // pending.)
2208  bOutgoing, // Since it's the recordbox, it contains both
2209  // incoming and outgoing receipts.
2210  true, // IsRecord
2211  false, // IsReceipt,
2213  if (strContents.Exists())
2214  sp_Record->SetContents(strContents.Get());
2215  sp_Record->SetDateRange(tValidFrom, tValidTo);
2216  sp_Record->SetBoxIndex(nIndex);
2217  if (!str_memo.empty()) sp_Record->SetMemo(str_memo);
2218  if (!str_other_nym_id.empty())
2219  sp_Record->SetOtherNymID(str_other_nym_id);
2220  if (!str_other_acct_id.empty())
2221  sp_Record->SetOtherAccountID(str_other_acct_id);
2222  sp_Record->SetTransNumForDisplay(
2223  pBoxTrans->GetReferenceNumForDisplay());
2224  sp_Record->SetTransactionNum(
2225  pBoxTrans->GetTransactionNum());
2226 
2227  m_contents.push_back(sp_Record);
2228 
2229  } // Loop through Recordbox
2230  }
2231  else
2232  otWarn << __FUNCTION__
2233  << ": Failed loading payments record box. "
2234  "(Probably just doesn't exist yet.)\n";
2235 
2236  // EXPIRED RECORDS:
2237  nIndex = (-1);
2238 
2239  // Also loop through its expired record box.
2240  // OPTIMIZE FYI: m_bRunFast impacts run speed here.
2241  OTLedger* pExpiredbox =
2242  m_bRunFast
2243  ? OTAPI_Wrap::OTAPI()->LoadExpiredBoxNoVerify(theServerID,
2244  theNymID)
2245  : OTAPI_Wrap::OTAPI()->LoadExpiredBox(theServerID,
2246  theNymID);
2247  std::unique_ptr<OTLedger> theExpiredBoxAngel(pExpiredbox);
2248 
2249  // It loaded up, so let's loop through it.
2250  if (nullptr != pExpiredbox) {
2251  for (auto& it : pExpiredbox->GetTransactionMap()) {
2252  OTTransaction* pBoxTrans = it.second;
2253  OT_ASSERT(nullptr != pBoxTrans);
2254  bool bOutgoing = false;
2255  ++nIndex; // 0 on first iteration.
2256  otOut << __FUNCTION__
2257  << ": Expired payment RECORD index: " << nIndex
2258  << "\n";
2259  std::string str_name; // name of sender OR recipient
2260  // (depending on whether it was
2261  // originally incoming or outgoing.)
2262  std::string str_other_nym_id;
2263  std::string str_other_acct_id;
2264 
2265  if (!pBoxTrans->IsAbbreviated()) {
2266  OTIdentifier theSenderID, theSenderAcctID;
2267  OTIdentifier theRecipientID, theRecipientAcctID;
2268 
2269  if (pBoxTrans->GetSenderUserIDForDisplay(theSenderID)) {
2270  const OTString strSenderID(theSenderID);
2271  const std::string str_sender_id(strSenderID.Get());
2272 
2273  // Usually, Nym is the RECIPIENT. Sometimes he's the
2274  // sender.
2275  // Either way, we want the OTHER ID (the other Nym)
2276  // for display.
2277  // So here, if Nym's CLEARLY the sender, then we
2278  // want the RECIPIENT.
2279  // Whereas if Nym were the recipient, then we'd want
2280  // the SENDER. (For display.)
2281  //
2282  if (0 ==
2283  str_nym_id.compare(str_sender_id)) // str_nym_id
2284  // IS
2285  // str_sender_id.
2286  // (Therefore we want
2287  // recipient.)
2288  {
2289  bOutgoing = true; // if Nym is the sender, then
2290  // it must have been outgoing.
2291 
2292  if (pBoxTrans->GetRecipientUserIDForDisplay(
2293  theRecipientID)) {
2294  const OTString strRecipientID(
2295  theRecipientID);
2296  const std::string str_recipient_id(
2297  strRecipientID.Get());
2298 
2299  OTString strName(m_pLookup->GetNymName(
2300  str_recipient_id, &it_server)),
2301  strNameTemp;
2302 
2303  if (strName.Exists())
2304  strNameTemp.Format(
2306  strName.Get());
2307  else
2308  strNameTemp.Format(
2310  str_recipient_id.c_str());
2311 
2312  str_name = strNameTemp.Get();
2313  str_other_nym_id = str_recipient_id;
2314  if (pBoxTrans->GetRecipientAcctIDForDisplay(
2315  theRecipientAcctID)) {
2316  const OTString strRecipientAcctID(
2317  theRecipientAcctID);
2318  str_other_acct_id =
2319  strRecipientAcctID.Get();
2320  }
2321  }
2322  }
2323  else // str_nym_id IS NOT str_sender_id.
2324  // (Therefore we want sender.)
2325  { // In this case, some OTHER Nym is the sender, so
2326  // it must have been incoming. (And bOutgoing is
2327  // already false.)
2328 
2329  OTString strName(m_pLookup->GetNymName(
2330  str_sender_id, &it_server)),
2331  strNameTemp;
2332 
2333  if (strName.Exists())
2334  strNameTemp.Format(OTRecordList::textFrom(),
2335  strName.Get());
2336  else
2337  strNameTemp.Format(OTRecordList::textFrom(),
2338  str_sender_id.c_str());
2339 
2340  str_name = strNameTemp.Get();
2341  str_other_nym_id = str_sender_id;
2342  if (pBoxTrans->GetSenderAcctIDForDisplay(
2343  theSenderAcctID)) {
2344  const OTString strSenderAcctID(
2345  theSenderAcctID);
2346  str_other_acct_id = strSenderAcctID.Get();
2347  }
2348  }
2349  }
2350  // In this block below, we already KNOW
2351  // GetSenderUserIDForDisplay is EMPTY.
2352  // (So it's "recipient or bust.")
2353  else if (pBoxTrans->GetRecipientUserIDForDisplay(
2354  theRecipientID)) {
2355  const OTString strRecipientID(theRecipientID);
2356  const std::string str_recipient_id(
2357  strRecipientID.Get());
2358 
2359  if (0 !=
2360  str_nym_id.compare(
2361  str_recipient_id)) // str_nym_id is NOT
2362  // str_recipient_id.
2363  // (Therefore we want
2364  // str_recipient_id.)
2365  {
2366  // If Nym is not the recipient, then he must be
2367  // the sender.
2368  // (Therefore it must be outgoing.)
2369  bOutgoing = true;
2370 
2371  OTString strName(m_pLookup->GetNymName(
2372  str_recipient_id, &it_server)),
2373  strNameTemp;
2374 
2375  if (strName.Exists())
2376  strNameTemp.Format(OTRecordList::textTo(),
2377  strName.Get());
2378  else
2379  strNameTemp.Format(
2381  str_recipient_id.c_str());
2382 
2383  str_name = strNameTemp.Get();
2384  str_other_nym_id = str_recipient_id;
2385  if (pBoxTrans->GetRecipientAcctIDForDisplay(
2386  theRecipientAcctID)) {
2387  const OTString strRecipientAcctID(
2388  theRecipientAcctID);
2389  str_other_acct_id =
2390  strRecipientAcctID.Get();
2391  }
2392  }
2393  }
2394  } // if not abbreviated.
2395  time64_t tValidFrom = OT_TIME_ZERO, tValidTo = OT_TIME_ZERO;
2396  std::string str_date =
2397  "0"; // the "date signed" on the transaction receipt.
2398  time64_t tDateSigned = pBoxTrans->GetDateSigned();
2399 
2400  if (tDateSigned > OT_TIME_ZERO) {
2401  tValidFrom = tDateSigned;
2402  const uint64_t lDateSigned =
2403  OTTimeGetSecondsFromTime(tDateSigned);
2404  OTString strDateSigned;
2405  strDateSigned.Format("%" PRIu64 "", lDateSigned);
2406  str_date = strDateSigned.Get();
2407  }
2408  const std::string* p_str_asset_type =
2409  &OTRecordList::s_blank; // <========== ASSET TYPE
2410  const std::string* p_str_asset_name =
2411  &OTRecordList::s_blank; // asset type display name.
2412  const std::string* p_str_account =
2413  &OTRecordList::s_blank; // <========== ACCOUNT
2414  std::string str_amount; // <========== AMOUNT
2415  std::string str_type; // Instrument type.
2416  std::string str_memo; // Instrument memo (if applicable.)
2417  OTString strContents; // Instrument contents.
2418 
2419  if (pBoxTrans->IsAbbreviated()) {
2420  str_type =
2421  pBoxTrans->GetTypeString(); // instrumentNotice,
2422  // etc.
2423  int64_t lAmount = pBoxTrans->GetAbbrevDisplayAmount();
2424 
2425  if (0 != lAmount) {
2426  OTString strTemp;
2427  strTemp.Format("%" PRId64 "", lAmount);
2428  str_amount = strTemp.Get();
2429  }
2430  }
2431  else // NOT abbreviated. (Full box receipt is already
2432  // loaded.)
2433  {
2434  OTPayment* pPayment = GetInstrument(
2435  *pNym, nIndex,
2436  *pExpiredbox); //===> Returns financial instrument
2437  // by index.
2438  std::unique_ptr<OTPayment> thePaymentAngel(pPayment);
2439  if (nullptr ==
2440  pPayment) // then we treat it like it's abbreviated.
2441  {
2442  str_type =
2443  pBoxTrans->GetTypeString(); // instrumentNotice,
2444  // etc.
2445  int64_t lAmount =
2446  pBoxTrans->GetAbbrevDisplayAmount();
2447 
2448  if (0 != lAmount) {
2449  OTString strTemp;
2450  strTemp.Format("%" PRId64 "", lAmount);
2451  str_amount = strTemp.Get();
2452  }
2453  }
2454  // We have pPayment, the instrument accompanying the
2455  // receipt in the payments recordbox.
2456  else if (pPayment->SetTempValues()) {
2457  pPayment->GetValidFrom(tValidFrom);
2458  pPayment->GetValidTo(tValidTo);
2459 
2460  if (tValidFrom > OT_TIME_ZERO) {
2461  const uint64_t lFrom =
2462  OTTimeGetSecondsFromTime(tValidFrom);
2463  OTString strFrom;
2464  strFrom.Format("%" PRIu64 "", lFrom);
2465  str_date = strFrom.Get();
2466  }
2467  pPayment->GetPaymentContents(strContents);
2468  OTIdentifier theAccountID;
2469 
2470  if (bOutgoing) // Nym is sender.
2471  {
2472  if (pPayment->GetSenderAcctIDForDisplay(
2473  theAccountID)) // Since Nym is ME, the
2474  // Account must be MY
2475  // acct.
2476  { // (If this record was originally OUTgoing,
2477  // then the SENDER's account is MY acct.)
2478  OTString strTemp(theAccountID);
2479  std::string str_outpmt_account =
2480  strTemp.Get(); // The accountID we found
2481  // on the payment (only
2482  // applies to outgoing
2483  // payments.)
2484  auto it_acct = std::find(
2485  m_accounts.begin(), m_accounts.end(),
2486  str_outpmt_account);
2487  if (it_acct !=
2488  m_accounts.end()) // Found it on the
2489  // list of accounts we
2490  // care about.
2491  {
2492  p_str_account = &(*it_acct);
2493  }
2494  else {
2495  // There was definitely an account on
2496  // the instrument, and it definitely
2497  // did not match any of the accounts
2498  // that we care about.
2499  // Therefore, skip.
2500  //
2501  otOut
2502  << __FUNCTION__
2503  << ": Skipping 'sent payment' "
2504  "expired record. (We don't care "
2505  "about account "
2506  << str_outpmt_account.c_str()
2507  << ")\n";
2508  continue;
2509  }
2510  }
2511  }
2512  else // Nym is recipient.
2513  {
2514  // Why is this here? Because if Nym is
2515  // recipient, let's say he received an
2516  // instrumentNotice containing
2517  // a sendUserInstrument message containing an
2518  // incoming cheque. Well... that incoming cheque
2519  // (the payload
2520  // on sendUserInstrument message) is ENCRYPTED.
2521  // Meaning the above calls to
2522  // pBoxReceipt->GetSenderAcctID
2523  // on the instrumentNotice transaction will
2524  // FAIL. One option is to pass pNym into
2525  // GetSenderAcctID so it
2526  // can decrypt the payload and return the value.
2527  // But since we already have the payload
2528  // decrypted here
2529  // (we already have the cheque loaded up here)
2530  // we can just grab the senderAcctID directly
2531  // from the cheque.
2532  // That's why this is here -- because this is
2533  // where we KNOW we have the account ID -- so we
2534  // grab it.
2535  //
2536  if (str_other_acct_id.empty() &&
2537  (pPayment->GetSenderAcctIDForDisplay(
2538  theAccountID))) {
2539  OTString strTemp(theAccountID);
2540  str_other_acct_id = strTemp.Get();
2541  }
2542  }
2543  // By this point, p_str_account is definitely set.
2544  OT_ASSERT(nullptr !=
2545  p_str_account); // and it's either
2546  // blank, or it's
2547  // one of the
2548  // accounts we
2549  // care about.
2550  OTIdentifier theAssetTypeID;
2551 
2552  if (pPayment->GetAssetTypeID(theAssetTypeID)) {
2553  OTString strTemp(theAssetTypeID);
2554  const std::string str_inpmt_asset(
2555  strTemp.Get()); // The asset type we found
2556  // on the payment (if we
2557  // found anything.)
2558  auto it_asset = m_assets.find(str_inpmt_asset);
2559  if (it_asset != m_assets.end()) // Found it on
2560  // the map of
2561  // asset types
2562  // we care
2563  // about.
2564  {
2565  p_str_asset_type =
2566  &(it_asset->first); // Set the asset
2567  // type ID.
2568  p_str_asset_name =
2569  &(it_asset->second); // The CurrencyTLA.
2570  // Examples: USD,
2571  // BTC, etc.
2572  }
2573  else {
2574  // There was definitely an asset type on the
2575  // instrument, and it definitely
2576  // did not match any of the assets that we
2577  // care about.
2578  // Therefore, skip.
2579  //
2580  otErr
2581  << __FUNCTION__
2582  << ": Skipping: Expired payment record "
2583  "(we don't care about asset type "
2584  << str_inpmt_asset.c_str() << ")\n";
2585  continue;
2586  }
2587  }
2588  // By this point, p_str_asset_type and
2589  // p_str_asset_name are definitely set.
2590  OT_ASSERT(nullptr != p_str_asset_type); // and it's
2591  // either
2592  // blank, or
2593  // it's one of
2594  // the asset
2595  // types we
2596  // care about.
2597  OT_ASSERT(nullptr != p_str_asset_name); // and it's
2598  // either
2599  // blank, or
2600  // it's one of
2601  // the asset
2602  // types we
2603  // care about.
2604  OTString strMemo;
2605  if (pPayment->GetMemo(strMemo)) {
2606  str_memo = strMemo.Get();
2607  }
2608  // Instrument type (cheque, voucher, etc)
2609  int32_t nType =
2610  static_cast<int32_t>(pPayment->GetType());
2611 
2612  str_type = GetTypeString(nType);
2613  int64_t lAmount = 0;
2614 
2615  if (pPayment->GetAmount(lAmount)) {
2616  OTString strTemp;
2617  strTemp.Format("%" PRId64 "", lAmount);
2618  str_amount = strTemp.Get();
2619  }
2620  }
2621  }
2622  otOut << __FUNCTION__ << ": ADDED: Expired payment record "
2623  << (bOutgoing ? "(sent)" : "(received)")
2624  << " (str_type: " << str_type.c_str() << ")\n";
2625 
2626  shared_ptr_OTRecord sp_Record(new OTRecord(
2627  it_server, *p_str_asset_type, *p_str_asset_name,
2628  str_nym_id, // This is the Nym WHOSE BOX IT IS.
2629  *p_str_account, // This is the Nym's account for this
2630  // box. (Blank for incoming, set for
2631  // outgoing.)
2632  // Everything above this line, it stores a reference to
2633  // an external string.
2634  // Everything below this line, it makes its own internal
2635  // copy of the string.
2636  str_name, // name of sender or recipient (since its in
2637  // the recordbox.)
2638  str_date, // the "date signed" on the receipt.
2639  str_amount, str_type, // pending, chequeReceipt, etc.
2640  false, // Everything in the recordbox is finished. (NOT
2641  // pending.)
2642  bOutgoing, // Since it's the recordbox, it contains both
2643  // incoming and outgoing receipts.
2644  true, // IsRecord
2645  false, // IsReceipt,
2647  if (strContents.Exists())
2648  sp_Record->SetContents(strContents.Get());
2649  sp_Record->SetDateRange(tValidFrom, tValidTo);
2650  sp_Record->SetExpired();
2651  sp_Record->SetBoxIndex(nIndex);
2652  if (!str_memo.empty()) sp_Record->SetMemo(str_memo);
2653  if (!str_other_nym_id.empty())
2654  sp_Record->SetOtherNymID(str_other_nym_id);
2655  if (!str_other_acct_id.empty())
2656  sp_Record->SetOtherAccountID(str_other_acct_id);
2657  sp_Record->SetTransNumForDisplay(
2658  pBoxTrans->GetReferenceNumForDisplay());
2659  sp_Record->SetTransactionNum(
2660  pBoxTrans->GetTransactionNum());
2661 
2662  m_contents.push_back(sp_Record);
2663 
2664  } // Loop through ExpiredBox
2665  }
2666  else
2667  otWarn << __FUNCTION__
2668  << ": Failed loading expired payments box. "
2669  "(Probably just doesn't exist yet.)\n";
2670 
2671  } // Loop through servers for each Nym.
2672  } // Loop through Nyms.
2673  // ASSET ACCOUNT -- INBOX/OUTBOX + RECORD BOX
2674  // Loop through the Accounts.
2675  //
2676  otOut << "================ " << __FUNCTION__
2677  << ": Looping through the accounts in the wallet...\n";
2678  int32_t nAccountIndex = -1;
2679  for (auto& it_acct : m_accounts) {
2680  ++nAccountIndex; // (0 on first iteration.)
2681  // For each account, loop through its inbox, outbox, and record box.
2682  //
2683  const std::string& str_account_id(it_acct);
2684  const OTIdentifier theAccountID(str_account_id);
2685  OTAccount* pAccount = pWallet->GetAccount(theAccountID);
2686  OT_ASSERT(nullptr != pAccount);
2687  const OTIdentifier& theNymID = pAccount->GetUserID();
2688  const OTIdentifier& theServerID = pAccount->GetPurportedServerID();
2689  const OTIdentifier& theAssetID = pAccount->GetAssetTypeID();
2690  const OTString strNymID(theNymID);
2691  const OTString strServerID(theServerID);
2692  const OTString strAssetID(theAssetID);
2693  otOut << "------------\n" << __FUNCTION__
2694  << ": Account: " << nAccountIndex
2695  << ", ID: " << str_account_id.c_str() << "\n";
2696  const std::string str_nym_id(strNymID.Get());
2697  const std::string str_server_id(strServerID.Get());
2698  const std::string str_asset_id(strAssetID.Get());
2699  const std::string* pstr_nym_id = &OTRecordList::s_blank;
2700  const std::string* pstr_server_id = &OTRecordList::s_blank;
2701  const std::string* pstr_asset_id = &OTRecordList::s_blank;
2702  const std::string* pstr_asset_name = &OTRecordList::s_blank;
2703  // NOTE: Since this account is already on my "care about" list for
2704  // accounts,
2705  // I wouldn't bother double-checking my "care about" lists for servers,
2706  // nyms,
2707  // and asset types. But I still look up the appropriate string for each,
2708  // since
2709  // I have to pass a reference to it into the constructor for OTRecord.
2710  // (To a version
2711  // that won't be deleted, since the OTRecord will reference it. And the
2712  // "care about"
2713  // list definitely contains a copy of the string that won't be deleted.)
2714  //
2715  auto it_nym = std::find(m_nyms.begin(), m_nyms.end(), str_nym_id);
2716  auto it_server =
2717  std::find(m_servers.begin(), m_servers.end(), str_server_id);
2718  auto it_asset = m_assets.find(str_asset_id);
2719  if ((m_nyms.end() == it_nym) || (m_servers.end() == it_server) ||
2720  (m_assets.end() == it_asset)) {
2721  otOut << __FUNCTION__ << ": Skipping an account ("
2722  << str_account_id.c_str()
2723  << ") since its Nym, or Server, "
2724  "or Asset Type wasn't on my list.\n";
2725  continue;
2726  }
2727  // These pointers are what we'll use to construct each OTRecord.
2728  //
2729  pstr_nym_id = &(*it_nym);
2730  pstr_server_id = &(*it_server);
2731  pstr_asset_id = &(it_asset->first);
2732  pstr_asset_name = &(it_asset->second);
2733  // Loop through asset account INBOX.
2734  //
2735  // OPTIMIZE FYI:
2736  // NOTE: LoadInbox is much SLOWER than LoadInboxNoVerify, but it also
2737  // lets you get
2738  // the NAME off of the box receipt. So if you are willing to GIVE UP the
2739  // NAME, in
2740  // return for FASTER PERFORMANCE, then call SetFastMode() before
2741  // Populating.
2742  //
2743  OTLedger* pInbox = m_bRunFast
2745  theServerID, theNymID, theAccountID)
2747  theServerID, theNymID, theAccountID);
2748  std::unique_ptr<OTLedger> theInboxAngel(pInbox);
2749 
2750  // It loaded up, so let's loop through it.
2751  if (nullptr != pInbox) {
2752  int32_t nInboxIndex = -1;
2753  for (auto& it : pInbox->GetTransactionMap()) {
2754  ++nInboxIndex; // (0 on first iteration.)
2755  if (0 == nInboxIndex)
2756  otOut
2757  << __FUNCTION__
2758  << ": Beginning loop through asset account INBOX...\n";
2759  OTTransaction* pBoxTrans = it.second;
2760  OT_ASSERT(nullptr != pBoxTrans);
2761  otOut << __FUNCTION__ << ": Inbox index: " << nInboxIndex
2762  << "\n";
2763  bool bCanceled = false;
2764  std::string str_name; // name of sender (since its in the
2765  // inbox.)
2766  std::string str_other_nym_id;
2767  std::string str_other_acct_id;
2768  std::string str_memo;
2769 
2770  if (!pBoxTrans->IsAbbreviated()) {
2771  OTString strMemo;
2772 
2773  if (pBoxTrans->GetMemo(strMemo)) str_memo = strMemo.Get();
2774  if (OTTransaction::pending == pBoxTrans->GetType()) {
2775  // NOTE: REMOVE THE BELOW CODE. (Found a better way,
2776  // above this block.)
2777  // const OTString
2778  // strBoxTrans(*pBoxTrans);
2779  //
2780  // if (strBoxTrans.Exists())
2781  // str_memo =
2782  // OTAPI_Wrap::Pending_GetNote(*pstr_server_id,
2783  // *pstr_nym_id, str_account_id, strBoxTrans.Get());
2784  OTIdentifier theSenderID, theSenderAcctID;
2785 
2786  if (pBoxTrans->GetSenderAcctIDForDisplay(
2787  theSenderAcctID)) // ACCOUNT name.
2788  {
2789  if (pBoxTrans->GetSenderUserIDForDisplay(
2790  theSenderID)) {
2791  const OTString strSenderID(theSenderID);
2792  str_other_nym_id = strSenderID.Get();
2793  }
2794  const OTString strSenderAcctID(theSenderAcctID);
2795  const std::string str_sender_acct_id(
2796  strSenderAcctID.Get());
2797 
2798  str_other_acct_id = str_sender_acct_id;
2799 
2800  OTString strName(m_pLookup->GetAcctName(
2801  str_other_acct_id,
2802  str_other_nym_id.empty()
2803  ? nullptr
2804  : &str_other_nym_id, // nym ID if known
2805  pstr_server_id, // server ID if known.
2806  pstr_asset_id)), // asset ID if known.
2807  strNameTemp;
2808 
2809  if (strName.Exists()) {
2810  strNameTemp.Format(OTRecordList::textFrom(),
2811  strName.Get());
2812  str_name = strNameTemp.Get();
2813  }
2814  else if (!str_other_nym_id.empty()) {
2815  OTString strNymName(m_pLookup->GetNymName(
2816  str_other_nym_id, &(*it_server))),
2817  strNymNameTemp;
2818 
2819  if (strNymName.Exists()) {
2820  strNymNameTemp.Format(
2822  strNymName.Get());
2823  str_name = strNameTemp.Get();
2824  }
2825  }
2826  if (str_name.empty()) {
2827  strNameTemp.Format(OTRecordList::textFrom(),
2828  str_sender_acct_id.c_str());
2829  str_name = strNameTemp.Get();
2830  }
2831  }
2832  else if (pBoxTrans->GetSenderUserIDForDisplay(
2833  theSenderID)) // NYM name.
2834  {
2835  const OTString strSenderID(theSenderID);
2836  const std::string str_sender_id(strSenderID.Get());
2837 
2838  OTString strName(m_pLookup->GetNymName(
2839  str_sender_id, &(*it_server))),
2840  strNameTemp;
2841 
2842  if (strName.Exists())
2843  strNameTemp.Format(OTRecordList::textFrom(),
2844  strName.Get());
2845  else
2846  strNameTemp.Format(OTRecordList::textFrom(),
2847  str_sender_id.c_str());
2848 
2849  str_name = strNameTemp.Get();
2850  str_other_nym_id = str_sender_id;
2851  }
2852  else {
2854  str_account_id)),
2855  strNameTemp;
2856 
2857  if (strName.Exists())
2858  strNameTemp = strName;
2859  else
2860  strNameTemp = str_account_id;
2861 
2862  str_name = strNameTemp.Get();
2863  }
2864  } // end: (if pending)
2865  else // else it's a receipt.
2866  {
2867  OTIdentifier theRecipientID, theRecipientAcctID;
2868 
2869  if (pBoxTrans->GetRecipientUserIDForDisplay(
2870  theRecipientID)) {
2871  const OTString strRecipientID(theRecipientID);
2872  const std::string str_recipient_user_id(
2873  strRecipientID.Get());
2874 
2875  OTString strName(m_pLookup->GetNymName(
2876  str_recipient_user_id, &(*it_server))),
2877  strNameTemp;
2878 
2879  if (strName.Exists())
2880  strNameTemp.Format(OTRecordList::textTo(),
2881  strName.Get());
2882  else
2883  strNameTemp.Format(
2885  str_recipient_user_id.c_str());
2886 
2887  str_name = strNameTemp.Get();
2888  str_other_nym_id = str_recipient_user_id;
2889  if (pBoxTrans->GetRecipientAcctIDForDisplay(
2890  theRecipientAcctID)) {
2891  const OTString strRecipientAcctID(
2892  theRecipientAcctID);
2893  str_other_acct_id = strRecipientAcctID.Get();
2894  }
2895  }
2896  else if (pBoxTrans->GetRecipientAcctIDForDisplay(
2897  theRecipientAcctID)) {
2898  const OTString strRecipientAcctID(
2899  theRecipientAcctID);
2900  const std::string str_recipient_acct_id(
2901  strRecipientAcctID.Get());
2902 
2903  OTString strName(m_pLookup->GetAcctName(
2904  str_recipient_acct_id,
2905  nullptr, // nym ID if known
2906  pstr_server_id, // server ID if known.
2907  pstr_asset_id)), // asset ID if known.
2908  strNameTemp;
2909 
2910  if (strName.Exists())
2911  strNameTemp.Format(OTRecordList::textTo(),
2912  strName.Get());
2913  else
2914  strNameTemp.Format(
2916  str_recipient_acct_id.c_str());
2917 
2918  str_name = strNameTemp.Get();
2919  str_other_acct_id = str_recipient_acct_id;
2920  }
2921  } // end: (else it's a receipt.)
2922  }
2923  bCanceled = pBoxTrans->IsCancelled();
2924  time64_t tValidFrom = OT_TIME_ZERO, tValidTo = OT_TIME_ZERO;
2925  std::string str_date =
2926  "0"; // the "date signed" on the transaction receipt.
2927  time64_t tDateSigned = pBoxTrans->GetDateSigned();
2928 
2929  if (tDateSigned > OT_TIME_ZERO) {
2930  tValidFrom = tDateSigned;
2931  const uint64_t lDateSigned =
2932  OTTimeGetSecondsFromTime(tDateSigned);
2933  OTString strDateSigned;
2934  strDateSigned.Format("%" PRIu64 "", lDateSigned);
2935  str_date = strDateSigned.Get();
2936  }
2937  std::string str_amount; // <========== AMOUNT
2938  int64_t lAmount = pBoxTrans->GetAbbrevDisplayAmount();
2939 
2940  if (0 == lAmount) lAmount = pBoxTrans->GetReceiptAmount();
2941  if (0 != lAmount) {
2942  OTString strTemp;
2943  strTemp.Format("%" PRId64 "", lAmount);
2944  str_amount = strTemp.Get();
2945  }
2946  const std::string str_type(
2947  pBoxTrans->GetTypeString()); // pending, chequeReceipt, etc.
2948  otOut << __FUNCTION__ << ": ADDED: incoming "
2949  << ((OTTransaction::pending == pBoxTrans->GetType())
2950  ? "pending transfer"
2951  : "receipt") << " (str_type: " << str_type.c_str()
2952  << ")\n";
2953 
2954  shared_ptr_OTRecord sp_Record(new OTRecord(
2955  *pstr_server_id, *pstr_asset_id, *pstr_asset_name,
2956  *pstr_nym_id, // This is the Nym WHOSE BOX IT IS.
2957  str_account_id, // This is the Nym's account for this box.
2958  // Everything above this line, it stores a reference to an
2959  // external string.
2960  // Everything below this line, it makes its own internal
2961  // copy of the string.
2962  str_name, // name of sender (since its in the inbox.)
2963  str_date, // the "valid from" date on the instrument.
2964  str_amount, str_type, // pending, chequeReceipt, etc.
2965  (OTTransaction::pending ==
2966  pBoxTrans->GetType()), // Sometimes true, often false.
2967  (lAmount < 0) ? true : false, // bIsOutgoing (this is the
2968  // inbox, but a
2969  // transferReceipt in the inbox represents
2970  // outgoing funds. Whereas a "pending" in the
2971  // inbox represents incoming funds. For now I'm
2972  // just going to go based on whether the amount
2973  // is negative or not, to determine incoming /
2974  // outgoing. We'll see how that works.)
2975  false, // IsRecord
2976  (OTTransaction::pending !=
2977  pBoxTrans->GetType()), // IsReceipt,
2978  (OTTransaction::pending == pBoxTrans->GetType())
2980  : OTRecord::Receipt));
2981  const OTString strContents(*pBoxTrans);
2982  sp_Record->SetContents(strContents.Get());
2983  sp_Record->SetDateRange(tValidFrom, tValidTo);
2984  sp_Record->SetBoxIndex(nInboxIndex);
2985  if (bCanceled) sp_Record->SetCanceled();
2986  if (!str_memo.empty()) sp_Record->SetMemo(str_memo);
2987  if (!str_other_nym_id.empty())
2988  sp_Record->SetOtherNymID(str_other_nym_id);
2989  if (!str_other_acct_id.empty())
2990  sp_Record->SetOtherAccountID(str_other_acct_id);
2991  sp_Record->SetTransNumForDisplay(
2992  pBoxTrans->GetReferenceNumForDisplay());
2993  sp_Record->SetTransactionNum(pBoxTrans->GetTransactionNum());
2994  m_contents.push_back(sp_Record);
2995  }
2996  }
2997  // OPTIMIZE FYI:
2998  // NOTE: LoadOutbox is much SLOWER than LoadOutboxNoVerify, but it also
2999  // lets you get
3000  // the NAME off of the box receipt. So if you are willing to GIVE UP the
3001  // NAME, in
3002  // return for FASTER PERFORMANCE, then call SetFastMode() before running
3003  // Populate.
3004  //
3005  OTLedger* pOutbox = m_bRunFast
3007  theServerID, theNymID, theAccountID)
3009  theServerID, theNymID, theAccountID);
3010  std::unique_ptr<OTLedger> theOutboxAngel(pOutbox);
3011 
3012  // It loaded up, so let's loop through it.
3013  if (nullptr != pOutbox) {
3014  int32_t nOutboxIndex = -1;
3015  for (auto& it : pOutbox->GetTransactionMap()) {
3016  ++nOutboxIndex; // (0 on first iteration.)
3017  if (0 == nOutboxIndex)
3018  otOut
3019  << __FUNCTION__
3020  << ": Beginning loop through asset account OUTBOX...\n";
3021  OTTransaction* pBoxTrans = it.second;
3022  OT_ASSERT(nullptr != pBoxTrans);
3023  otOut << __FUNCTION__ << ": Outbox index: " << nOutboxIndex
3024  << "\n";
3025  std::string str_name; // name of recipient (since its in the
3026  // outbox.)
3027  std::string str_other_nym_id;
3028  std::string str_other_acct_id;
3029  std::string str_memo;
3030 
3031  if (!pBoxTrans->IsAbbreviated()) {
3032  OTIdentifier theRecipientID, theRecipientAcctID;
3033 
3034  if (pBoxTrans->GetRecipientUserIDForDisplay(
3035  theRecipientID)) {
3036  const OTString strRecipientID(theRecipientID);
3037  const std::string str_recipient_id(
3038  strRecipientID.Get());
3039 
3040  OTString strName(m_pLookup->GetNymName(str_recipient_id,
3041  &(*it_server))),
3042  strNameTemp;
3043 
3044  if (strName.Exists())
3045  strNameTemp.Format(OTRecordList::textTo(),
3046  strName.Get());
3047  else
3048  strNameTemp.Format(OTRecordList::textTo(),
3049  str_recipient_id.c_str());
3050 
3051  str_name = strNameTemp.Get();
3052  str_other_nym_id = str_recipient_id;
3053  if (pBoxTrans->GetRecipientAcctIDForDisplay(
3054  theRecipientAcctID)) {
3055  const OTString strRecipientAcctID(
3056  theRecipientAcctID);
3057  str_other_acct_id = strRecipientAcctID.Get();
3058  }
3059  }
3060  else if (pBoxTrans->GetRecipientAcctIDForDisplay(
3061  theRecipientAcctID)) {
3062  const OTString strRecipientAcctID(theRecipientAcctID);
3063  const std::string str_recipient_acct_id(
3064  strRecipientAcctID.Get());
3065 
3066  OTString strName(m_pLookup->GetAcctName(
3067  str_recipient_acct_id, nullptr, // nym ID if known
3068  pstr_server_id, // server ID if known.
3069  pstr_asset_id)), // asset ID if known.
3070  strNameTemp;
3071 
3072  if (strName.Exists())
3073  strNameTemp.Format(OTRecordList::textTo(),
3074  strName.Get());
3075  else
3076  strNameTemp.Format(OTRecordList::textTo(),
3077  str_recipient_acct_id.c_str());
3078 
3079  str_name = strNameTemp.Get();
3080  str_other_acct_id = str_recipient_acct_id;
3081  }
3082  if (OTTransaction::pending == pBoxTrans->GetType()) {
3083  OTString strMemo;
3084 
3085  if (pBoxTrans->GetMemo(strMemo))
3086  str_memo = strMemo.Get();
3087 
3088  // DELETE THE BELOW CODE (replaced by above code.)
3089  // const OTString
3090  // strBoxTrans(*pBoxTrans);
3091  //
3092  // if (strBoxTrans.Exists())
3093  // str_memo =
3094  // OTAPI_Wrap::Pending_GetNote(*pstr_server_id,
3095  // *pstr_nym_id, str_account_id, strBoxTrans.Get());
3096  }
3097  }
3098  time64_t tValidFrom = OT_TIME_ZERO, tValidTo = OT_TIME_ZERO;
3099  std::string str_date =
3100  "0"; // the "date signed" on the transaction receipt.
3101  time64_t tDateSigned = pBoxTrans->GetDateSigned();
3102 
3103  if (tDateSigned > OT_TIME_ZERO) {
3104  tValidFrom = tDateSigned;
3105  const uint64_t lDateSigned =
3106  OTTimeGetSecondsFromTime(tDateSigned);
3107  OTString strDateSigned;
3108  strDateSigned.Format("%" PRIu64 "", lDateSigned);
3109  str_date = strDateSigned.Get();
3110  }
3111  std::string str_amount; // <========== AMOUNT
3112  int64_t lAmount = pBoxTrans->GetAbbrevDisplayAmount();
3113 
3114  if (0 == lAmount) lAmount = pBoxTrans->GetReceiptAmount();
3115  if (lAmount >
3116  0) // Outgoing transfer should display with negative amount
3117  lAmount *= (-1);
3118  if (0 != lAmount) {
3119  OTString strTemp;
3120  strTemp.Format("%" PRId64 "", lAmount);
3121  str_amount = strTemp.Get();
3122  }
3123  std::string str_type(
3124  pBoxTrans->GetTypeString()); // pending, chequeReceipt, etc.
3125  if (0 == str_type.compare("pending")) str_type = "transfer";
3126  otOut << __FUNCTION__ << ": ADDED: "
3127  << ((OTTransaction::pending == pBoxTrans->GetType())
3128  ? "pending"
3129  : "ERROR")
3130  << " outgoing transfer (str_type: " << str_type.c_str()
3131  << ").\n";
3132 
3133  shared_ptr_OTRecord sp_Record(new OTRecord(
3134  *pstr_server_id, *pstr_asset_id, *pstr_asset_name,
3135  *pstr_nym_id, // This is the Nym WHOSE BOX IT IS.
3136  str_account_id, // This is the Nym's account for this box.
3137  // Everything above this line, it stores a reference to an
3138  // external string.
3139  // Everything below this line, it makes its own internal
3140  // copy of the string.
3141  str_name, // name of recipient (since its in the outbox.)
3142  str_date, // the "valid from" date on the instrument.
3143  str_amount, str_type, // pending, chequeReceipt, etc.
3144  (OTTransaction::pending ==
3145  pBoxTrans->GetType()), // Basically always true, in this
3146  // case.
3147  true, // bIsOutgoing=true. (Since this is the outbox...)
3148  false, // IsRecord
3149  false, // IsReceipt
3151  const OTString strContents(*pBoxTrans);
3152  sp_Record->SetContents(strContents.Get());
3153  sp_Record->SetDateRange(tValidFrom, tValidTo);
3154  sp_Record->SetBoxIndex(nOutboxIndex);
3155  if (!str_memo.empty()) sp_Record->SetMemo(str_memo);
3156  if (!str_other_nym_id.empty())
3157  sp_Record->SetOtherNymID(str_other_nym_id);
3158  if (!str_other_acct_id.empty())
3159  sp_Record->SetOtherAccountID(str_other_acct_id);
3160  sp_Record->SetTransNumForDisplay(
3161  pBoxTrans->GetReferenceNumForDisplay());
3162  sp_Record->SetTransactionNum(pBoxTrans->GetTransactionNum());
3163  m_contents.push_back(sp_Record);
3164  }
3165  }
3166  // For this record box, pass a NymID AND an AcctID,
3167  // since it's the recordbox for a specific account.
3168  //
3169  // OPTIMIZE FYI:
3170  // NOTE: LoadRecordBox is much SLOWER than LoadRecordBoxNoVerify, but it
3171  // also lets you get
3172  // the NAME off of the box receipt. So if you are willing to GIVE UP the
3173  // NAME, in
3174  // return for FASTER PERFORMANCE, then call SetFastMode() before
3175  // Populating.
3176  //
3177  OTLedger* pRecordbox = m_bRunFast
3179  theServerID, theNymID, theAccountID)
3181  theServerID, theNymID, theAccountID);
3182  std::unique_ptr<OTLedger> theRecordBoxAngel(pRecordbox);
3183 
3184  // It loaded up, so let's loop through it.
3185  if (nullptr != pRecordbox) {
3186  int32_t nRecordIndex = -1;
3187  for (auto& it : pRecordbox->GetTransactionMap()) {
3188  ++nRecordIndex;
3189  OTTransaction* pBoxTrans = it.second;
3190  OT_ASSERT(nullptr != pBoxTrans);
3191  otOut << __FUNCTION__
3192  << ": Account RECORD index: " << nRecordIndex << "\n";
3193  bool bOutgoing = false;
3194  bool bCanceled = false;
3195  std::string str_name; // name of sender OR recipient (depending
3196  // on whether it was originally incoming
3197  // or outgoing.)
3198  std::string str_other_nym_id;
3199  std::string str_other_acct_id;
3200  std::string str_memo;
3201 
3202  if (!pBoxTrans->IsAbbreviated()) {
3203  OTIdentifier theSenderID, theSenderAcctID;
3204  OTIdentifier theRecipientID, theRecipientAcctID;
3205 
3206  if (pBoxTrans->GetSenderAcctIDForDisplay(theSenderAcctID)) {
3207  const OTString strSenderAcctID(theSenderAcctID);
3208  const std::string str_sender_acct_id(
3209  strSenderAcctID.Get());
3210 
3211  // Usually, Nym is the RECIPIENT. Sometimes he's the
3212  // sender.
3213  // Either way, we want the OTHER ID (the other Nym) for
3214  // display.
3215  // So here, if Nym's CLEARLY the sender, then we want
3216  // the RECIPIENT.
3217  // Whereas if Nym were the recipient, then we'd want the
3218  // SENDER. (For display.)
3219  //
3220  if (0 ==
3221  str_account_id.compare(
3222  str_sender_acct_id)) // str_account_id IS
3223  // str_sender_acct_id.
3224  // (Therefore we want
3225  // recipient.)
3226  {
3227  bOutgoing = true; // if Nym is the sender, then it
3228  // must have been outgoing.
3229 
3230  const bool bGotRecipientUserIDForDisplay =
3231  pBoxTrans->GetRecipientUserIDForDisplay(
3232  theRecipientID);
3233 
3234  if (pBoxTrans->GetRecipientAcctIDForDisplay(
3235  theRecipientAcctID)) {
3236  const OTString strRecipientAcctID(
3237  theRecipientAcctID);
3238  const std::string str_recip_acct_id(
3239  strRecipientAcctID.Get());
3240 
3241  OTString strRecipientUserID("");
3242  std::string str_recip_user_id("");
3243 
3244  if (bGotRecipientUserIDForDisplay) {
3245  theRecipientID.GetString(
3246  strRecipientUserID);
3247  str_recip_user_id =
3248  strRecipientUserID.Get();
3249  }
3250  // NOTE: We check for cancelled here so we don't
3251  // accidentally
3252  // cause the address book to falsely believe
3253  // that str_recip_user_id
3254  // is the owner of str_recip_acct_id. (If the
3255  // cheque/invoice is cancelled,
3256  // the recipient account will be the sender
3257  // account, which is NOT owned
3258  // by the recipient, obviously...)
3259  //
3260  if (!pBoxTrans->IsCancelled()) {
3261  OTString strName(m_pLookup->GetAcctName(
3262  str_recip_acct_id,
3263  // NOTE: we CANNOT pass
3264  // str_recip_user_id here with
3265  // str_recip_acct_id
3266  // if it's a cancelled instrument, since
3267  // in that case, the SENDER ACCT
3268  // is ALSO the RECIPIENT ACCT. So this
3269  // logic is ONLY correct since we
3270  // are inside the block of if
3271  // (!pBoxTrans->IsCancelled())
3272  // (Otherwise we'd be training the
3273  // address book to falsely believe that
3274  // the recipient Nym is the owner of the
3275  // sender acct.)
3276  bGotRecipientUserIDForDisplay
3277  ? &str_recip_user_id
3278  : nullptr, // nym ID if known
3279  pstr_server_id, // server ID if known.
3280  pstr_asset_id)), // asset ID if known.
3281  strNameTemp;
3282 
3283  if (strName.Exists())
3284  strNameTemp.Format(
3286  strName.Get());
3287  else
3288  strNameTemp.Format(
3290  str_recip_acct_id.c_str());
3291 
3292  str_name =
3293  strNameTemp.Get(); // We don't want to
3294  // see our own name
3295  // on cancelled
3296  // cheques.
3297  }
3298  str_other_acct_id = str_recip_acct_id;
3299  }
3300  if (bGotRecipientUserIDForDisplay) {
3301  const OTString strRecipientID(theRecipientID);
3302  const std::string str_recipient_id(
3303  strRecipientID.Get());
3304 
3305  str_other_nym_id = str_recipient_id;
3306 
3307  if (str_name.empty()) {
3308  OTString strName(m_pLookup->GetNymName(
3309  str_recipient_id, &(*it_server))),
3310  strNameTemp;
3311 
3312  if (strName.Exists())
3313  strNameTemp.Format(
3315  strName.Get());
3316  else
3317  strNameTemp.Format(
3319  str_recipient_id.c_str());
3320 
3321  str_name = strNameTemp.Get();
3322  }
3323  }
3324  }
3325  else // str_account_id IS NOT str_sender_acct_id.
3326  // (Therefore we want sender.)
3327  { // In this case, some OTHER Nym is the sender, so it
3328  // must have been incoming. (And bOutgoing is
3329  // already
3330  // false.)
3331 
3332  if (pBoxTrans->GetSenderUserIDForDisplay(
3333  theSenderID)) {
3334  const OTString strSenderUserID(theSenderID);
3335  str_other_nym_id = strSenderUserID.Get();
3336  }
3337  OTString strName(m_pLookup->GetAcctName(
3338  str_sender_acct_id,
3339  str_other_nym_id.empty()
3340  ? nullptr
3341  : &str_other_nym_id, // nym ID if known
3342  pstr_server_id, // server ID if known.
3343  pstr_asset_id)), // asset ID if known.
3344  strNameTemp;
3345 
3346  if (strName.Exists())
3347  strNameTemp.Format(OTRecordList::textFrom(),
3348  strName.Get());
3349  else
3350  strNameTemp.Format(OTRecordList::textFrom(),
3351  str_sender_acct_id.c_str());
3352 
3353  str_name = strNameTemp.Get();
3354  str_other_acct_id = str_sender_acct_id;
3355  }
3356  }
3357  // In this block below, we already KNOW
3358  // GetSenderAcctIDForDisplay is EMPTY.
3359  // (So it's "recipient or bust.")
3360  else if (pBoxTrans->GetRecipientAcctIDForDisplay(
3361  theRecipientAcctID)) {
3362  if (pBoxTrans->GetRecipientUserIDForDisplay(
3363  theRecipientID)) {
3364  const OTString strRecipientID(theRecipientID);
3365  const std::string str_recipient_user_id(
3366  strRecipientID.Get());
3367 
3368  str_other_nym_id = str_recipient_user_id;
3369  }
3370  const OTString strRecipientAcctID(theRecipientAcctID);
3371  const std::string str_recipient_acct_id(
3372  strRecipientAcctID.Get());
3373 
3374  if (0 !=
3375  str_account_id.compare(
3376  str_recipient_acct_id)) // str_account_id is NOT
3377  // str_recipient_acct_id.
3378  // (Therefore we want
3379  // str_recipient_acct_id.)
3380  {
3381  // If Nym is not the recipient, then he must be the
3382  // sender.
3383  // (Therefore it must be outgoing.)
3384  bOutgoing = true;
3385 
3386  OTString strName(m_pLookup->GetAcctName(
3387  str_recipient_acct_id,
3388  str_other_nym_id.empty()
3389  ? nullptr
3390  : &str_other_nym_id, // nym ID if known
3391  pstr_server_id, // server ID if known.
3392  pstr_asset_id)), // asset ID if known.
3393  strNameTemp;
3394 
3395  if (strName.Exists())
3396  strNameTemp.Format(OTRecordList::textTo(),
3397  strName.Get());
3398  else
3399  strNameTemp.Format(
3401  str_recipient_acct_id.c_str());
3402 
3403  str_name = strNameTemp.Get();
3404  str_other_acct_id = str_recipient_acct_id;
3405  }
3406  }
3407  else if (pBoxTrans->GetSenderUserIDForDisplay(
3408  theSenderID)) {
3409  const OTString strSenderID(theSenderID);
3410  const std::string str_sender_id(strSenderID.Get());
3411 
3412  // Usually, Nym is the RECIPIENT. Sometimes he's the
3413  // sender.
3414  // Either way, we want the OTHER ID (the other Nym) for
3415  // display.
3416  // So here, if Nym's CLEARLY the sender, then we want
3417  // the RECIPIENT.
3418  // Whereas if Nym were the recipient, then we'd want the
3419  // SENDER. (For display.)
3420  //
3421  if (0 ==
3422  str_nym_id.compare(str_sender_id)) // str_nym_id IS
3423  // str_sender_id.
3424  // (Therefore we
3425  // want
3426  // recipient.)
3427  {
3428  bOutgoing = true; // if Nym is the sender, then it
3429  // must have been outgoing.
3430 
3431  if (pBoxTrans->GetRecipientUserIDForDisplay(
3432  theRecipientID)) {
3433  const OTString strRecipientID(theRecipientID);
3434  const std::string str_recipient_id(
3435  strRecipientID.Get());
3436 
3437  OTString strName(m_pLookup->GetNymName(
3438  str_recipient_id, &(*it_server))),
3439  strNameTemp;
3440 
3441  if (strName.Exists())
3442  strNameTemp.Format(OTRecordList::textTo(),
3443  strName.Get());
3444  else
3445  strNameTemp.Format(
3447  str_recipient_id.c_str());
3448 
3449  str_name = strNameTemp.Get();
3450  str_other_nym_id = str_recipient_id;
3451  if (pBoxTrans->GetRecipientAcctIDForDisplay(
3452  theRecipientAcctID)) {
3453  const OTString strRecipientAcctID(
3454  theRecipientAcctID);
3455  str_other_acct_id =
3456  strRecipientAcctID.Get();
3457  }
3458  }
3459  }
3460  else // str_nym_id IS NOT str_sender_id. (Therefore we
3461  // want sender.)
3462  { // In this case, some OTHER Nym is the sender, so it
3463  // must have been incoming. (And bOutgoing is
3464  // already
3465  // false.)
3466 
3467  OTString strName(m_pLookup->GetNymName(
3468  str_sender_id, &(*it_server))),
3469  strNameTemp;
3470 
3471  if (strName.Exists())
3472  strNameTemp.Format(OTRecordList::textFrom(),
3473  strName.Get());
3474  else
3475  strNameTemp.Format(OTRecordList::textFrom(),
3476  str_sender_id.c_str());
3477 
3478  str_name = strNameTemp.Get();
3479  str_other_nym_id = str_sender_id;
3480  if (pBoxTrans->GetSenderAcctIDForDisplay(
3481  theSenderAcctID)) {
3482  const OTString strSenderAcctID(theSenderAcctID);
3483  str_other_acct_id = strSenderAcctID.Get();
3484  }
3485  }
3486  }
3487  // In this block below, we already KNOW
3488  // GetSenderUserIDForDisplay is EMPTY.
3489  // (So it's "recipient or bust.")
3490  else if (pBoxTrans->GetRecipientUserIDForDisplay(
3491  theRecipientID)) {
3492  const OTString strRecipientID(theRecipientID);
3493  const std::string str_recipient_id(
3494  strRecipientID.Get());
3495 
3496  if (0 !=
3497  str_nym_id.compare(str_recipient_id)) // str_nym_id
3498  // is NOT
3499  // str_recipient_id.
3500  // (Therefore we want
3501  // str_recipient_id.)
3502  {
3503  // If Nym is not the recipient, then he must be the
3504  // sender.
3505  // (Therefore it must be outgoing.)
3506  bOutgoing = true;
3507 
3508  OTString strName(m_pLookup->GetNymName(
3509  str_recipient_id, &(*it_server))),
3510  strNameTemp;
3511 
3512  if (strName.Exists())
3513  strNameTemp.Format(OTRecordList::textTo(),
3514  strName.Get());
3515  else
3516  strNameTemp.Format(OTRecordList::textTo(),
3517  str_recipient_id.c_str());
3518 
3519  str_name = strNameTemp.Get();
3520  str_other_nym_id = str_recipient_id;
3521  if (pBoxTrans->GetRecipientAcctIDForDisplay(
3522  theRecipientAcctID)) {
3523  const OTString strRecipientAcctID(
3524  theRecipientAcctID);
3525  str_other_acct_id = strRecipientAcctID.Get();
3526  }
3527  }
3528  }
3529  // Get the Memo field for a transferReceipt and also for
3530  // other receipts.
3531  //
3532  OTString strMemo;
3533 
3534  if (pBoxTrans->GetMemo(strMemo)) str_memo = strMemo.Get();
3535 
3536  } // if not abbreviated.
3537  bCanceled = pBoxTrans->IsCancelled();
3538  time64_t tValidFrom = OT_TIME_ZERO, tValidTo = OT_TIME_ZERO;
3539  std::string str_date =
3540  "0"; // the "date signed" on the transaction receipt.
3541  time64_t tDateSigned = pBoxTrans->GetDateSigned();
3542 
3543  if (tDateSigned > OT_TIME_ZERO) {
3544  tValidFrom = tDateSigned;
3545  const uint64_t lDateSigned =
3546  OTTimeGetSecondsFromTime(tDateSigned);
3547  OTString strDateSigned;
3548  strDateSigned.Format("%" PRIu64 "", lDateSigned);
3549  str_date = strDateSigned.Get();
3550  }
3551  std::string str_amount; // <========== AMOUNT
3552  int64_t lAmount = pBoxTrans->GetAbbrevDisplayAmount();
3553 
3554  if (0 == lAmount) lAmount = pBoxTrans->GetReceiptAmount();
3555  const std::string str_type(
3556  pBoxTrans->GetTypeString()); // pending, chequeReceipt, etc.
3557  if (0 == str_type.compare("transferReceipt"))
3558  bOutgoing = true; // only the sender of a transfer will have
3559  // a transferReceipt.
3560  else if (0 == str_type.compare("pending"))
3561  bOutgoing = false; // only the recipient of a transfer will
3562  // have a pending in his recordbox.
3563  if (0 != lAmount) {
3564 
3565  // if (lAmount < 0)
3566  // bOutgoing = true;
3567  // else
3568  // bOutgoing = false;
3569 
3570  // A transfer receipt ALWAYS represents an outgoing
3571  // transfer.
3572  // If the amount is over 0, we want to display it as a
3573  // negative
3574  // since it represents money LEAVING my account.
3575  // if ((0 ==
3576  // str_type.compare("transferReceipt")) && (lAmount > 0))
3577  // lAmount *= (-1);
3578 
3579  OTString strTemp;
3580  strTemp.Format("%" PRId64 "", lAmount);
3581  str_amount = strTemp.Get();
3582  }
3583  otOut << __FUNCTION__ << ": ADDED: "
3584  << ((pBoxTrans->GetType() != OTTransaction::pending)
3585  ? ""
3586  : (bOutgoing ? "sent" : "received"))
3587  << " (asset account) record (str_type: "
3588  << str_type.c_str() << ")\n";
3589  // This line means: If it's a receipt, use a blank string.
3590  // Otherwise if
3591  // it's a transfer, then show sent/received. (This is the
3592  // record box, so
3593  // if it's a transfer, it's a completed one.)
3594  //
3595  // FYI, for Receipts we don't say "sent transferReceipt",
3596  // we just say "transferReceipt."
3597 
3598  shared_ptr_OTRecord sp_Record(new OTRecord(
3599  *pstr_server_id, *pstr_asset_id, *pstr_asset_name,
3600  *pstr_nym_id, // This is the Nym WHOSE BOX IT IS.
3601  str_account_id, // This is the Nym's account for this box.
3602  // Everything above this line, it stores a reference to an
3603  // external string.
3604  // Everything below this line, it makes its own internal
3605  // copy of the string.
3606  str_name, // name of sender or recipient (whichever is NOT
3607  // the current Nym.)
3608  str_date, // the "valid from" date on the instrument.
3609  str_amount, str_type, // pending, chequeReceipt, etc.
3610  false, // bPending=false. If it's in the record box, then
3611  // it's finished (not pending.)
3612  bOutgoing, // Record box stores both old incoming, AND old
3613  // outgoing, receipts.
3614  true, // IsRecord
3615  pBoxTrans->GetType() != OTTransaction::pending, // IsReceipt
3616  pBoxTrans->GetType() == OTTransaction::pending
3618  : OTRecord::Receipt));
3619  const OTString strContents(*pBoxTrans);
3620  sp_Record->SetContents(strContents.Get());
3621  if (bCanceled) sp_Record->SetCanceled();
3622  sp_Record->SetDateRange(tValidFrom, tValidTo);
3623  sp_Record->SetBoxIndex(nRecordIndex);
3624  if (!str_memo.empty()) sp_Record->SetMemo(str_memo);
3625  if (!str_other_nym_id.empty())
3626  sp_Record->SetOtherNymID(str_other_nym_id);
3627  if (!str_other_acct_id.empty())
3628  sp_Record->SetOtherAccountID(str_other_acct_id);
3629  sp_Record->SetTransNumForDisplay(
3630  pBoxTrans->GetReferenceNumForDisplay());
3631  sp_Record->SetTransactionNum(pBoxTrans->GetTransactionNum());
3632  m_contents.push_back(sp_Record);
3633  }
3634  }
3635 
3636  } // loop through the accounts.
3637  // SORT the vector.
3638  //
3639  SortRecords();
3640  return true;
3641 }
3642 
3644 {
3645  return m_nyms;
3646 }
3647 
3648 // Populate already sorts. But if you have to add some external records
3649 // after Populate, then you can sort again.
3650 //
3652 {
3653  // TODO OPTIMIZE: We might load everything up into a multimap, and THEN copy
3654  // it
3655  // directly over to the vector. (Since the multimap sorts automatically on
3656  // insert.)
3657  // The question is, would doing that be any faster than just sorting it
3658  // here?
3659  // (Possibly not, but I'm not sure. Re-visit later.)
3660  //
3661  std::sort(m_contents.begin(), m_contents.end(),
3662  compare_records); // Todo optimize: any faster sorting algorithms?
3663 }
3664 
3665 // Let's say you also want to add some Bitmessages. (Or any other external
3666 // source.) This is where you do that. Make sure to call Populate, then use
3667 // AddSpecialMsg a few times, then call SortRecords.
3668 //
3670  const std::string& str_msg_id, // The id of this message, from whatever
3671  // system it came from.
3672  bool bIsOutgoing, int32_t nMethodID,
3673  const std::string& str_contents, // Make sure to concatentate subject with
3674  // contents, before passing here.
3675  const std::string& str_address, const std::string& str_other_address,
3676  const std::string& str_type, const std::string& str_type_display,
3677  std::string str_my_nym_id, time64_t tDate)
3678 {
3679  const char* pToFrom =
3680  bIsOutgoing ? OTRecordList::textTo() : OTRecordList::textFrom();
3681  const std::string* p_str_server =
3682  &OTRecordList::s_blank; // <========== Bitmessage doesn't use OT
3683  // servers.
3684  // TODO OPTIMIZE: instead of looking up the Nym's name every time, look it
3685  // up ONCE when first adding the NymID. Add it to a map, instead of a list,
3686  // and add the Nym's name as the second item in the map's pair.
3687  // (Just like I already did with the asset type.)
3688  //
3689  std::string str_other_name;
3690 
3691  if (!str_other_address.empty())
3692  str_other_name = m_pLookup->GetAddressName(str_other_address);
3693  OTString strNameTemp;
3694  std::string str_name("");
3695 
3696  if (!str_other_name.empty())
3697  strNameTemp.Format(pToFrom, str_other_name.c_str());
3698  else if (!str_other_address.empty())
3699  strNameTemp.Format(pToFrom, str_other_address.c_str());
3700 
3701  str_name = strNameTemp.Get();
3702  const std::string* p_str_nym_id =
3703  &OTRecordList::s_blank; // <========== MY NYM ID
3704  const std::string* p_str_asset_type =
3705  &OTRecordList::s_blank; // <========== ASSET TYPE
3706  const std::string* p_str_asset_name =
3707  &OTRecordList::s_blank; // asset type display name.
3708  const std::string* p_str_account =
3709  &OTRecordList::s_blank; // <========== ACCOUNT
3710 
3711  std::string str_amount; // There IS NO amount, on mail. (So we leave this
3712  // empty.)
3713  // ---------------------------------------------------
3714  uint64_t lDate = static_cast<uint64_t>(tDate);
3715  OTString strDate;
3716  strDate.Format("%" PRIu64 "", lDate);
3717  const std::string str_date(strDate.Get());
3718  // CREATE AN OTRecord AND POPULATE IT...
3719  //
3720  // This loop is here because normally an OTRecord's "nym id" is
3721  // a reference to a string found in OTRecordList's list of Nyms.
3722  // We can't just stick a Nym ID in there, we have to find the
3723  // specific Nym ID string in the OTRecordList and use THAT, otherwise
3724  // we'd end up with bad pointer problems.
3725  //
3726  if (!str_my_nym_id.empty()) {
3727  for (auto& it_nym : m_nyms) {
3728  const std::string& str_nym_id(it_nym);
3729 
3730  if (0 == str_my_nym_id.compare(str_nym_id)) {
3731  p_str_nym_id = &str_nym_id;
3732  break;
3733  }
3734  }
3735  }
3736  shared_ptr_OTRecord sp_Record(new OTRecord(
3737  *p_str_server, *p_str_asset_type, *p_str_asset_name,
3738  *p_str_nym_id, // This is "me" (the sender Nym, if outgoing, or
3739  // recipient, if incoming.)
3740  *p_str_account, // No OT asset account on any mail, much less on a
3741  // "bitmessage" mail.
3742  // Everything above this line, it stores a reference to an external
3743  // string.
3744  // Everything below this line, it makes its own internal copy of the
3745  // string.
3746  str_name, // name of sender for incoming, otherwise name of recipient
3747  // for outgoing.
3748  str_date, str_amount, OTRecordList::s_message_type, // "message"
3749  false, // bIsPending=false since its already received.
3750  bIsOutgoing, false, // IsRecord
3751  false, // IsReceipt
3752  OTRecord::Mail));
3753  sp_Record->SetSpecialMail(); // true by default. This means it's not an OT
3754  // message, but a Bitmessage (or something like
3755  // that.)
3756  sp_Record->SetContents(str_contents.c_str()); // "Subject: %s\n[Contents]"
3757  sp_Record->SetMsgID(str_msg_id);
3758  sp_Record->SetDateRange(OTTimeGetTimeFromSeconds(tDate),
3759  OTTimeGetTimeFromSeconds(tDate));
3760  sp_Record->SetMethodID(nMethodID);
3761  sp_Record->SetAddress(str_address);
3762  sp_Record->SetOtherAddress(str_other_address);
3763  sp_Record->SetMsgType(str_type);
3764  sp_Record->SetMsgTypeDisplay(str_type_display);
3765  otWarn << __FUNCTION__
3766  << ": ADDED: " << (bIsOutgoing ? "outgoing" : "incoming")
3767  << " special mail.\n";
3768 
3769  m_contents.push_back(sp_Record);
3770 }
3771 
3772 // This one expects that s_pCaller is not nullptr.
3773 //
3775  : m_pLookup(nullptr)
3776  , m_bRunFast(false)
3777  , m_bAutoAcceptCheques(false)
3778  , m_bAutoAcceptReceipts(false)
3779  , m_bAutoAcceptTransfers(false)
3780  , m_bAutoAcceptCash(false)
3781 {
3782  OT_ASSERT_MSG((nullptr != s_pCaller),
3783  "Address Book Caller was nullptr! "
3784  "On app startup, did you forget to call "
3785  "OT_API_Set_AddrBookCallback ?\n");
3787  "Address Book Callback was nullptr! "
3788  "On app startup, did you forget to call "
3789  "OT_API_Set_AddrBookCallback ?\n");
3790  m_pLookup = s_pCaller->getCallback(); // <==========
3791 }
3792 
3794  : m_pLookup(&theLookup)
3795  , m_bRunFast(false)
3796  , m_bAutoAcceptCheques(false)
3797  , m_bAutoAcceptReceipts(false)
3798  , m_bAutoAcceptTransfers(false)
3799  , m_bAutoAcceptCash(false)
3800 {
3801 }
3802 
3804 {
3805  // if (nullptr != m_pLookup) // NO DELETE! We assume whatever client app is
3806  // using OTRecordList, will
3807  // delete m_pLookup; // delete its own address book lookup class when
3808  // it is good and ready.
3809 
3810  m_pLookup = nullptr;
3811 }
3812 
3813 // Clears m_contents (NOT nyms, accounts, servers, or asset types.)
3814 
3816 {
3817  m_contents.clear();
3818 }
3819 
3820 // RETRIEVE:
3821 //
3822 
3823 int32_t OTRecordList::size() const
3824 {
3825  return m_contents.size();
3826 }
3827 
3828 bool OTRecordList::RemoveRecord(int32_t nIndex)
3829 {
3830  OT_ASSERT((nIndex >= 0) &&
3831  (nIndex < static_cast<int32_t>(m_contents.size())));
3832  m_contents.erase(m_contents.begin() + nIndex);
3833  return true;
3834 }
3835 
3837 {
3838  OT_ASSERT((nIndex >= 0) &&
3839  (nIndex < static_cast<int32_t>(m_contents.size())));
3840  weak_ptr_OTRecord wp_record(m_contents[nIndex]);
3841  shared_ptr_OTRecord sp_record(wp_record);
3842 
3843  return sp_record;
3844 }
3845 
3846 } // namespace opentxs
static EXPORT std::string GetAccountWallet_Name(const std::string &ACCOUNT_ID)
Definition: OTAPI.cpp:924
EXPORT bool GetAmount(int64_t &lOutput) const
Definition: OTPayment.cpp:502
EXPORT bool DoesAcceptReceiptsAutomatically() const
virtual EXPORT ~OTNameLookup()
bool compare_records(shared_ptr_OTRecord i, shared_ptr_OTRecord j)
EXPORT bool GetSenderAcctIDForDisplay(OTIdentifier &theReturnID)
EXPORT bool GetValidFrom(time64_t &tOutput) const
Definition: OTPayment.cpp:867
EXPORT void SetServerID(std::string str_id)
EXPORT OTLedger * LoadRecordBox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID) const
static OTLookupCaller * s_pCaller
static bool setAddrBookCaller(OTLookupCaller &theCaller)
EXPORT OTLedger * LoadInbox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID) const
EXPORT const OTIdentifier & GetAssetTypeID() const
Definition: OTAccount.cpp:449
EXPORT void AddSpecialMsg(const std::string &str_msg_id, bool bIsOutgoing, int32_t nMethodID, const std::string &str_contents, const std::string &str_address, const std::string &str_other_address, const std::string &str_type, const std::string &str_type_display, std::string str_my_nym_id="", time64_t tDate=OT_TIME_ZERO)
EXPORT bool RemoveRecord(int32_t nIndex)
EXPORT OTAssetContract * GetAssetContract(const OTIdentifier &theContractID)
Definition: OTWallet.cpp:1203
EXPORT char const * GetTypeString() const
Definition: OTAccount.hpp:271
EXPORT std::string Ledger_FinalizeResponse(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_LEDGER) const
EXPORT std::string Transaction_CreateResponse(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &RESPONSE_LEDGER, const std::string &ORIGINAL_TRANSACTION, const bool &BOOL_DO_I_ACCEPT) const
static EXPORT std::string GetNym_OutmailContentsByIndex(const std::string &NYM_ID, const int32_t &nIndex)
Definition: OTAPI.cpp:728
std::weak_ptr< OTRecord > weak_ptr_OTRecord
EXPORT bool GetRecipientAcctIDForDisplay(OTIdentifier &theReturnID)
std::list< std::string > list_of_strings
EXPORT void AddAssetID(std::string str_id)
EXPORT std::string GetAddressName(const std::string &str_address) const
static EXPORT OTAPI_Exec * It()
Definition: OTAPI.cpp:174
EXPORT const OTString & GetCurrencyTLA() const
EXPORT OTWallet * GetWallet(const char *szFuncName=nullptr) const
OTLOG_IMPORT OTLogStream otOut
EXPORT OTLedger * LoadOutbox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID) const
OTLOG_IMPORT OTLogStream otLog3
EXPORT bool GetSenderUserIDForDisplay(OTIdentifier &theReturnID)
EXPORT bool GetAccount(int32_t iIndex, OTIdentifier &THE_ID, OTString &THE_NAME)
Definition: OTWallet.cpp:431
EXPORT void SetNymID(std::string str_id)
static EXPORT std::string GetNym_MailContentsByIndex(const std::string &NYM_ID, const int32_t &nIndex)
Definition: OTAPI.cpp:693
std::map< int32_t, OTPayment * > mapOfPayments
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
Definition: Common.hpp:215
EXPORT bool GetAssetTypeID(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:963
EXPORT OTLedger * LoadPaymentInbox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
int64_t time64_t
Definition: Common.hpp:209
EXPORT bool GetOpeningNum(int64_t &lOutput, const OTIdentifier &theNymID) const
Definition: OTPayment.cpp:744
EXPORT int32_t InterpretTransactionMsgReply(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &str_Attempt, const std::string &str_Response) const
Definition: OT_ME.cpp:1051
virtual EXPORT std::string GetAcctName(const std::string &str_id, const std::string *p_nym_id=nullptr, const std::string *p_server_id=nullptr, const std::string *p_asset_id=nullptr) const
static EXPORT std::string GetNym_OutmailRecipientIDByIndex(const std::string &NYM_ID, const int32_t &nIndex)
Definition: OTAPI.cpp:734
EXPORT bool Exists() const
Definition: OTString.cpp:1035
const char * GetTypeString() const
EXPORT OTLedger * LoadPaymentInboxNoVerify(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
static EXPORT int32_t GetNym_OutpaymentsCount(const std::string &NYM_ID)
Definition: OTAPI.cpp:758
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
EXPORT bool DoesAcceptCashAutomatically() const
EXPORT const OTString & GetCurrencySymbol() const
#define MC_UI_TEXT_FROM
EXPORT void ClearAssets()
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
EXPORT bool GetMemo(OTString &strMemo)
EXPORT bool DoesAcceptChequesAutomatically() const
EXPORT void ClearContents()
const OTIdentifier & GetPurportedServerID() const
EXPORT void SetAssetID(std::string str_id)
virtual EXPORT std::string GetAddressName(const std::string &str_address) const
EXPORT bool GetPaymentContents(OTString &strOutput) const
Definition: OTPayment.hpp:323
EXPORT void AcceptReceiptsAutomatically(bool bVal=true)
EXPORT bool GetMemo(OTString &strOutput) const
Definition: OTPayment.cpp:468
EXPORT const list_of_strings & GetNyms() const
static EXPORT std::string GetNym_MailServerIDByIndex(const std::string &NYM_ID, const int32_t &nIndex)
Definition: OTAPI.cpp:705
static EXPORT std::string GetNym_Name(const std::string &NYM_ID)
Definition: OTAPI.cpp:648
EXPORT OTPseudonym * GetNymByID(const OTIdentifier &NYM_ID)
Definition: OTWallet.cpp:275
EXPORT void setCallback(OTNameLookup *cb)
EXPORT bool make_sure_enough_trans_nums(int32_t nNumberNeeded, const std::string &SERVER_ID, const std::string &NYM_ID) const
Definition: OT_ME.cpp:382
static EXPORT std::string GetNym_OutpaymentsRecipientIDByIndex(const std::string &NYM_ID, const int32_t &nIndex)
Definition: OTAPI.cpp:769
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT OTMessage * GetOutmailByIndex(int32_t nIndex) const
EXPORT void SetAccountID(std::string str_id)
static EXPORT std::string GetNym_MailSenderIDByIndex(const std::string &NYM_ID, const int32_t &nIndex)
Definition: OTAPI.cpp:699
EXPORT void ClearServers()
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
#define MC_UI_TEXT_TO
virtual EXPORT std::string GetNymName(const std::string &str_id, const std::string *p_server_id=nullptr) const
OTPayment * GetInstrument(const OTPseudonym &theNym, const int32_t &nIndex, OTLedger &ledger)
Definition: Helpers.cpp:149
EXPORT void AcceptTransfersAutomatically(bool bVal=true)
EXPORT void AddServerID(std::string str_id)
EXPORT void ClearNyms()
EXPORT std::shared_ptr< OTRecord > GetRecord(int32_t nIndex)
EXPORT void ClearAccounts()
time64_t GetDateSigned() const
EXPORT bool SetTempValues()
Definition: OTPayment.cpp:196
static EXPORT int32_t GetNym_OutmailCount(const std::string &NYM_ID)
Definition: OTAPI.cpp:723
static EXPORT std::string GetNym_OutpaymentsServerIDByIndex(const std::string &NYM_ID, const int32_t &nIndex)
Definition: OTAPI.cpp:775
OTLOG_IMPORT OTLogStream otWarn
EXPORT int64_t GetReferenceNumForDisplay()
int64_t GetAbbrevDisplayAmount() const
EXPORT const char * Get() const
Definition: OTString.cpp:1045
EXPORT OTNameLookup * getCallback()
transactionType GetType() const
EXPORT std::string GetNymName(const std::string &str_id, const std::string *p_server_id=nullptr) const
EXPORT bool GetSenderAcctIDForDisplay(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:1080
OTNameLookup * _callback
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
EXPORT std::string Ledger_CreateResponse(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &ORIGINAL_LEDGER) const
Creates a new &#39;response&#39; ledger, set up with the right Server ID, etc,.
EXPORT bool GetValidTo(time64_t &tOutput) const
Definition: OTPayment.cpp:894
EXPORT OTLedger * LoadExpiredBox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT void AcceptChequesAutomatically(bool bVal=true)
static EXPORT const char * textFrom()
EXPORT bool IsValid() const
Definition: OTPayment.hpp:301
bool IsAbbreviated() const
EXPORT OTLedger * LoadRecordBoxNoVerify(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID) const
EXPORT bool retrieve_account(const std::string &SERVER_ID, const std::string &NYM_ID, const std::string &ACCOUNT_ID, bool bForceDownload=false) const
Definition: OT_ME.cpp:485
EXPORT void AddAccountID(std::string str_id)
static EXPORT std::string GetNym_OutmailServerIDByIndex(const std::string &NYM_ID, const int32_t &nIndex)
Definition: OTAPI.cpp:740
EXPORT void GetString(OTString &theStr) const
EXPORT std::string GetAcctName(const std::string &str_id, const std::string *p_nym_id=nullptr, const std::string *p_server_id=nullptr, const std::string *p_asset_id=nullptr) const
std::shared_ptr< OTRecord > shared_ptr_OTRecord
EXPORT void AcceptCashAutomatically(bool bVal=true)
static EXPORT OT_API * OTAPI()
Definition: OTAPI.cpp:244
EXPORT int32_t size() const
EXPORT OTLedger * LoadExpiredBoxNoVerify(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
const OTIdentifier & GetUserID() const
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
static EXPORT std::string GetNym_OutpaymentsContentsByIndex(const std::string &NYM_ID, const int32_t &nIndex)
Definition: OTAPI.cpp:763
EXPORT bool DoesAcceptTransfersAutomatically() const
#define OT_TIME_ZERO
Definition: Common.hpp:180
virtual EXPORT void Release()
Definition: OTData.cpp:257
EXPORT OTServerContract * GetServerContract(const OTIdentifier &SERVER_ID)
Definition: OTWallet.cpp:667
EXPORT paymentType GetType() const
Definition: OTPayment.hpp:306
EXPORT OTLedger * LoadInboxNoVerify(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID) const
static EXPORT int32_t GetNym_MailCount(const std::string &NYM_ID)
Definition: OTAPI.cpp:688
EXPORT OTLedger * LoadOutboxNoVerify(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID) const
static OTLookupCaller * getAddrBookCaller()
static EXPORT const char * textTo()
EXPORT bool PerformAutoAccept()
static EXPORT std::string GetAssetType_Name(const std::string &ASSET_TYPE_ID)
Definition: OTAPI.cpp:909
EXPORT bool isCallbackSet() const
EXPORT bool OT_API_Set_AddrBookCallback(OTLookupCaller &theCaller)
EXPORT OTMessage * GetMailByIndex(int32_t nIndex) const
EXPORT void AddNymID(std::string str_id)
EXPORT void SortRecords()
EXPORT std::string process_inbox(const std::string &SERVER_ID, const std::string &NYM_ID, const std::string &ACCOUNT_ID, const std::string &RESPONSE_LEDGER) const
Definition: OT_ME.cpp:514
EXPORT bool GetRecipientUserIDForDisplay(OTIdentifier &theReturnID)
EXPORT const OTString & GetCurrencyName() const
EXPORT const mapOfTransactions & GetTransactionMap() const
Definition: OTLedger.cpp:1160