Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTAPI_Exec.cpp
Go to the documentation of this file.
1 /************************************************************
2 *
3 * OTAPI_Exec.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 "OTAPI_Exec.hpp"
136 #include "OpenTransactions.hpp"
137 #include "OTWallet.hpp"
138 #include "TransportCallback.hpp"
139 #include "Helpers.hpp"
140 
141 #include "../ext/OTPayment.hpp"
142 
143 #include "../cash/Mint.hpp"
144 #include "../cash/Purse.hpp"
145 #include "../cash/Token.hpp"
146 
147 #include "../basket/Basket.hpp"
148 
149 #include "../core/recurring/OTPaymentPlan.hpp"
150 #include "../core/OTAccount.hpp"
151 #include "../core/script/OTAgent.hpp"
152 #include "../core/OTAssetContract.hpp"
153 #include "../core/crypto/OTAsymmetricKey.hpp"
154 #include "../core/script/OTBylaw.hpp"
155 #include "../core/OTCheque.hpp"
156 #include "../core/script/OTClause.hpp"
157 #include "../core/crypto/OTCredential.hpp"
158 #include "../core/crypto/OTEnvelope.hpp"
159 #include "../core/OTLedger.hpp"
160 #include "../core/OTLog.hpp"
161 #include "../core/OTMessage.hpp"
162 #include "../core/script/OTParty.hpp"
163 #include "../core/script/OTPartyAccount.hpp"
164 #include "../core/crypto/OTPasswordData.hpp"
165 #include "../core/util/OTPaths.hpp"
166 #include "../core/OTPseudonym.hpp"
167 #include "../core/OTServerContract.hpp"
168 #include "../core/crypto/OTSymmetricKey.hpp"
169 
170 #include <memory>
171 
172 namespace opentxs
173 {
174 
175 #ifndef OT_BOOL
176 #define OT_BOOL int32_t
177 #endif
178 
179 #ifndef OT_FALSE
180 const int32_t OT_FALSE = 0;
181 #endif
182 
183 #ifndef OT_TRUE
184 const int32_t OT_TRUE = 1;
185 #endif
186 
187 #ifndef OT_ERROR
188 const int32_t OT_ERROR = (-1);
189 #endif
190 
191 bool OTAPI_Exec::bInitOTApp = false;
192 bool OTAPI_Exec::bCleanupOTApp = false;
193 
195  : p_OTAPI(nullptr)
196 {
197 }
198 
200 {
201 }
202 
203 bool OTAPI_Exec::AppInit() // Call this ONLY ONCE, when your App first starts
204  // up.
205 {
207  if (!OTAPI_Exec::bInitOTApp) {
208  OTAPI_Exec::bInitOTApp = true;
209  if (OT_API::InitOTApp()) {
210  OT_API* tmpOTAPI = new OT_API();
211  if (nullptr != tmpOTAPI) {
212  if (tmpOTAPI->IsInitialized()) {
213  if (tmpOTAPI->SetTransportCallback(
214  new TransportCallback(*tmpOTAPI))) {
215  p_OTAPI = tmpOTAPI; // success
216  return true;
217  }
218  }
219  delete tmpOTAPI;
220  tmpOTAPI = nullptr;
221  }
222  }
223  }
224  }
225  return false;
226 }
227 
228 bool OTAPI_Exec::AppCleanup() // Call this ONLY ONCE, when your App is shutting
229  // down.
230 {
231  if (!OTAPI_Exec::bCleanupOTApp) // if we haven't cleaned up already
232  {
233  if (OTAPI_Exec::bInitOTApp) // and have had a ctx.
234  {
235  // will cleanup everything.
236  if (nullptr != p_OTAPI) delete p_OTAPI;
237  p_OTAPI = nullptr;
238 
240  return OT_API::CleanupOTApp();
241  }
242  }
243  return false;
244 }
245 
246 // SetAppBinaryFolder
247 // OPTIONAL. Used in Android and Qt.
248 //
249 // Certain platforms use this to override the Prefix folder.
250 // Basically /usr/local is the prefix folder by default, meaning
251 // /usr/local/lib/opentxs will be the location of the scripts. But
252 // if you override AppBinary folder to, say, "res/raw"
253 // (Android does something like that) then even though the prefix remains
254 // as /usr/local, the scripts folder will be res/raw
255 //
256 //
257 void OTAPI_Exec::SetAppBinaryFolder(const std::string& strFolder) const
258 {
259  OTPaths::SetAppBinaryFolder(strFolder.c_str());
260 }
261 
262 // SetHomeFolder
263 // OPTIONAL. Used in Android.
264 //
265 // The AppDataFolder, such as /Users/au/.ot, is constructed from the home
266 // folder, such as /Users/au.
267 //
268 // Normally the home folder is auto-detected, but certain platforms, such as
269 // Android, require us to explicitly set this folder from the Java code. Then
270 // the AppDataFolder is constructed from it. (It's the only way it can be done.)
271 //
272 // In Android, you would SetAppBinaryFolder to the path to
273 // "/data/app/packagename/res/raw",
274 // and you would SetHomeFolder to "/data/data/[app package]/files/"
275 //
276 void OTAPI_Exec::SetHomeFolder(const std::string& strFolder) const
277 {
278  OTPaths::SetHomeFolder(strFolder.c_str());
279 }
280 
282 {
283  return p_OTAPI;
284 }
285 
286 int64_t OTAPI_Exec::StringToLong(const std::string& strNumber) const
287 {
288  return OTString::StringToLong(strNumber);
289 }
290 
291 std::string OTAPI_Exec::LongToString(const int64_t& lNumber) const
292 {
293  std::string strNumber;
294  std::stringstream strstream;
295 
296  strstream << lNumber;
297  strstream >> strNumber;
298 
299  return strNumber;
300 }
301 
302 uint64_t OTAPI_Exec::StringToUlong(const std::string& strNumber) const
303 {
304  return OTString::StringToUlong(strNumber);
305 }
306 
307 std::string OTAPI_Exec::UlongToString(const uint64_t& lNumber) const
308 {
309  std::string strNumber;
310  std::stringstream strstream;
311 
312  strstream << lNumber;
313  strstream >> strNumber;
314 
315  return strNumber;
316 }
317 
322 void OTAPI_Exec::Output(const int32_t& nLogLevel,
323  const std::string& strOutput) const
324 {
325  const OTString otstrOutput(!strOutput.empty() ? strOutput : "\n");
326 
327  OTLog::Output(nLogLevel, otstrOutput.Get());
328 }
329 
330 bool OTAPI_Exec::SetWallet(const std::string& strWalletFilename) const
331 {
332  bool bIsInitialized = OTAPI()->IsInitialized();
333  if (!bIsInitialized) {
334  otErr << __FUNCTION__ << ": Error: OT_API not Initialized!!\n";
335  OT_FAIL;
336  }
337  else {
338  OTString sWalletFilename(strWalletFilename);
339 
340  if (sWalletFilename.Exists()) {
341  return OTAPI()->SetWalletFilename(strWalletFilename);
342  }
343  else {
344  otErr << __FUNCTION__ << ": Error:: Wallet Filename is Null!\n";
345  }
346  OT_FAIL;
347  }
348 }
349 
359 {
360  return OTAPI()->WalletExists();
361 }
362 
364 {
365  return OTAPI()->LoadWallet();
366 }
367 
369 {
370  return OTAPI()->LoadWallet();
371 }
372 
374 {
375  return OTLog::GetMemlogSize();
376 }
377 
378 std::string OTAPI_Exec::GetMemlogAtIndex(const int32_t& nIndex) const
379 {
380  return OTLog::GetMemlogAtIndex(nIndex).Get();
381 }
382 
383 std::string OTAPI_Exec::PeekMemlogFront() const
384 {
385  return OTLog::PeekMemlogFront().Get();
386 }
387 
388 std::string OTAPI_Exec::PeekMemlogBack() const
389 {
390  return OTLog::PeekMemlogBack().Get();
391 }
392 
394 {
395  return OTLog::PopMemlogFront();
396 }
397 
399 {
400  return OTLog::PopMemlogBack();
401 }
402 
403 // OpenTransactions.h
404 // bool NumList_Add (OTNumList& theList, const OTNumList&
405 // theNewNumbers);
406 // bool NumList_Remove (OTNumList& theList, const OTNumList&
407 // theOldNumbers);
408 // bool NumList_VerifyQuery(OTNumList& theList, const OTNumList&
409 // theQueryNumbers);
410 // bool NumList_VerifyAll (OTNumList& theList, const OTNumList&
411 // theQueryNumbers);
412 // int32_t NumList_Count (OTNumList& theList);
413 
414 // OTAPI_funcdef.h
415 // std::string OTAPI_Exec::NumList_Add (const std::string&
416 // strNumList, const std::string& strNumbers);
417 // std::string OTAPI_Exec::NumList_Remove (const std::string&
418 // strNumList, const std::string& strNumbers);
419 // int32_t OTAPI_Exec::NumList_VerifyQuery(const std::string&
420 // strNumList, const std::string& strNumbers); // returns bool
421 // int32_t OTAPI_Exec::NumList_VerifyAll (const std::string&
422 // strNumList, const std::string& strNumbers); // returns bool
423 // int32_t OTAPI_Exec::NumList_Count (const std::string&
424 // strNumList);
425 
426 // Returns new list if ALL strNumbers are successfully added to strNumList.
427 // Otherwise returns "" and doesn't change anything.
428 //
429 std::string OTAPI_Exec::NumList_Add(const std::string& strNumList,
430  const std::string& strNumbers) const
431 {
432  bool bIsInitialized = OTAPI()->IsInitialized();
433  if (!bIsInitialized) {
434  otErr << __FUNCTION__
435  << ": Not initialized; call OT_API::Init first.\n";
436  OT_FAIL;
437  }
438  if (strNumbers.empty()) {
439  otErr << __FUNCTION__ << ": Null: strNumbers passed in!\n";
440  OT_FAIL;
441  }
442 
443  // strNumList can be null, (create a new one).
444  OTNumList theList, theNewNumbers(strNumbers);
445 
446  if ("" != strNumList) {
447  const OTString otstrNumList(strNumList);
448  theList.Add(otstrNumList);
449  }
450 
451  const bool& bAdded = OTAPI()->NumList_Add(theList, theNewNumbers);
452 
453  OTString strOutput;
454  if (bAdded && theList.Output(strOutput)) {
455  std::string pBuf = strOutput.Get();
456 
457  return pBuf;
458  }
459 
460  return "";
461 }
462 
463 // Returns new list if ALL strNumbers are successfully removed from strNumList.
464 // Otherwise returns "" and doesn't change anything.
465 //
466 std::string OTAPI_Exec::NumList_Remove(const std::string& strNumList,
467  const std::string& strNumbers) const
468 {
469  bool bIsInitialized = OTAPI()->IsInitialized();
470  if (!bIsInitialized) {
471  otErr << __FUNCTION__
472  << ": Not initialized; call OT_API::Init first.\n";
473  OT_FAIL;
474  }
475 
476  if (strNumList.empty()) {
477  otErr << __FUNCTION__ << ": Null: strNumList passed in!\n";
478  OT_FAIL;
479  }
480  if (strNumbers.empty()) {
481  otErr << __FUNCTION__ << ": Null: strNumbers passed in!\n";
482  OT_FAIL;
483  }
484 
485  OTNumList theList(strNumList), theNewNumbers(strNumbers);
486 
487  const bool& bRemoved = OTAPI()->NumList_Remove(theList, theNewNumbers);
488 
489  OTString strOutput;
490  if (bRemoved && theList.Output(strOutput)) {
491  std::string pBuf = strOutput.Get();
492 
493  return pBuf;
494  }
495 
496  return "";
497 }
498 
499 // Verifies strNumbers as a SUBSET of strNumList.
500 //
501 bool OTAPI_Exec::NumList_VerifyQuery(const std::string& strNumList,
502  const std::string& strNumbers) const
503 {
504  bool bIsInitialized = OTAPI()->IsInitialized();
505  if (!bIsInitialized) {
506  otErr << __FUNCTION__
507  << ": Not initialized; call OT_API::Init first.\n";
508  OT_FAIL;
509  }
510 
511  if (strNumList.empty()) {
512  otErr << __FUNCTION__ << ": Null: strNumList passed in!\n";
513  OT_FAIL;
514  }
515  if (strNumbers.empty()) {
516  otErr << __FUNCTION__ << ": Null: strNumbers passed in!\n";
517  OT_FAIL;
518  }
519 
520  OTNumList theList(strNumList), theNewNumbers(strNumbers);
521 
522  const bool& bVerified =
523  OTAPI()->NumList_VerifyQuery(theList, theNewNumbers);
524 
525  return bVerified ? true : false;
526 }
527 
528 // Verifies COUNT and CONTENT but NOT ORDER.
529 //
530 bool OTAPI_Exec::NumList_VerifyAll(const std::string& strNumList,
531  const std::string& strNumbers) const
532 {
533  bool bIsInitialized = OTAPI()->IsInitialized();
534  if (!bIsInitialized) {
535  otErr << __FUNCTION__
536  << ": Not initialized; call OT_API::Init first.\n";
537  OT_FAIL;
538  }
539  if (strNumList.empty()) {
540  otErr << __FUNCTION__ << ": Null: strNumList passed in!\n";
541  OT_FAIL;
542  }
543  if (strNumbers.empty()) {
544  otErr << __FUNCTION__ << ": Null: strNumbers passed in!\n";
545  OT_FAIL;
546  }
547  OTNumList theList(strNumList), theNewNumbers(strNumbers);
548 
549  const bool& bVerified = OTAPI()->NumList_VerifyAll(theList, theNewNumbers);
550 
551  return bVerified ? true : false;
552 }
553 
554 int32_t OTAPI_Exec::NumList_Count(const std::string& strNumList) const
555 {
556  bool bIsInitialized = OTAPI()->IsInitialized();
557  if (!bIsInitialized) {
558  otErr << __FUNCTION__
559  << ": Not initialized; call OT_API::Init first.\n";
560  OT_FAIL;
561  }
562  if (strNumList.empty()) {
563  otErr << __FUNCTION__ << ": Null: strNumList passed in!\n";
564  OT_FAIL;
565  }
566  OTNumList theList(strNumList);
567 
568  return OTAPI()->NumList_Count(theList);
569 }
570 
571 // CREATE NYM -- Create new User
572 //
573 // Creates a new Nym and adds it to the wallet.
574 // (Including PUBLIC and PRIVATE KEYS.)
575 //
576 // Returns a new User ID (with files already created)
577 // or "" upon failure.
578 //
579 // Once it exists, use OTAPI_Exec::createUserAccount() to
580 // register your new Nym at any given Server. (Nearly all
581 // server requests require this...)
582 //
584  const int32_t& nKeySize, // must be 1024, 2048, 4096, or 8192
585  const std::string& NYM_ID_SOURCE, // Can be empty.
586  const std::string& ALT_LOCATION) const // Can be empty.
587 {
588  if (0 >= nKeySize) {
589  otErr << __FUNCTION__
590  << ": Keysize is 0 or less, will fail! Try 1024.\n";
591  OT_FAIL;
592  }
593  OTPseudonym* pNym =
594  OTAPI()->CreateNym(nKeySize, NYM_ID_SOURCE, ALT_LOCATION);
595  if (nullptr == pNym) // Creation failed.
596  {
597  otOut << __FUNCTION__ << ": Failed trying to create Nym.\n";
598  return "";
599  }
600  // -----------------------------------------------------}
601  OTString strOutput;
602  pNym->GetIdentifier(strOutput); // We're returning the new Nym ID.
603  if (strOutput.Exists()) return strOutput.Get();
604  return "";
605 }
606 
608  const std::string& NYM_ID, const std::string& SERVER_ID) const
609 {
610  if (NYM_ID.empty()) {
611  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
612  OT_FAIL;
613  }
614  if (SERVER_ID.empty()) {
615  otErr << __FUNCTION__ << ": nullptr SERVER_ID passed in!\n";
616  OT_FAIL;
617  }
618  const OTIdentifier nymId(NYM_ID), serverId(SERVER_ID);
619  OTNumList numlist;
620  std::string str_return;
621 
622  if (OTCronItem::GetActiveCronTransNums(numlist, nymId, serverId)) {
623  OTString strOutput;
624  numlist.Output(strOutput);
625  str_return = strOutput.Get();
626  }
627 
628  return str_return;
629 }
630 
631 std::string OTAPI_Exec::GetActiveCronItem(const std::string& SERVER_ID,
632  int64_t lTransNum) const
633 {
634  if (SERVER_ID.empty()) {
635  otErr << __FUNCTION__ << ": nullptr SERVER_ID passed in!\n";
636  OT_FAIL;
637  }
638  if (0 > lTransNum) {
639  otErr << __FUNCTION__ << ": Negative: lTransNum passed in!\n";
640  OT_FAIL;
641  }
642  const OTIdentifier serverId(SERVER_ID);
643  std::string str_return;
644  const int64_t lTransactionNum = static_cast<int64_t>(lTransNum);
645 
646  std::unique_ptr<OTCronItem> pCronItem(
647  OTCronItem::LoadActiveCronReceipt(lTransactionNum, serverId));
648  if (nullptr != pCronItem) {
649  const OTString strCronItem(*pCronItem);
650 
651  str_return = strCronItem.Get();
652  }
653  return str_return;
654 }
655 
656 std::string OTAPI_Exec::GetNym_SourceForID(const std::string& NYM_ID) const
657 {
658  if (NYM_ID.empty()) {
659  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
660  OT_FAIL;
661  }
662  OTPasswordData thePWData(OT_PW_DISPLAY);
663  OTIdentifier nym_id(NYM_ID);
664  // This tries to get, then tries to load as public, then tries to load as
665  // private.
666  OTPseudonym* pNym =
667  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
668  if (nullptr == pNym) return "";
669  const std::string str_return(pNym->GetNymIDSource().Get());
670  return str_return;
671 }
672 
674  const std::string& NYM_ID) const
675 {
676  if (NYM_ID.empty()) {
677  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
678  OT_FAIL;
679  }
680  OTPasswordData thePWData(OT_PW_DISPLAY);
681  OTIdentifier nym_id(NYM_ID);
682  // This tries to get, then tries to load as public, then tries to load as
683  // private.
684  OTPseudonym* pNym =
685  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
686  if (nullptr == pNym) return "";
687  const std::string str_return(pNym->GetAltLocation().Get());
688  return str_return;
689 }
690 
691 int32_t OTAPI_Exec::GetNym_CredentialCount(const std::string& NYM_ID) const
692 {
693  if (NYM_ID.empty()) {
694  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
695  OT_FAIL;
696  }
697  OTPasswordData thePWData(OT_PW_DISPLAY);
698  OTIdentifier nym_id(NYM_ID);
699  // This tries to get, then tries to load as public, then tries to load as
700  // private.
701  OTPseudonym* pNym =
702  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
703  if (nullptr == pNym) return (-1);
704  const int32_t nReturnValue =
705  static_cast<int32_t>(pNym->GetMasterCredentialCount());
706  return nReturnValue;
707 }
708 
709 std::string OTAPI_Exec::GetNym_CredentialID(const std::string& NYM_ID,
710  const int32_t& nIndex) const
711 {
712  if (NYM_ID.empty()) {
713  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
714  OT_FAIL;
715  }
716  OTPasswordData thePWData(OT_PW_DISPLAY);
717  OTIdentifier nym_id(NYM_ID);
718  // This tries to get, then tries to load as public, then tries to load as
719  // private.
720  OTPseudonym* pNym =
721  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
722  if (nullptr == pNym) return "";
723  std::string str_return;
724  const OTCredential* pCredential =
725  pNym->GetMasterCredentialByIndex(static_cast<const int32_t>(nIndex));
726 
727  if (nullptr != pCredential)
728  str_return = pCredential->GetMasterCredID().Get();
729  return str_return;
730 }
731 
733  const std::string& NYM_ID, const std::string& CREDENTIAL_ID) const
734 {
735  if (NYM_ID.empty()) {
736  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
737  OT_FAIL;
738  }
739  OTPasswordData thePWData(OT_PW_DISPLAY);
740  OTIdentifier nym_id(NYM_ID);
741  // This tries to get, then tries to load as public, then tries to load as
742  // private.
743  OTPseudonym* pNym =
744  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
745  if (nullptr == pNym) return "";
746  std::string str_return;
747  const OTString strCredID(CREDENTIAL_ID);
748  OTCredential* pCredential = pNym->GetMasterCredential(strCredID);
749 
750  if (nullptr != pCredential) // Found the master credential...
751  str_return = pCredential->GetPubCredential().Get();
752  return str_return;
753 }
754 
755 int32_t OTAPI_Exec::GetNym_RevokedCredCount(const std::string& NYM_ID) const
756 {
757  if (NYM_ID.empty()) {
758  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
759  OT_FAIL;
760  }
761  OTPasswordData thePWData(OT_PW_DISPLAY);
762  OTIdentifier nym_id(NYM_ID);
763  // This tries to get, then tries to load as public, then tries to load as
764  // private.
765  OTPseudonym* pNym =
766  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
767  if (nullptr == pNym) return (-1);
768  const int32_t nReturnValue =
769  static_cast<int32_t>(pNym->GetRevokedCredentialCount());
770  return nReturnValue;
771 }
772 
773 std::string OTAPI_Exec::GetNym_RevokedCredID(const std::string& NYM_ID,
774  const int32_t& nIndex) const
775 {
776  if (NYM_ID.empty()) {
777  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
778  OT_FAIL;
779  }
780  OTPasswordData thePWData(OT_PW_DISPLAY);
781  OTIdentifier nym_id(NYM_ID);
782  // This tries to get, then tries to load as public, then tries to load as
783  // private.
784  OTPseudonym* pNym =
785  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
786  if (nullptr == pNym) return "";
787  std::string str_return;
788  const OTCredential* pCredential =
789  pNym->GetRevokedCredentialByIndex(static_cast<const int32_t>(nIndex));
790 
791  if (nullptr != pCredential) {
792  str_return = pCredential->GetMasterCredID().Get();
793  }
794  return str_return;
795 }
796 
798  const std::string& NYM_ID, const std::string& CREDENTIAL_ID) const
799 {
800  if (NYM_ID.empty()) {
801  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
802  OT_FAIL;
803  }
804  OTPasswordData thePWData(OT_PW_DISPLAY);
805  OTIdentifier nym_id(NYM_ID);
806  // This tries to get, then tries to load as public, then tries to load as
807  // private.
808  OTPseudonym* pNym =
809  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
810  if (nullptr == pNym) return "";
811  std::string str_return;
812  const OTString strCredID(CREDENTIAL_ID);
813  const OTCredential* pCredential = pNym->GetRevokedCredential(strCredID);
814 
815  if (nullptr != pCredential) // Found the (revoked) master credential...
816  str_return = pCredential->GetPubCredential().Get();
817  return str_return;
818 }
819 
821  const std::string& NYM_ID, const std::string& MASTER_CRED_ID) const
822 {
823  if (NYM_ID.empty()) {
824  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
825  OT_FAIL;
826  }
827  if (MASTER_CRED_ID.empty()) {
828  otErr << __FUNCTION__ << ": nullptr MASTER_CRED_ID passed in!\n";
829  OT_FAIL;
830  }
831  OTPasswordData thePWData(OT_PW_DISPLAY);
832  OTIdentifier nym_id(NYM_ID);
833  // This tries to get, then tries to load as public, then tries to load as
834  // private.
835  OTPseudonym* pNym =
836  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
837  if (nullptr == pNym) return (-1);
838  const OTString strCredID(MASTER_CRED_ID);
839  OTCredential* pCredential = pNym->GetMasterCredential(strCredID);
840 
841  if (nullptr != pCredential) // Found the master credential...
842  {
843  const size_t nSubCredCount = pCredential->GetSubcredentialCount();
844 
845  const int32_t nReturnValue = static_cast<const int32_t>(nSubCredCount);
846  return nReturnValue;
847  }
848 
849  return (-1);
850 }
851 
853  const std::string& NYM_ID, const std::string& MASTER_CRED_ID,
854  const int32_t& nIndex) const
855 {
856  if (NYM_ID.empty()) {
857  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
858  OT_FAIL;
859  }
860  if (MASTER_CRED_ID.empty()) {
861  otErr << __FUNCTION__ << ": nullptr MASTER_CRED_ID passed in!\n";
862  OT_FAIL;
863  }
864  OTPasswordData thePWData(OT_PW_DISPLAY);
865  OTIdentifier nym_id(NYM_ID);
866  // This tries to get, then tries to load as public, then tries to load as
867  // private.
868  OTPseudonym* pNym =
869  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
870  if (nullptr == pNym) return "";
871  const OTString strCredID(MASTER_CRED_ID);
872  OTCredential* pCredential = pNym->GetMasterCredential(strCredID);
873 
874  if (nullptr != pCredential) // Found the master credential...
875  return pCredential->GetSubcredentialIDByIndex(
876  static_cast<const int32_t>(nIndex));
877 
878  return "";
879 }
880 
882  const std::string& NYM_ID, const std::string& MASTER_CRED_ID,
883  const std::string& SUB_CRED_ID) const
884 {
885  if (NYM_ID.empty()) {
886  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
887  OT_FAIL;
888  }
889  if (MASTER_CRED_ID.empty()) {
890  otErr << __FUNCTION__ << ": nullptr MASTER_CRED_ID passed in!\n";
891  OT_FAIL;
892  }
893  if (SUB_CRED_ID.empty()) {
894  otErr << __FUNCTION__ << ": nullptr SUB_CRED_ID passed in!\n";
895  OT_FAIL;
896  }
897  OTPasswordData thePWData(OT_PW_DISPLAY);
898  OTIdentifier nym_id(NYM_ID);
899  // This tries to get, then tries to load as public, then tries to load as
900  // private.
901  OTPseudonym* pNym =
902  OTAPI()->GetOrLoadNym(nym_id, false, __FUNCTION__, &thePWData);
903  if (nullptr == pNym) return "";
904  const OTString strCredID(MASTER_CRED_ID);
905  OTCredential* pCredential = pNym->GetMasterCredential(strCredID);
906 
907  if (nullptr != pCredential) // Found the master credential...
908  {
909  const OTString strSubID(SUB_CRED_ID);
910  const OTSubcredential* pSub = pCredential->GetSubcredential(strSubID);
911 
912  if (nullptr != pSub) return pSub->GetPubCredential().Get();
913  }
914  return "";
915 }
916 
917 std::string OTAPI_Exec::AddSubcredential(const std::string& NYM_ID,
918  const std::string& MASTER_CRED_ID,
919  const int32_t& nKeySize) const
920 {
921  if (NYM_ID.empty()) {
922  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
923  OT_FAIL;
924  }
925  if (MASTER_CRED_ID.empty()) {
926  otErr << __FUNCTION__ << ": nullptr MASTER_CRED_ID passed in!\n";
927  OT_FAIL;
928  }
929  if (0 >= nKeySize) {
930  otErr << __FUNCTION__
931  << ": Keysize is 0 or less, will fail! Try 1024.\n";
932  OT_FAIL;
933  }
934  OTPasswordData thePWData(OT_PW_DISPLAY);
935  OTIdentifier nym_id(NYM_ID);
936  // This tries to get, then tries to load as public, then tries to load as
937  // private.
938  OTPseudonym* pNym =
939  OTAPI()->GetOrLoadPrivateNym(nym_id, false, __FUNCTION__, &thePWData);
940  if (nullptr == pNym) return "";
941  const OTString strCredID(MASTER_CRED_ID);
942  OTCredential* pCredential = pNym->GetMasterCredential(strCredID);
943 
944  if (nullptr == pCredential)
945  otOut << __FUNCTION__ << ": Sorry, (Nym " << NYM_ID
946  << ") no master credential found with the ID: " << strCredID
947  << "\n";
948  else // Found the master credential...
949  {
950  const OTIdentifier idMasterCredential(strCredID);
951  OTString strNewSubcredID;
952 
953  const bool bAdded =
954  pNym->AddNewSubkey(idMasterCredential, nKeySize, nullptr,
955  &thePWData, &strNewSubcredID);
956 
957  if (bAdded) {
958  return strNewSubcredID.Get();
959  }
960  else
961  otErr << __FUNCTION__
962  << ": Failed trying to add new subcredential.\n";
963  }
964  return "";
965 }
966 
967 bool OTAPI_Exec::RevokeSubcredential(const std::string& NYM_ID,
968  const std::string& MASTER_CRED_ID,
969  const std::string& SUB_CRED_ID) const
970 {
971  if (NYM_ID.empty()) {
972  otErr << __FUNCTION__ << ": nullptr NYM_ID passed in!\n";
973  OT_FAIL;
974  }
975  if (MASTER_CRED_ID.empty()) {
976  otErr << __FUNCTION__ << ": nullptr MASTER_CRED_ID passed in!\n";
977  OT_FAIL;
978  }
979  if (SUB_CRED_ID.empty()) {
980  otErr << __FUNCTION__ << ": nullptr SUB_CRED_ID passed in!\n";
981  OT_FAIL;
982  }
983  OTPasswordData thePWData(OT_PW_DISPLAY);
984  OTIdentifier nym_id(NYM_ID);
985  // This tries to get, then tries to load as public, then tries to load as
986  // private.
987  OTPseudonym* pNym =
988  OTAPI()->GetOrLoadPrivateNym(nym_id, false, __FUNCTION__, &thePWData);
989  if (nullptr == pNym) return false;
990  const OTString strCredID(MASTER_CRED_ID);
991  OTCredential* pCredential = pNym->GetMasterCredential(strCredID);
992 
993  if (nullptr == pCredential)
994  otOut << __FUNCTION__ << ": Sorry, (Nym " << NYM_ID
995  << ") no master credential found with the ID : " << strCredID
996  << "\n";
997  else // Found the master credential...
998  {
999  const OTString strSubID(SUB_CRED_ID);
1000  const OTSubcredential* pSub = pCredential->GetSubcredential(strSubID);
1001 
1002  if (nullptr == pSub)
1003  otOut << __FUNCTION__ << ": Found master credential (" << strCredID
1004  << "), but unable to "
1005  "find subcredential with ID: " << strSubID << "\n";
1006  else {
1007 
1008  // TODO: Okay we found master AND subcredential. Now let's revoke
1009  // it...
1010  //
1011 
1012  otErr << "\n\n\nOTAPI_Wrap::" << __FUNCTION__
1013  << ": TODO: REVOKING IS NOT YET CODED. ADD FUNCTION CALL "
1014  "HERE TO REVOKE SUB-CREDENTIAL!\n\n\n";
1015 
1016  // return true;
1017  }
1018  }
1019  return false;
1020 }
1021 
1023  const std::string& str_Contract) const
1024 {
1025  bool bIsInitialized = OTAPI()->IsInitialized();
1026  if (!bIsInitialized) {
1027  otErr << __FUNCTION__
1028  << ": Not initialized; call OT_API::Init first.\n";
1029  OT_FAIL;
1030  }
1031  if (str_Contract.empty()) {
1032  otErr << __FUNCTION__ << ": Null: str_Contract passed in!\n";
1033  OT_FAIL;
1034  }
1035  std::string str_Trim(str_Contract);
1036  std::string str_Trim2 = OTString::trim(str_Trim);
1037  OTString strContract(str_Trim2.c_str());
1038 
1039  if (strContract.GetLength() < 2) {
1040  otOut << __FUNCTION__ << ": Empty contract passed in!\n";
1041  return "";
1042  }
1043  OTAssetContract theContract;
1044 
1045  if (theContract.LoadContractFromString(strContract)) {
1046  OTIdentifier idOutput;
1047  theContract.CalculateContractID(idOutput);
1048  const OTString strOutput(idOutput);
1049  std::string pBuf = strOutput.Get();
1050 
1051  return pBuf;
1052  }
1053  return "";
1054 }
1055 
1057  const std::string& str_Contract) const
1058 {
1059  bool bIsInitialized = OTAPI()->IsInitialized();
1060  if (!bIsInitialized) {
1061  otErr << __FUNCTION__
1062  << ": Not initialized; call OT_API::Init first.\n";
1063  OT_FAIL;
1064  }
1065  if (str_Contract.empty()) {
1066  otErr << __FUNCTION__ << ": Null: str_Contract passed in!\n";
1067  OT_FAIL;
1068  }
1069  std::string str_Trim(str_Contract);
1070  std::string str_Trim2 = OTString::trim(str_Trim);
1071  OTString strContract(str_Trim2.c_str());
1072 
1073  if (strContract.GetLength() < 2) {
1074  otOut << __FUNCTION__ << ": Empty contract passed in!\n";
1075  return "";
1076  }
1077  OTServerContract theContract;
1078 
1079  if (theContract.LoadContractFromString(strContract)) {
1080  OTIdentifier idOutput;
1081  theContract.CalculateContractID(idOutput);
1082  const OTString strOutput(idOutput);
1083  std::string pBuf = strOutput.Get();
1084 
1085  return pBuf;
1086  }
1087  return "";
1088 }
1089 
1090 // Creates a contract based on the contents passed in,
1091 // then sets the contract key based on the NymID,
1092 // and signs it with that Nym.
1093 // This function will also ADD the contract to the wallet.
1094 // Returns: the new contract ID, or "" if failure.
1095 //
1097  const std::string& NYM_ID, const std::string& strXMLcontents) const
1098 {
1099  bool bIsInitialized = OTAPI()->IsInitialized();
1100  if (!bIsInitialized) {
1101  otErr << __FUNCTION__
1102  << ": Not initialized; call OT_API::Init first.\n";
1103  OT_FAIL;
1104  }
1105 
1106  if (NYM_ID.empty()) {
1107  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
1108  OT_FAIL;
1109  }
1110  if (strXMLcontents.empty()) {
1111  otErr << __FUNCTION__ << ": Null: strXMLcontents passed in!\n";
1112  OT_FAIL;
1113  }
1114 
1115  OTWallet* pWallet =
1116  OTAPI()->GetWallet(__FUNCTION__); // This logs and ASSERTs already.
1117  if (nullptr == pWallet) return "";
1118  // By this point, pWallet is a good pointer. (No need to cleanup.)
1119  const OTIdentifier theNymID(NYM_ID);
1120  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
1121  if (nullptr == pNym) return "";
1122  std::string str_Trim(strXMLcontents);
1123  std::string str_Trim2 = OTString::trim(str_Trim);
1124  OTString strContract(str_Trim2.c_str());
1125 
1126  if (strContract.GetLength() < 2) {
1127  otOut << __FUNCTION__ << ": Empty XML contents passed in! (Failure.)\n";
1128  return "";
1129  }
1130  std::unique_ptr<OTServerContract> pContract(new OTServerContract);
1131  pContract->CreateContract(
1132  strContract, *pNym); // <========== **** CREATE CONTRACT!! ****
1133  // But does it meet our requirements?
1134  //
1135  const OTPseudonym* pContractKeyNym = pContract->GetContractPublicNym();
1136  // const OTAsymmetricKey * pKey = pContract->GetContractPublicKey();
1137 
1138  if (nullptr == pContractKeyNym) {
1139  otOut << __FUNCTION__ << ": Missing 'key' tag with name=\"contract\" "
1140  "and text value containing the public cert or "
1141  "public key of the signer Nym. (Please add it "
1142  "first. Failure.)\n";
1143  return "";
1144  }
1145  else if (!pNym->CompareID(*pContractKeyNym)) {
1146  otOut << __FUNCTION__ << ": Found 'key' tag with name=\"contract\" and "
1147  "text value, but it apparently does NOT "
1148  "contain the public cert or public key of the "
1149  "signer Nym. Please fix that first; see the "
1150  "sample data. (Failure.)\n";
1151  return "";
1152  }
1153  /*
1154  <key name="contract">
1155  - -----BEGIN CERTIFICATE-----
1156  MIICZjCCAc+gAwIBAgIJAO14L19TJgzcMA0GCSqGSIb3DQEBBQUAMFcxCzAJBgNV
1157  BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTEQMA4GA1UEBxMHRmFpcmZheDERMA8G
1158  A1UEChMIWm9yay5vcmcxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTAwOTI5MDUyMzAx
1159  WhcNMjAwOTI2MDUyMzAxWjBeMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2lu
1160  aWExEDAOBgNVBAcTB0ZhaXJmYXgxETAPBgNVBAoTCFpvcmsub3JnMRcwFQYDVQQD
1161  Ew5zaGVsbC56b3JrLm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3vD9
1162  fO4ov4854L8wXrgfv2tltDz0ieVrTNSLuy1xuQyb//+MwZ0EYwu8jMMQrqbUaYG6
1163  y8zJu32yBKrBNPPwJ+fJE+tfgVg860dGVbwMd4KhpkKtppJXmZaGqLqvELaXa4Uw
1164  9N3qg/faj0NMEDIBhv/tD/B5U65vH+U0JlRJ07kCAwEAAaMzMDEwCQYDVR0TBAIw
1165  ADAkBgNVHREEHTAbgg5zaGVsbC56b3JrLm9yZ4IJbG9jYWxob3N0MA0GCSqGSIb3
1166  DQEBBQUAA4GBALLXPa/naWsiXsw0JwlSiG7aOmvMF2romUkcr6uObhN7sghd38M0
1167  l2kKTiptnA8txrri8RhqmQgOgiyKFCKBkxY7/XGot62cE8Y1+lqGXlhu2UHm6NjA
1168  pRKvng75J2HTjmmsbCHy+nexn4t44wssfPYlGPD8sGwmO24u9tRfdzJE
1169  - -----END CERTIFICATE-----
1170  </key>
1171  */
1172  OTString strHostname;
1173  int32_t nPort = 0;
1174 
1175  if (!pContract->GetConnectInfo(strHostname, nPort)) {
1176  otOut << __FUNCTION__ << ": Unable to retrieve connection info from "
1177  "this contract. Please fix that first; see "
1178  "the sample data. (Failure.)\n";
1179  return "";
1180  }
1181  // By this point, we know that the "contract" key is properly attached
1182  // to the raw XML contents, AND that the NymID for that key matches
1183  // the NymID passed into this function.
1184  // We also know that the connect info was properly attached to this
1185  // server contract.
1186  // So we can proceed to add it to the wallet...
1187  //
1188  OTIdentifier idOutput;
1189  pContract->CalculateContractID(idOutput);
1190  const OTString strOutput(idOutput);
1191 
1192  pWallet->AddServerContract(*(pContract.release()));
1193  std::string pBuf = strOutput.Get();
1194 
1195  return pBuf;
1196 }
1197 
1199  const std::string& NYM_ID, const std::string& strXMLcontents) const
1200 {
1201  bool bIsInitialized = OTAPI()->IsInitialized();
1202  if (!bIsInitialized) {
1203  otErr << __FUNCTION__
1204  << ": Not initialized; call OT_API::Init first.\n";
1205  OT_FAIL;
1206  }
1207  if (NYM_ID.empty()) {
1208  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
1209  OT_FAIL;
1210  }
1211  if (strXMLcontents.empty()) {
1212  otErr << __FUNCTION__ << ": Null: strXMLcontents passed in!\n";
1213  OT_FAIL;
1214  }
1215  OTWallet* pWallet =
1216  OTAPI()->GetWallet(__FUNCTION__); // This logs and ASSERTs already.
1217  if (nullptr == pWallet) return "";
1218  // By this point, pWallet is a good pointer. (No need to cleanup.)
1219  const OTIdentifier theNymID(NYM_ID);
1220  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
1221  if (nullptr == pNym) return "";
1222  std::string str_Trim(strXMLcontents);
1223  std::string str_Trim2 = OTString::trim(str_Trim);
1224  OTString strContract(str_Trim2.c_str());
1225 
1226  if (strContract.GetLength() < 2) {
1227  otOut << __FUNCTION__ << ": Empty XML contents passed in! (Failure.)\n";
1228  return "";
1229  }
1230  std::unique_ptr<OTAssetContract> pContract(new OTAssetContract);
1231  pContract->CreateContract(
1232  strContract, *pNym); // <========== **** CREATE CONTRACT!! ****
1233  // But does it meet our requirements?
1234  //
1235  const OTPseudonym* pContractKeyNym = pContract->GetContractPublicNym();
1236  // const OTAsymmetricKey * pKey = pContract->GetContractPublicKey();
1237 
1238  if (nullptr == pContractKeyNym) {
1239  otOut << __FUNCTION__ << ": Missing 'key' tag with name=\"contract\" "
1240  "and text value containing the public cert or "
1241  "public key of the signer Nym. (Please add it "
1242  "first. Failure.)\n";
1243  return "";
1244  }
1245  else if (!pNym->CompareID(*pContractKeyNym)) {
1246  otOut << __FUNCTION__ << ": Found 'key' tag with name=\"contract\" and "
1247  "text value, but it apparently does NOT "
1248  "contain the public cert or public key of the "
1249  "signer Nym. Please fix that first; see the "
1250  "sample data. (Failure.)\n";
1251  return "";
1252  }
1253  /*
1254  <key name="contract">
1255  - -----BEGIN CERTIFICATE-----
1256  MIICZjCCAc+gAwIBAgIJAO14L19TJgzcMA0GCSqGSIb3DQEBBQUAMFcxCzAJBgNV
1257  BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTEQMA4GA1UEBxMHRmFpcmZheDERMA8G
1258  A1UEChMIWm9yay5vcmcxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTAwOTI5MDUyMzAx
1259  WhcNMjAwOTI2MDUyMzAxWjBeMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2lu
1260  aWExEDAOBgNVBAcTB0ZhaXJmYXgxETAPBgNVBAoTCFpvcmsub3JnMRcwFQYDVQQD
1261  Ew5zaGVsbC56b3JrLm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3vD9
1262  fO4ov4854L8wXrgfv2tltDz0ieVrTNSLuy1xuQyb//+MwZ0EYwu8jMMQrqbUaYG6
1263  y8zJu32yBKrBNPPwJ+fJE+tfgVg860dGVbwMd4KhpkKtppJXmZaGqLqvELaXa4Uw
1264  9N3qg/faj0NMEDIBhv/tD/B5U65vH+U0JlRJ07kCAwEAAaMzMDEwCQYDVR0TBAIw
1265  ADAkBgNVHREEHTAbgg5zaGVsbC56b3JrLm9yZ4IJbG9jYWxob3N0MA0GCSqGSIb3
1266  DQEBBQUAA4GBALLXPa/naWsiXsw0JwlSiG7aOmvMF2romUkcr6uObhN7sghd38M0
1267  l2kKTiptnA8txrri8RhqmQgOgiyKFCKBkxY7/XGot62cE8Y1+lqGXlhu2UHm6NjA
1268  pRKvng75J2HTjmmsbCHy+nexn4t44wssfPYlGPD8sGwmO24u9tRfdzJE
1269  - -----END CERTIFICATE-----
1270  </key>
1271  */
1272  // By this point, we know that the "contract" key is properly attached
1273  // to the raw XML contents, AND that the NymID for that key matches
1274  // the NymID passed into this function.
1275  // So we can proceed to add it to the wallet...
1276  //
1277  OTIdentifier idOutput;
1278  pContract->CalculateContractID(idOutput);
1279  const OTString strOutput(idOutput);
1280 
1281  pWallet->AddAssetContract(*(pContract.release()));
1282  std::string pBuf = strOutput.Get();
1283 
1284  return pBuf;
1285 }
1286 
1287 // Use these below functions to get the new contract ITSELF, using its ID
1288 // that was returned by the above two functions:
1289 //
1290 // std::string OTAPI_Exec::GetServer_Contract(const std::string& SERVER_ID); //
1291 // Return's Server's contract (based on server ID)
1292 // std::string OTAPI_Exec::GetAssetType_Contract(const std::string&
1293 // ASSET_TYPE_ID); // Returns currency contract based on Asset Type ID
1294 
1295 std::string OTAPI_Exec::GetServer_Contract(const std::string& SERVER_ID)
1296  const // Return's Server's contract (based on server
1297  // ID)
1298 {
1299  bool bIsInitialized = OTAPI()->IsInitialized();
1300 
1301  if (!bIsInitialized) {
1302  otErr << __FUNCTION__
1303  << ": Not initialized; call OT_API::Init first.\n";
1304  OT_FAIL;
1305  }
1306  if (SERVER_ID.empty()) {
1307  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
1308  OT_FAIL;
1309  }
1310 
1311  const OTIdentifier theServerID(SERVER_ID);
1312  OTServerContract* pServer = OTAPI()->GetServer(theServerID, __FUNCTION__);
1313  if (nullptr == pServer) return "";
1314  // By this point, pServer is a good pointer. (No need to cleanup.)
1315  const OTString strOutput(*pServer);
1316  std::string pBuf = strOutput.Get();
1317 
1318  return pBuf;
1319 }
1320 
1321 // Returns amount from formatted string, based on currency contract and locale.
1322 //
1323 int64_t OTAPI_Exec::StringToAmount(const std::string& ASSET_TYPE_ID,
1324  const std::string& str_input) const
1325 {
1326  bool bIsInitialized = OTAPI()->IsInitialized();
1327  if (!bIsInitialized) {
1328  otErr << __FUNCTION__
1329  << ": Not initialized; call OT_API::Init first.\n";
1330  OT_FAIL;
1331  }
1332  if (ASSET_TYPE_ID.empty()) {
1333  otErr << __FUNCTION__ << ": Empty ASSET_TYPE_ID passed in!\n";
1334  OT_FAIL;
1335  }
1336  const OTIdentifier theAssetID(ASSET_TYPE_ID);
1337  OTAssetContract* pContract =
1338  OTAPI()->GetAssetType(theAssetID, __FUNCTION__);
1339  if (nullptr == pContract) return OT_ERROR_AMOUNT;
1340  // By this point, pContract is a good pointer. (No need to cleanup.)
1341  int64_t theResult;
1342  bool bParsed = pContract->StringToAmount(theResult, str_input);
1343  return bParsed ? theResult : StringToLong(str_input);
1344 }
1345 
1346 // Returns formatted string for output, for a given amount, based on currency
1347 // contract and locale.
1348 //
1349 std::string OTAPI_Exec::FormatAmount(const std::string& ASSET_TYPE_ID,
1350  const int64_t& THE_AMOUNT) const
1351 {
1352  bool bIsInitialized = OTAPI()->IsInitialized();
1353  if (!bIsInitialized) {
1354  otErr << __FUNCTION__
1355  << ": Not initialized; call OT_API::Init first.\n";
1356  OT_FAIL;
1357  }
1358  if (ASSET_TYPE_ID.empty()) {
1359  otErr << __FUNCTION__ << ": Empty ASSET_TYPE_ID passed in!\n";
1360  OT_FAIL;
1361  }
1362  // NOTE: probably just remove this. I think we now allow negative amounts to
1363  // be formatted.
1364  // if (0 > THE_AMOUNT)
1365  // {
1366  // otErr << __FUNCTION__ << ": Negative: THE_AMOUNT passed in: " <<
1367  // OTAPI_Exec::LongToString(THE_AMOUNT) << "\n";
1368  // OT_FAIL;
1369  // }
1370  const OTIdentifier theAssetID(ASSET_TYPE_ID);
1371  OTAssetContract* pContract =
1372  OTAPI()->GetAssetType(theAssetID, __FUNCTION__);
1373  if (nullptr == pContract) return "";
1374  // By this point, pContract is a good pointer. (No need to cleanup.)
1375  const int64_t lAmount = THE_AMOUNT;
1376  int64_t theAmount(lAmount);
1377  OTString strBackup(LongToString(THE_AMOUNT));
1378  std::string str_result;
1379  const bool bFormatted =
1380  pContract->FormatAmount(theAmount, str_result); // Convert 545 to $5.45.
1381  const OTString strOutput(bFormatted ? str_result.c_str() : strBackup.Get());
1382 
1383  std::string pBuf = strOutput.Get();
1384  return pBuf;
1385 }
1386 
1387 std::string OTAPI_Exec::GetAssetType_Contract(const std::string& ASSET_TYPE_ID)
1388  const // Returns currency contract based on
1389  // Asset Type ID
1390 {
1391  bool bIsInitialized = OTAPI()->IsInitialized();
1392  if (!bIsInitialized) {
1393  otErr << __FUNCTION__
1394  << ": Not initialized; call OT_API::Init first.\n";
1395  OT_FAIL;
1396  }
1397 
1398  if (ASSET_TYPE_ID.empty()) {
1399  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
1400  OT_FAIL;
1401  }
1402 
1403  const OTIdentifier theAssetID(ASSET_TYPE_ID);
1404  OTAssetContract* pContract =
1405  OTAPI()->GetAssetType(theAssetID, __FUNCTION__);
1406  if (nullptr == pContract) return "";
1407  // By this point, pContract is a good pointer. (No need to cleanup.)
1408  const OTString strOutput(*pContract);
1409  std::string pBuf = strOutput.Get();
1410  return pBuf;
1411 }
1412 
1413 // If you have a server contract that you'd like to add
1414 // to your wallet, call this function.
1415 //
1416 int32_t OTAPI_Exec::AddServerContract(const std::string& strContract) const
1417 {
1418  if (strContract.empty()) {
1419  otErr << __FUNCTION__ << ": Null: strContract passed in!\n";
1420  OT_FAIL;
1421  }
1422  OTWallet* pWallet =
1423  OTAPI()->GetWallet(__FUNCTION__); // This logs and ASSERTs already.
1424  if (nullptr == pWallet) return false;
1425  // By this point, pWallet is a good pointer. (No need to cleanup.)
1426  OT_ASSERT("" != strContract);
1427  std::string str_Trim(strContract);
1428  std::string str_Trim2 = OTString::trim(str_Trim);
1429  OTString otstrContract(str_Trim2.c_str());
1430  OTServerContract* pContract = new OTServerContract;
1431  OT_ASSERT(nullptr != pContract);
1432 
1433  // Check the server signature on the contract here. (Perhaps the message is
1434  // good enough?
1435  // After all, the message IS signed by the server and contains the Account.
1436  // if (pContract->LoadContract() && pContract->VerifyContract())
1437  if (otstrContract.Exists() &&
1438  pContract->LoadContractFromString(otstrContract)) {
1439  OTIdentifier theContractID;
1440 
1441  pContract->CalculateContractID(theContractID);
1442  pContract->SetIdentifier(theContractID);
1443 
1444  pWallet->AddServerContract(*pContract);
1445  pContract = nullptr; // Success. The wallet "owns" it now, no need to
1446  // clean it up.
1447  }
1448  // cleanup
1449  if (pContract) {
1450  delete pContract;
1451  pContract = nullptr;
1452 
1453  return false;
1454  }
1455 
1456  return true;
1457 }
1458 
1459 // If you have an asset contract that you'd like to add
1460 // to your wallet, call this function.
1461 //
1462 int32_t OTAPI_Exec::AddAssetContract(const std::string& strContract) const
1463 {
1464  if (strContract.empty()) {
1465  otErr << __FUNCTION__ << ": Null: strContract passed in!\n";
1466  OT_FAIL;
1467  }
1468  OTWallet* pWallet =
1469  OTAPI()->GetWallet(__FUNCTION__); // This logs and ASSERTs already.
1470  if (nullptr == pWallet) return false;
1471  // By this point, pWallet is a good pointer. (No need to cleanup.)
1472  OT_ASSERT("" != strContract);
1473  std::string str_Trim(strContract);
1474  std::string str_Trim2 = OTString::trim(str_Trim);
1475  OTString otstrContract(str_Trim2.c_str());
1476 
1477  OTAssetContract* pContract = new OTAssetContract;
1478  OT_ASSERT(nullptr != pContract);
1479 
1480  // Check the server signature on the contract here. (Perhaps the message is
1481  // good enough?
1482  // After all, the message IS signed by the server and contains the Account.
1483  // if (pContract->LoadContract() && pContract->VerifyContract())
1484  if (otstrContract.Exists() &&
1485  pContract->LoadContractFromString(otstrContract)) {
1486  OTIdentifier theContractID;
1487 
1488  pContract->CalculateContractID(theContractID);
1489  pContract->SetIdentifier(theContractID);
1490 
1491  // Next make sure the wallet has this contract on its list...
1492  pWallet->AddAssetContract(*pContract);
1493  pContract = nullptr; // Success. The wallet "owns" it now, no need to
1494  // clean it up.
1495  }
1496  // cleanup
1497  if (pContract) {
1498  delete pContract;
1499  pContract = nullptr;
1500 
1501  return false;
1502  }
1503  return true;
1504 }
1505 
1506 int32_t OTAPI_Exec::GetNymCount(void) const
1507 {
1508  return OTAPI()->GetNymCount();
1509 }
1510 
1511 int32_t OTAPI_Exec::GetServerCount(void) const
1512 {
1513  return OTAPI()->GetServerCount();
1514 }
1515 
1517 {
1518  return OTAPI()->GetAssetTypeCount();
1519 }
1520 
1521 int32_t OTAPI_Exec::GetAccountCount(void) const
1522 {
1523  return OTAPI()->GetAccountCount();
1524 }
1525 
1526 // *** FUNCTIONS FOR REMOVING VARIOUS CONTRACTS AND NYMS FROM THE WALLET ***
1527 
1528 // Can I remove this server contract from my wallet?
1529 //
1530 // You cannot remove the server contract from your wallet if there are accounts
1531 // (or nyms) in there using it.
1532 // This function tells you whether you can remove the server contract or not.
1533 // (Whether there are accounts or nyms using it...)
1534 //
1535 // returns bool
1536 //
1537 bool OTAPI_Exec::Wallet_CanRemoveServer(const std::string& SERVER_ID) const
1538 {
1539  bool bIsInitialized = OTAPI()->IsInitialized();
1540  if (!bIsInitialized) {
1541  otErr << __FUNCTION__
1542  << ": Not initialized; call OT_API::Init first.\n";
1543  OT_FAIL;
1544  }
1545  if (SERVER_ID.empty()) {
1546  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
1547  OT_FAIL;
1548  }
1549  OTIdentifier theID(SERVER_ID);
1550  const int32_t& nCount = OTAPI_Exec::GetAccountCount();
1551 
1552  // Loop through all the accounts.
1553  for (int32_t i = 0; i < nCount; i++) {
1554  std::string pAcctID = OTAPI_Exec::GetAccountWallet_ID(i);
1555  OTString strAcctID(pAcctID);
1556 
1557  std::string pID =
1559  OTIdentifier theCompareID(pID);
1560 
1561  if (theID == theCompareID) {
1562  otOut << __FUNCTION__ << ": Unable to remove server contract "
1563  << SERVER_ID << " from "
1564  "wallet, because Account " << strAcctID
1565  << " uses it.\n";
1566  return false;
1567  }
1568  }
1569  const int32_t& nNymCount = OTAPI_Exec::GetNymCount();
1570 
1571  // Loop through all the Nyms. (One might be registered on that server.)
1572  //
1573  for (int32_t i = 0; i < nNymCount; i++) {
1574  std::string pNymID = OTAPI_Exec::GetNym_ID(i);
1575  OTString strNymID(pNymID);
1576 
1577  if (true ==
1578  OTAPI_Exec::IsNym_RegisteredAtServer(strNymID.Get(), SERVER_ID)) {
1579  otOut << __FUNCTION__ << ": Unable to remove server contract "
1580  << SERVER_ID << " from "
1581  "wallet, because Nym " << strNymID
1582  << " is registered there. (Delete that first...)\n";
1583  return false;
1584  }
1585  }
1586  return true;
1587 }
1588 
1589 // Remove this server contract from my wallet!
1590 //
1591 // Try to remove the server contract from the wallet.
1592 // This will not work if there are any accounts in the wallet for the same
1593 // server ID.
1594 // returns bool
1595 //
1596 bool OTAPI_Exec::Wallet_RemoveServer(const std::string& SERVER_ID) const
1597 {
1598  bool bIsInitialized = OTAPI()->IsInitialized();
1599  if (!bIsInitialized) {
1600  otErr << __FUNCTION__
1601  << ": Not initialized; call OT_API::Init first.\n";
1602  OT_FAIL;
1603  }
1604 
1605  if (SERVER_ID.empty()) {
1606  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
1607  OT_FAIL;
1608  }
1609 
1610  // Make sure there aren't any dependent accounts..
1611  if (!OTAPI_Exec::Wallet_CanRemoveServer(SERVER_ID)) return false;
1612 
1613  // TODO: the above call proves that there are no accounts laying around
1614  // for this server ID. (No need to worry about "orphaned accounts.")
1615  //
1616  // However, there may still be Nyms registered at the server! Therefore,
1617  // we need to loop through the Nyms, and make sure none of them has been
1618  // registered at this server ID. If it has, then we need to message the
1619  // server
1620  // to "deregister" the Nym, which is much cleaner. Otherwise server's only
1621  // other alternative is to expire Nyms that have gone unused for some
1622  // specific
1623  // period of time, presumably those terms are described in the server
1624  // contract.
1625  //
1626  OTWallet* pWallet = OTAPI()->GetWallet(__FUNCTION__);
1627 
1628  if (nullptr == pWallet) {
1629  otErr << __FUNCTION__ << ": No wallet found...\n";
1630  OT_FAIL;
1631  }
1632 
1633  OTIdentifier theID(SERVER_ID);
1634 
1635  if (pWallet->RemoveServerContract(theID)) {
1636  pWallet->SaveWallet();
1637  otOut << __FUNCTION__
1638  << ": Removed server contract from the wallet: " << SERVER_ID
1639  << "\n";
1640  return true;
1641  }
1642  return false;
1643 }
1644 
1645 // Can I remove this asset contract from my wallet?
1646 //
1647 // You cannot remove the asset contract from your wallet if there are accounts
1648 // in there using it.
1649 // This function tells you whether you can remove the asset contract or not.
1650 // (Whether there are accounts...)
1651 // returns bool
1652 //
1653 bool OTAPI_Exec::Wallet_CanRemoveAssetType(const std::string& ASSET_ID) const
1654 {
1655  bool bIsInitialized = OTAPI()->IsInitialized();
1656  if (!bIsInitialized) {
1657  otErr << __FUNCTION__
1658  << ": Not initialized; call OT_API::Init first.\n";
1659  OT_FAIL;
1660  }
1661 
1662  if (ASSET_ID.empty()) {
1663  otErr << __FUNCTION__ << ": Null: ASSET_ID passed in!\n";
1664  OT_FAIL;
1665  }
1666 
1667  OTIdentifier theID(ASSET_ID);
1668  const int32_t& nCount = OTAPI_Exec::GetAccountCount();
1669 
1670  // Loop through all the accounts.
1671  for (int32_t i = 0; i < nCount; i++) {
1672  std::string pAcctID = OTAPI_Exec::GetAccountWallet_ID(i);
1673  OTString strAcctID(pAcctID);
1674 
1675  std::string pID =
1677  OTIdentifier theCompareID(pID);
1678 
1679  if (theID == theCompareID) {
1680  otOut << __FUNCTION__ << ": Unable to remove asset contract "
1681  << ASSET_ID << " from "
1682  "wallet: Account " << strAcctID
1683  << " uses it.\n";
1684  return false;
1685  }
1686  }
1687  return true;
1688 }
1689 
1690 // Remove this asset contract from my wallet!
1691 //
1692 // Try to remove the asset contract from the wallet.
1693 // This will not work if there are any accounts in the wallet for the same asset
1694 // type ID.
1695 // returns bool
1696 //
1697 bool OTAPI_Exec::Wallet_RemoveAssetType(const std::string& ASSET_ID) const
1698 {
1699  bool bIsInitialized = OTAPI()->IsInitialized();
1700  if (!bIsInitialized) {
1701  otErr << __FUNCTION__
1702  << ": Not initialized; call OT_API::Init first.\n";
1703  OT_FAIL;
1704  }
1705 
1706  if (ASSET_ID.empty()) {
1707  otErr << __FUNCTION__ << ": Null: ASSET_ID passed in!\n";
1708  OT_FAIL;
1709  }
1710 
1711  // Make sure there aren't any dependent accounts..
1712  if (!OTAPI_Exec::Wallet_CanRemoveAssetType(ASSET_ID)) return false;
1713 
1714  OTWallet* pWallet = OTAPI()->GetWallet(__FUNCTION__);
1715 
1716  if (nullptr == pWallet) {
1717  otErr << __FUNCTION__ << ": No wallet found...!\n";
1718  OT_FAIL;
1719  }
1720 
1721  OTIdentifier theID(ASSET_ID);
1722 
1723  if (pWallet->RemoveAssetContract(theID)) {
1724  pWallet->SaveWallet();
1725  otOut << __FUNCTION__
1726  << ": Removed asset contract from the wallet: " << ASSET_ID
1727  << "\n";
1728  return true;
1729  }
1730  return false;
1731 }
1732 
1733 // Can I remove this Nym from my wallet?
1734 //
1735 // You cannot remove the Nym from your wallet if there are accounts in there
1736 // using it.
1737 // This function tells you whether you can remove the Nym or not. (Whether there
1738 // are accounts...)
1739 // It also checks to see if the Nym in question is registered at any servers.
1740 //
1741 // returns bool
1742 //
1743 bool OTAPI_Exec::Wallet_CanRemoveNym(const std::string& NYM_ID) const
1744 {
1745  bool bIsInitialized = OTAPI()->IsInitialized();
1746  if (!bIsInitialized) {
1747  otErr << __FUNCTION__
1748  << ": Not initialized; call OT_API::Init first.\n";
1749  OT_FAIL;
1750  }
1751 
1752  if (NYM_ID.empty()) {
1753  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
1754  OT_FAIL;
1755  }
1756 
1757  OTIdentifier theID(NYM_ID);
1758  OTPseudonym* pNym = OTAPI()->GetNym(theID, __FUNCTION__);
1759  if (nullptr == pNym) return false;
1760  // Make sure the Nym doesn't have any accounts in the wallet.
1761  // (Client must close those before calling this.)
1762  //
1763  const int32_t& nCount = OTAPI_Exec::GetAccountCount();
1764 
1765  // Loop through all the accounts.
1766  for (int32_t i = 0; i < nCount; i++) {
1767  std::string pAcctID = OTAPI_Exec::GetAccountWallet_ID(i);
1768  OTString strAcctID(pAcctID);
1769 
1770  std::string pID = OTAPI_Exec::GetAccountWallet_NymID(strAcctID.Get());
1771 
1772  if (pID.empty()) {
1773  otErr << __FUNCTION__ << ": Bug in OTAPI_Exec::Wallet_CanRemoveNym "
1774  "/ OTAPI_Exec::GetAccountWallet_NymID\n";
1775  return false;
1776  }
1777 
1778  OTIdentifier theCompareID(pID);
1779 
1780  // Looks like the Nym still has some accounts in this wallet.
1781  if (theID == theCompareID) {
1782  otOut << __FUNCTION__ << ": Nym cannot be removed because there "
1783  "are still accounts in the wallet for "
1784  "that Nym.\n";
1785  return false;
1786  }
1787  }
1788 
1789  // Make sure the Nym isn't registered at any servers...
1790  // (Client must unregister at those servers before calling this function..)
1791  //
1792  const int32_t& nServerCount = OTAPI_Exec::GetServerCount();
1793 
1794  for (int32_t i = 0; i < nServerCount; i++) {
1795  std::string str_ServerID = OTAPI_Exec::GetServer_ID(i);
1796 
1797  if ("" != str_ServerID) {
1798  const OTString strServerID(str_ServerID);
1799 
1800  if (pNym->IsRegisteredAtServer(strServerID)) {
1801  otOut << __FUNCTION__ << ": Nym cannot be removed because "
1802  "there are still servers in the "
1803  "wallet that the Nym is registered "
1804  "at.\n";
1805  return false;
1806  }
1807  }
1808  }
1809 
1810  // TODO: Make sure Nym doesn't have any cash in any purses...
1811 
1812  return true;
1813 }
1814 
1815 // Remove this Nym from my wallet!
1816 //
1817 // Try to remove the Nym from the wallet.
1818 // This will fail if the Nym is registered at any servers, or has any accounts.
1819 //
1820 // returns bool
1821 //
1822 bool OTAPI_Exec::Wallet_RemoveNym(const std::string& NYM_ID) const
1823 {
1824  bool bIsInitialized = OTAPI()->IsInitialized();
1825  if (!bIsInitialized) {
1826  otErr << __FUNCTION__
1827  << ": Not initialized; call OT_API::Init first.\n";
1828  OT_FAIL;
1829  }
1830 
1831  if (NYM_ID.empty()) {
1832  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
1833  OT_FAIL;
1834  }
1835 
1836  // DONE: The below call proves already that there are no accounts laying
1837  // around
1838  // for this Nym. (No need to worry about "orphaned accounts.")
1839  //
1840  // DONE (finally):
1841  // However, the Nym might still be registered at various servers, even
1842  // without asset accounts.
1843  // Therefore, we need to iterate through the server contracts, and if the
1844  // Nym is registered at
1845  // any of the servers, then "deregister" (before deleting the Nym entirely.)
1846  // This is much
1847  // cleaner for the server side, who otherwise has to expired unused nyms
1848  // based on some rule
1849  // presumably to be found in the server contract.
1850  if (!OTAPI_Exec::Wallet_CanRemoveNym(NYM_ID)) return false;
1851 
1852  OTWallet* pWallet = OTAPI()->GetWallet(__FUNCTION__);
1853 
1854  if (nullptr == pWallet) {
1855  otErr << __FUNCTION__ << ": No wallet found...!\n";
1856  OT_FAIL;
1857  }
1858 
1859  OTIdentifier theID(NYM_ID);
1860 
1861  if (pWallet->RemoveNym(theID)) {
1862  otOut << __FUNCTION__ << ": Success erasing Nym from wallet: " << NYM_ID
1863  << "\n";
1864  pWallet->SaveWallet();
1865  return true;
1866  }
1867  else
1868  otOut << __FUNCTION__ << ": Failure erasing Nym from wallet: " << NYM_ID
1869  << "\n";
1870 
1871  return false;
1872 }
1873 
1874 // Can I remove this Account from my wallet?
1875 //
1876 // You cannot remove the Account from your wallet if there are transactions
1877 // still open.
1878 // This function tells you whether you can remove the Account or not. (Whether
1879 // there are transactions...)
1880 // Also, balance must be zero to do this.
1881 //
1882 // returns bool
1883 //
1884 bool OTAPI_Exec::Wallet_CanRemoveAccount(const std::string& ACCOUNT_ID) const
1885 {
1886  bool bIsInitialized = OTAPI()->IsInitialized();
1887  if (!bIsInitialized) {
1888  otErr << __FUNCTION__
1889  << ": Not initialized; call OT_API::Init first.\n";
1890  OT_FAIL;
1891  }
1892 
1893  if (ACCOUNT_ID.empty()) {
1894  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
1895  OT_FAIL;
1896  }
1897 
1898  const OTIdentifier theAccountID(ACCOUNT_ID);
1899 
1900  OTAccount* pAccount = OTAPI()->GetAccount(theAccountID, __FUNCTION__);
1901  if (nullptr == pAccount) return false;
1902  // Balance must be zero in order to close an account!
1903  else if (pAccount->GetBalance() != 0) {
1904  otOut << __FUNCTION__ << ": Account balance MUST be zero in order to "
1905  "close an asset account: " << ACCOUNT_ID
1906  << ".\n";
1907  return false;
1908  }
1909  bool BOOL_RETURN_VALUE = false;
1910 
1911  const OTIdentifier& theServerID = pAccount->GetPurportedServerID();
1912  const OTIdentifier& theUserID = pAccount->GetUserID();
1913 
1914  // There is an OT_ASSERT in here for memory failure,
1915  // but it still might return "" if various verification fails.
1916  std::unique_ptr<OTLedger> pInbox(
1917  OTAPI()->LoadInbox(theServerID, theUserID, theAccountID));
1918  std::unique_ptr<OTLedger> pOutbox(
1919  OTAPI()->LoadOutbox(theServerID, theUserID, theAccountID));
1920 
1921  if (nullptr == pInbox) {
1922  otOut << __FUNCTION__
1923  << ": Failure calling OT_API::LoadInbox.\n Account ID : "
1924  << ACCOUNT_ID << "\n";
1925  }
1926  else if (nullptr == pOutbox) {
1927  otOut << __FUNCTION__
1928  << ": Failure calling OT_API::LoadOutbox.\n Account ID : "
1929  << ACCOUNT_ID << "\n";
1930  }
1931  else if ((pInbox->GetTransactionCount() > 0) ||
1932  (pOutbox->GetTransactionCount() > 0)) {
1933  otOut << __FUNCTION__ << ": Failure: You cannot remove an asset "
1934  "account if there are inbox/outbox items "
1935  "still waiting to be processed.\n";
1936  }
1937  else
1938  BOOL_RETURN_VALUE = true; // SUCCESS!
1939 
1940  return BOOL_RETURN_VALUE;
1941 }
1942 
1943 // So the client side knows which ones he has in storage, vs which ones he
1944 // still needs to download.
1945 //
1947  const std::string& SERVER_ID,
1948  const std::string& USER_ID, // Unused here for now, but still convention.
1949  const std::string& ACCOUNT_ID, // If for Nymbox (vs inbox/outbox) then pass
1950  // USER_ID in this field also.
1951  const int32_t& nBoxType, // 0/nymbox, 1/inbox, 2/outbox
1952  const int64_t& TRANSACTION_NUMBER) const
1953 {
1954 
1955  if (SERVER_ID.empty()) {
1956  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
1957  OT_FAIL;
1958  }
1959  if (USER_ID.empty()) {
1960  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
1961  OT_FAIL;
1962  }
1963  if (ACCOUNT_ID.empty()) {
1964  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
1965  OT_FAIL;
1966  }
1967  if (!((0 == nBoxType) || (1 == nBoxType) || (2 == nBoxType))) {
1968  otErr << __FUNCTION__
1969  << ": nBoxType is of wrong type: value: " << nBoxType << "\n";
1970  OT_FAIL;
1971  }
1972  if (0 > TRANSACTION_NUMBER) {
1973  otErr << __FUNCTION__ << ": Negative: TRANSACTION_NUMBER passed in!\n";
1974  OT_FAIL;
1975  }
1976  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
1977  theAccountID(ACCOUNT_ID);
1978  const int64_t lTransactionNum = TRANSACTION_NUMBER;
1979  switch (nBoxType) {
1980  case 0: // nymbox
1981  case 1: // inbox
1982  case 2: // outbox
1983  break;
1984  default:
1985  otErr << __FUNCTION__ << ": Error: bad nBoxType: " << nBoxType
1986  << " for UserID: " << USER_ID << " AcctID: " << ACCOUNT_ID
1987  << " (expected one of: 0/nymbox, 1/inbox, 2/outbox)\n";
1988  return false;
1989  }
1990  return OTAPI()->DoesBoxReceiptExist(
1991  theServerID, theUserID, theAccountID, // If for Nymbox (vs inbox/outbox)
1992  // then pass USER_ID in this field
1993  // also.
1994  nBoxType, // 0/nymbox, 1/inbox, 2/outbox
1995  static_cast<int64_t>(lTransactionNum));
1996 }
1997 
1998 // Returns int32_t:
1999 // -1 means error; no message was sent.
2000 // -2 means the message was sent, but the request number must be passed as a
2001 // string, so call OTAPI_Exec::GetLargeRequestNum.
2002 // 0 means NO error, but also: no message was sent.
2003 // >0 means NO error, and the message was sent, and the request number fits into
2004 // an integer...
2005 // ...and in fact the requestNum IS the return value!
2006 // ===> In 99% of cases, this LAST option is what actually happens!!
2007 //
2009  const std::string& SERVER_ID, const std::string& USER_ID,
2010  const std::string& ACCOUNT_ID, // If for Nymbox (vs inbox/outbox) then pass
2011  // USER_ID in this field also.
2012  const int32_t& nBoxType, // 0/nymbox, 1/inbox, 2/outbox
2013  const int64_t& TRANSACTION_NUMBER) const
2014 {
2015  if (SERVER_ID.empty()) {
2016  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
2017  OT_FAIL;
2018  }
2019  if (USER_ID.empty()) {
2020  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
2021  OT_FAIL;
2022  }
2023  if (ACCOUNT_ID.empty()) {
2024  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
2025  OT_FAIL;
2026  }
2027  if (!((0 == nBoxType) || (1 == nBoxType) || (2 == nBoxType))) {
2028  otErr << __FUNCTION__
2029  << ": nBoxType is of wrong type: value: " << nBoxType << "\n";
2030  OT_FAIL;
2031  }
2032  if (0 > TRANSACTION_NUMBER) {
2033  otErr << __FUNCTION__ << ": Negative: TRANSACTION_NUMBER passed in!\n";
2034  OT_FAIL;
2035  }
2036  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
2037  theAccountID(ACCOUNT_ID);
2038  const int64_t lTransactionNum = TRANSACTION_NUMBER;
2039  switch (nBoxType) {
2040  case 0: // nymbox
2041  case 1: // inbox
2042  case 2: // outbox
2043  break;
2044  default:
2045  otErr << __FUNCTION__ << ": Error: bad nBoxType: " << nBoxType
2046  << " for UserID: " << USER_ID << " AcctID: " << ACCOUNT_ID
2047  << "(expected one of: 0/nymbox, 1/inbox, 2/outbox)\n";
2048  return -1;
2049  }
2050 
2051  return OTAPI()->getBoxReceipt(theServerID, theUserID,
2052  theAccountID, // If for Nymbox (vs
2053  // inbox/outbox) then pass
2054  // USER_ID in this field also.
2055  nBoxType, // 0/nymbox, 1/inbox, 2/outbox
2056  static_cast<int64_t>(lTransactionNum));
2057 }
2058 
2059 // Returns int32_t:
2060 // -1 means error; no message was sent.
2061 // -2 means the message was sent, but the request number must be passed as a
2062 // string, so call OTAPI_Exec::GetLargeRequestNum.
2063 // 0 means NO error, but also: no message was sent.
2064 // >0 means NO error, and the message was sent, and the request number fits into
2065 // an integer...
2066 // ...and in fact the requestNum IS the return value!
2067 // ===> In 99% of cases, this LAST option is what actually happens!!
2068 //
2069 int32_t OTAPI_Exec::deleteAssetAccount(const std::string& SERVER_ID,
2070  const std::string& USER_ID,
2071  const std::string& ACCOUNT_ID) const
2072 {
2073  if (SERVER_ID.empty()) {
2074  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
2075  OT_FAIL;
2076  }
2077  if (USER_ID.empty()) {
2078  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
2079  OT_FAIL;
2080  }
2081  if (ACCOUNT_ID.empty()) {
2082  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
2083  OT_FAIL;
2084  }
2085 
2086  if (!OTAPI_Exec::Wallet_CanRemoveAccount(ACCOUNT_ID)) return 0;
2087 
2088  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
2089  theAccountID(ACCOUNT_ID);
2090 
2091  return OTAPI()->deleteAssetAccount(theServerID, theUserID, theAccountID);
2092 }
2093 
2094 // OT has the capability to export a Nym (normally stored in several files) as
2095 // an encoded
2096 // object (in base64-encoded form) and then import it again.
2097 // Returns: Exported Nym in String Form.
2098 //
2099 std::string OTAPI_Exec::Wallet_ExportNym(const std::string& NYM_ID) const
2100 {
2101  bool bIsInitialized = OTAPI()->IsInitialized();
2102  if (!bIsInitialized) {
2103  otErr << __FUNCTION__
2104  << ": Not initialized; call OT_API::Init first.\n";
2105  OT_FAIL;
2106  }
2107 
2108  if (NYM_ID.empty()) {
2109  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2110  OT_FAIL;
2111  }
2112 
2113  const OTIdentifier theNymID(NYM_ID);
2114 
2115  // Create a StringMap object with these values:
2116  //
2117  // id: The NymID.
2118  // name: The display name from the wallet.
2119  // cert: The public / private certfile in openssl format.
2120  // nymfile: The contents of the nymfile.
2121  //
2122  // Make sure to use master key when accessing them, but then put that on
2123  // pause while saving them to string. (Then unpause again.)
2124  //
2125  // Then Encode the StringMap into packed string form, and return it
2126  // from this function (or "".)
2127  //
2128  OTString strOutput;
2129 
2130  const bool& bExported = OTAPI()->Wallet_ExportNym(theNymID, strOutput);
2131 
2132  if (bExported) {
2133  std::string pBuf = strOutput.Get();
2134 
2135  return pBuf;
2136  }
2137 
2138  return "";
2139 }
2140 
2141 std::string OTAPI_Exec::Wallet_ExportCert(const std::string& NYM_ID) const
2142 {
2143  bool bIsInitialized = OTAPI()->IsInitialized();
2144  if (!bIsInitialized) {
2145  otErr << __FUNCTION__
2146  << ": Not initialized; call OT_API::Init first.\n";
2147  OT_FAIL;
2148  }
2149 
2150  if (NYM_ID.empty()) {
2151  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2152  OT_FAIL;
2153  }
2154 
2155  const OTIdentifier theNymID(NYM_ID);
2156 
2157  OTString strOutput;
2158 
2159  const bool& bExported = OTAPI()->Wallet_ExportCert(theNymID, strOutput);
2160 
2161  if (bExported) {
2162  std::string pBuf = strOutput.Get();
2163 
2164  return pBuf;
2165  }
2166 
2167  return "";
2168 }
2169 
2170 // OT has the capability to export a Nym (normally stored in several files) as
2171 // an encoded
2172 // object (in base64-encoded form) and then import it again.
2173 //
2174 // Returns: Nym ID of newly-imported Nym (or "".)
2175 //
2176 std::string OTAPI_Exec::Wallet_ImportNym(const std::string& FILE_CONTENTS) const
2177 {
2178  bool bIsInitialized = OTAPI()->IsInitialized();
2179  if (!bIsInitialized) {
2180  otErr << __FUNCTION__
2181  << ": Not initialized; call OT_API::Init first.\n";
2182  OT_FAIL;
2183  }
2184 
2185  if (FILE_CONTENTS.empty()) {
2186  otErr << __FUNCTION__ << ": Null: FILE_CONTENTS passed in!\n";
2187  OT_FAIL;
2188  }
2189 
2190  // Pause the master key, since this Nym is coming from outside
2191  // the wallet.
2192  //
2193  const OTString strFileContents(FILE_CONTENTS);
2194 
2195  OTIdentifier theNymID;
2196 
2197  const bool& bImported =
2198  OTAPI()->Wallet_ImportNym(strFileContents, &theNymID);
2199 
2200  // Decode the FILE_CONTENTS into a StringMap object,
2201  // and if success, make sure it contains these values:
2202  //
2203  // id: The NymID.
2204  // name: The display name from the wallet.
2205  // cert: The public / private certfile in openssl format.
2206  // nymfile: The contents of the nymfile.
2207  //
2208  // Unpause the master key.
2209  //
2210  // Do various verifications on the values to make sure there's no funny
2211  // business.
2212  //
2213  // Make sure the Nym with this ID isn't ALREADY in the wallet. If not, then
2214  // add it.
2215  //
2216  //
2217  //
2218 
2219  if (bImported) {
2220  const OTString strNymID(theNymID);
2221 
2222  std::string pBuf = strNymID.Get();
2223 
2224  return pBuf;
2225  }
2226 
2227  return "";
2228 }
2229 
2230 // In this case, instead of importing a special "OT Nym all-in-one exported"
2231 // file format,
2232 // we are importing the public/private keys only, from their Cert file contents,
2233 // and then
2234 // creating a blank Nymfile to go aint64_t with it. This is for when people wish
2235 // to import
2236 // pre-existing keys to create a new Nym.
2237 //
2238 // Returns: Nym ID of newly-imported Nym (or "".)
2239 //
2241  const std::string& DISPLAY_NAME, const std::string& FILE_CONTENTS) const
2242 {
2243  bool bIsInitialized = OTAPI()->IsInitialized();
2244  if (!bIsInitialized) {
2245  otErr << __FUNCTION__
2246  << ": Not initialized; call OT_API::Init first.\n";
2247  OT_FAIL;
2248  }
2249 
2250  // if (DISPLAY_NAME.empty()) { otErr << __FUNCTION__ << ": Null:
2251  // DISPLAY_NAME passed
2252  // in!\n"; OT_FAIL; }
2253  if (FILE_CONTENTS.empty()) {
2254  otErr << __FUNCTION__ << ": Null: FILE_CONTENTS passed in!\n";
2255  OT_FAIL;
2256  }
2257 
2258  const OTString strDisplayName(DISPLAY_NAME), strFileContents(FILE_CONTENTS);
2259 
2260  OTIdentifier theNymID;
2261 
2262  const bool& bImported =
2263  OTAPI()->Wallet_ImportCert(strDisplayName, strFileContents, &theNymID);
2264 
2265  if (bImported) {
2266  const OTString strNymID(theNymID);
2267 
2268  std::string pBuf = strNymID.Get();
2269 
2270  return pBuf;
2271  }
2272 
2273  return "";
2274 }
2275 
2276 /*
2277 CHANGE MASTER KEY and PASSWORD.
2278 
2279 Normally your passphrase is used to derive a key, which is used to unlock
2280 a random number (a symmetric key), which is used as the passphrase to open the
2281 master key, which is used as the passphrase to any given Nym.
2282 
2283 Since all the Nyms are encrypted to the master key, and since we can change the
2284 passphrase on the master key without changing the master key itself, then we
2285 don't
2286 have to do anything to update all the Nyms, since that part hasn't changed.
2287 
2288 But we might want a separate "Change Master Key" function that replaces that key
2289 itself, in which case we'd HAVE to load up all the Nyms and re-save them.
2290 
2291 UPDATE: Seems the easiest thing to do is to just change both the key and
2292 passphase
2293 at the same time here, by loading up all the private nyms, destroying the master
2294 key,
2295 and then saving all the private Nyms. (With master key never actually being
2296 "paused.")
2297 This will automatically cause it to generate a new master key during the saving
2298 process.
2299 (Make sure to save the wallet also.)
2300 */
2302 {
2303  return OTAPI()->Wallet_ChangePassphrase();
2304 }
2305 
2306 // bool OTPseudonym::Savex509CertAndPrivateKeyToString(OTString& strOutput,
2307 // OTString * pstrReason)
2308 
2309 // bool OTPseudonym::Savex509CertAndPrivateKey(bool bCreateFile,
2310 // OTString * pstrReason)
2311 
2312 // Attempts to find a full ID in the wallet, based on a partial of the same ID.
2313 // Returns "" on failure, otherwise returns the full ID.
2314 //
2316  const std::string& PARTIAL_ID) const
2317 {
2318  // OTPseudonym * GetNym(const OTIdentifier& NYM_ID, const std::string&
2319  // strFuncName="");
2320  // OTPseudonym * GetNymByIDPartialMatch(const std::string&PARTIAL_ID,
2321  // const std::string& strFuncName="");
2322  bool bIsInitialized = OTAPI()->IsInitialized();
2323  if (!bIsInitialized) {
2324  otErr << __FUNCTION__
2325  << ": Not initialized; call OT_API::Init first.\n";
2326  OT_FAIL;
2327  }
2328  if (PARTIAL_ID.empty()) {
2329  otErr << __FUNCTION__ << ": Null: PARTIAL_ID passed in!\n";
2330  OT_FAIL;
2331  }
2332  OTIdentifier thePartialID(PARTIAL_ID);
2333 
2334  // In this case, the user passed in the FULL ID.
2335  // (We STILL confirm whether he's found in the wallet...)
2336  //
2337  OTPseudonym* pObject =
2338  OTAPI()->GetNym(thePartialID, "OTAPI_Exec::Wallet_GetNymIDFromPartial");
2339 
2340  if (nullptr != pObject) // Found it (as full ID.)
2341  {
2342  OTString strID_Output(thePartialID);
2343  std::string pBuf = strID_Output.Get();
2344 
2345  return pBuf;
2346  }
2347  // Below this point, it definitely wasn't a FULL ID, so now we can
2348  // go ahead and search for it as a PARTIAL ID...
2349  //
2350  pObject = OTAPI()->GetNymByIDPartialMatch(
2351  PARTIAL_ID, "OTAPI_Exec::Wallet_GetNymIDFromPartial");
2352 
2353  if (nullptr != pObject) // Found it (as partial ID.)
2354  {
2355  OTString strID_Output;
2356  pObject->GetIdentifier(strID_Output);
2357  std::string pBuf = strID_Output.Get();
2358  return pBuf;
2359  }
2360 
2361  return "";
2362 }
2363 
2364 // Attempts to find a full ID in the wallet, based on a partial of the same ID.
2365 // Returns "" on failure, otherwise returns the full ID.
2366 //
2368  const std::string& PARTIAL_ID) const
2369 {
2370  // OTServerContract * GetServer(const OTIdentifier& THE_ID, const
2371  // std::string& strFuncName="");
2372  // OTServerContract * GetServerContractPartialMatch(const std::string
2373  // &PARTIAL_ID, const std::string& strFuncName="");
2374  bool bIsInitialized = OTAPI()->IsInitialized();
2375  if (!bIsInitialized) {
2376  otErr << __FUNCTION__
2377  << ": Not initialized; call OT_API::Init first.\n";
2378  OT_FAIL;
2379  }
2380 
2381  if (PARTIAL_ID.empty()) {
2382  otErr << __FUNCTION__ << ": Null: PARTIAL_ID passed in!\n";
2383  OT_FAIL;
2384  }
2385  OTIdentifier thePartialID(PARTIAL_ID);
2386 
2387  // In this case, the user passed in the FULL ID.
2388  // (We STILL confirm whether he's found in the wallet...)
2389  //
2390  OTServerContract* pObject = OTAPI()->GetServer(
2391  thePartialID, "OTAPI_Exec::Wallet_GetServerIDFromPartial");
2392 
2393  if (nullptr != pObject) // Found it (as full ID.)
2394  {
2395  OTString strID_Output(thePartialID);
2396  std::string pBuf = strID_Output.Get();
2397 
2398  return pBuf;
2399  }
2400  // Below this point, it definitely wasn't a FULL ID, so now we can
2401  // go ahead and search for it as a PARTIAL ID...
2402  //
2403  pObject = OTAPI()->GetServerContractPartialMatch(
2404  PARTIAL_ID, "OTAPI_Exec::Wallet_GetServerIDFromPartial");
2405 
2406  if (nullptr != pObject) // Found it (as partial ID.)
2407  {
2408  OTString strID_Output;
2409  pObject->GetIdentifier(strID_Output);
2410  std::string pBuf = strID_Output.Get();
2411 
2412  return pBuf;
2413  }
2414 
2415  return "";
2416 }
2417 
2418 // Attempts to find a full ID in the wallet, based on a partial of the same ID.
2419 // Returns "" on failure, otherwise returns the full ID.
2420 //
2422  const std::string& PARTIAL_ID) const
2423 {
2424  // OTAssetContract * GetAssetType(const OTIdentifier& THE_ID, const
2425  // std::string& strFuncName="");
2426  // OTAssetContract * GetAssetContractPartialMatch(const std::string
2427  // &PARTIAL_ID, const std::string& strFuncName="");
2428 
2429  bool bIsInitialized = OTAPI()->IsInitialized();
2430  if (!bIsInitialized) {
2431  otErr << __FUNCTION__
2432  << ": Not initialized; call OT_API::Init first.\n";
2433  OT_FAIL;
2434  }
2435 
2436  if (PARTIAL_ID.empty()) {
2437  otErr << __FUNCTION__ << ": Null: PARTIAL_ID passed in!\n";
2438  OT_FAIL;
2439  }
2440 
2441  OTIdentifier thePartialID(PARTIAL_ID);
2442 
2443  // In this case, the user passed in the FULL ID.
2444  // (We STILL confirm whether he's found in the wallet...)
2445  //
2446  OTAssetContract* pObject = OTAPI()->GetAssetType(
2447  thePartialID, "OTAPI_Exec::Wallet_GetAssetIDFromPartial");
2448 
2449  if (nullptr != pObject) // Found it (as full ID.)
2450  {
2451  OTString strID_Output(thePartialID);
2452  std::string pBuf = strID_Output.Get();
2453 
2454  return pBuf;
2455  }
2456  // Below this point, it definitely wasn't a FULL ID, so now we can
2457  // go ahead and search for it as a PARTIAL ID...
2458  //
2459  pObject = OTAPI()->GetAssetContractPartialMatch(
2460  PARTIAL_ID, "OTAPI_Exec::Wallet_GetAssetIDFromPartial");
2461 
2462  if (nullptr != pObject) // Found it (as partial ID.)
2463  {
2464  OTString strID_Output;
2465  pObject->GetIdentifier(strID_Output);
2466  std::string pBuf = strID_Output.Get();
2467 
2468  return pBuf;
2469  }
2470 
2471  return "";
2472 }
2473 
2475  const std::string& PARTIAL_ID) const
2476 {
2477  // OTAccount * GetAccount(const OTIdentifier& THE_ID, const
2478  // std::string& strFuncName="");
2479  // OTAccount * GetAccountPartialMatch(const std::string&PARTIAL_ID,
2480  // const std::string& strFuncName="");
2481 
2482  bool bIsInitialized = OTAPI()->IsInitialized();
2483  if (!bIsInitialized) {
2484  otErr << __FUNCTION__
2485  << ": Not initialized; call OT_API::Init first.\n";
2486  OT_FAIL;
2487  }
2488 
2489  if (PARTIAL_ID.empty()) {
2490  otErr << __FUNCTION__ << ": Null: PARTIAL_ID passed in!\n";
2491  OT_FAIL;
2492  }
2493 
2494  OTIdentifier thePartialID(PARTIAL_ID);
2495 
2496  // In this case, the user passed in the FULL ID.
2497  // (We STILL confirm whether he's found in the wallet...)
2498  //
2499  OTAccount* pObject = OTAPI()->GetAccount(
2500  thePartialID, "OTAPI_Exec::Wallet_GetNymIDFromPartial");
2501 
2502  if (nullptr != pObject) // Found it (as full ID.)
2503  {
2504  OTString strID_Output(thePartialID);
2505  std::string pBuf = strID_Output.Get();
2506 
2507  return pBuf;
2508  }
2509  // Below this point, it definitely wasn't a FULL ID, so now we can
2510  // go ahead and search for it as a PARTIAL ID...
2511  //
2512  pObject = OTAPI()->GetAccountPartialMatch(
2513  PARTIAL_ID, "OTAPI_Exec::Wallet_GetNymIDFromPartial");
2514 
2515  if (nullptr != pObject) // Found it (as partial ID.)
2516  {
2517  OTString strID_Output;
2518  pObject->GetIdentifier(strID_Output);
2519  std::string pBuf = strID_Output.Get();
2520 
2521  return pBuf;
2522  }
2523 
2524  return "";
2525 }
2526 
2528 std::string OTAPI_Exec::GetNym_ID(const int32_t& nIndex) const
2529 {
2530  if (0 > nIndex) {
2531  otErr << __FUNCTION__
2532  << ": nIndex is out of bounds (it's in the negative!)\n";
2533  OT_FAIL;
2534  }
2535 
2536  OTIdentifier theNymID;
2537  OTString strName;
2538 
2539  bool bGetNym = OTAPI()->GetNym(nIndex, theNymID, strName);
2540 
2541  if (bGetNym) {
2542  OTString strNymID(theNymID);
2543 
2544  std::string pBuf = strNymID.Get();
2545 
2546  return pBuf;
2547  }
2548 
2549  return "";
2550 }
2551 
2553 std::string OTAPI_Exec::GetNym_Name(const std::string& NYM_ID) const
2554 {
2555  if (NYM_ID.empty()) {
2556  otErr << __FUNCTION__ << ": Null NYM_ID passed in!\n";
2557  OT_FAIL;
2558  }
2559  OTIdentifier theNymID(NYM_ID);
2560  OTPseudonym* pNym = OTAPI()->GetNym(theNymID);
2561 
2562  if (nullptr != pNym) {
2563  OTString& strName = pNym->GetNymName();
2564  std::string pBuf = strName.Get();
2565 
2566  return pBuf;
2567  }
2568  return "";
2569 }
2570 
2571 bool OTAPI_Exec::IsNym_RegisteredAtServer(const std::string& NYM_ID,
2572  const std::string& SERVER_ID) const
2573 {
2574  if (NYM_ID.empty()) {
2575  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2576  OT_FAIL;
2577  }
2578  if (SERVER_ID.empty()) {
2579  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
2580  OT_FAIL;
2581  }
2582 
2583  const OTIdentifier theNymID(NYM_ID), theServerID(SERVER_ID);
2584 
2585  bool bSuccess = OTAPI()->IsNym_RegisteredAtServer(theNymID, theServerID);
2586 
2587  return (bSuccess) ? true : false;
2588 }
2589 
2590 // Returns Nym data (based on NymID)
2591 //
2592 std::string OTAPI_Exec::GetNym_Stats(const std::string& NYM_ID) const
2593 {
2594  if (NYM_ID.empty()) {
2595  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2596  OT_FAIL;
2597  }
2598 
2599  OTIdentifier theNymID(NYM_ID);
2600  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2601 
2602  if (nullptr != pNym) {
2603  OTString strOutput;
2604 
2605  pNym->DisplayStatistics(strOutput);
2606 
2607  std::string pBuf = strOutput.Get();
2608 
2609  return pBuf;
2610  }
2611 
2612  return "";
2613 }
2614 
2615 // Returns NymboxHash (based on ServerID)
2616 //
2618  const std::string& SERVER_ID,
2619  const std::string& NYM_ID) const // Returns NymboxHash (based on ServerID)
2620 {
2621  if (NYM_ID.empty()) {
2622  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2623  OT_FAIL;
2624  }
2625  if (SERVER_ID.empty()) {
2626  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
2627  OT_FAIL;
2628  }
2629 
2630  OTIdentifier theNymID(NYM_ID);
2631  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2632 
2633  if (nullptr != pNym) {
2634  OTIdentifier theNymboxHash;
2635  const std::string str_server_id(SERVER_ID);
2636  const bool& bGothash = pNym->GetNymboxHash(
2637  str_server_id, theNymboxHash); // (theNymboxHash is output.)
2638 
2639  if (!bGothash) {
2640  const OTString strNymID(theNymID); // You might ask, why create this
2641  // string and not just use
2642  // NYM_ID?
2643  // The answer is because I'm looking forward to a day soon when we
2644  // don't passconst std::string& in the first
2645  // place, and thus I can't always expect that variable will be
2646  // there.
2647  //
2648  otWarn << __FUNCTION__
2649  << ": NymboxHash not found, on client side, for server "
2650  << str_server_id << " and nym " << strNymID
2651  << ". (Returning .)\n";
2652  }
2653  else // Success: the hash was there, for that Nym, for that server ID.
2654  {
2655  OTString strOutput(theNymboxHash);
2656 
2657  std::string pBuf = strOutput.Get();
2658 
2659  return pBuf;
2660  }
2661  }
2662 
2663  return "";
2664 }
2665 
2666 // Returns RecentHash (based on ServerID)
2667 //
2669  const std::string& SERVER_ID,
2670  const std::string& NYM_ID) const // Returns RecentHash (based on ServerID)
2671 {
2672  if (NYM_ID.empty()) {
2673  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2674  OT_FAIL;
2675  }
2676  if (SERVER_ID.empty()) {
2677  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
2678  OT_FAIL;
2679  }
2680 
2681  OTIdentifier theNymID(NYM_ID);
2682  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2683 
2684  if (nullptr != pNym) {
2685  OTIdentifier theHash;
2686  const std::string str_server_id(SERVER_ID);
2687  const bool& bGothash =
2688  pNym->GetRecentHash(str_server_id, theHash); // (theHash is output.)
2689 
2690  if (!bGothash) {
2691  const OTString strNymID(theNymID); // You might ask, why create this
2692  // string and not just use
2693  // NYM_ID?
2694  // The answer is because I'm looking forward to a day soon when we
2695  // don't passconst std::string& in the first
2696  // place, and thus I can't always expect that variable will be
2697  // there.
2698  //
2699  otWarn << __FUNCTION__
2700  << ": RecentHash not found, on client side, for server "
2701  << str_server_id << " and nym " << strNymID
2702  << ". (Returning .)\n";
2703  }
2704  else // Success: the hash was there, for that Nym, for that server ID.
2705  {
2706  OTString strOutput(theHash);
2707 
2708  std::string pBuf = strOutput.Get();
2709 
2710  return pBuf;
2711  }
2712  }
2713 
2714  return "";
2715 }
2716 
2717 std::string OTAPI_Exec::GetNym_InboxHash(const std::string& ACCOUNT_ID,
2718  const std::string& NYM_ID)
2719  const // InboxHash for "most recently DOWNLOADED" Inbox
2720  // (by AccountID)
2721 {
2722  if (ACCOUNT_ID.empty()) {
2723  otErr << __FUNCTION__ << ": Null: ACOUNT_ID passed in!\n";
2724  OT_FAIL;
2725  }
2726  if (NYM_ID.empty()) {
2727  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2728  OT_FAIL;
2729  }
2730 
2731  OTIdentifier theNymID(NYM_ID);
2732  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2733 
2734  if (nullptr != pNym) {
2735  OTIdentifier theHash;
2736  const std::string str_acct_id(ACCOUNT_ID);
2737  const bool& bGothash =
2738  pNym->GetInboxHash(str_acct_id, theHash); // (theHash is output.)
2739 
2740  if (!bGothash) {
2741  const OTString strNymID(theNymID); // You might ask, why create this
2742  // string and not just use
2743  // NYM_ID?
2744  // The answer is because I'm looking forward to a day soon when we
2745  // don't passconst std::string& in the first
2746  // place, and thus I can't always expect that variable will be
2747  // there.
2748  //
2749  otWarn << __FUNCTION__
2750  << ": InboxHash not found, on client side, for account "
2751  << str_acct_id << " and nym " << strNymID
2752  << ". (Returning .)\n";
2753  }
2754  else // Success: the hash was there, for that Nym, for that server ID.
2755  {
2756  OTString strOutput(theHash);
2757 
2758  std::string pBuf = strOutput.Get();
2759 
2760  return pBuf;
2761  }
2762  }
2763 
2764  return "";
2765 }
2766 
2767 std::string OTAPI_Exec::GetNym_OutboxHash(const std::string& ACCOUNT_ID,
2768  const std::string& NYM_ID)
2769  const // OutboxHash for "most recently DOWNLOADED"
2770  // Outbox (by AccountID)
2771 {
2772  if (ACCOUNT_ID.empty()) {
2773  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
2774  OT_FAIL;
2775  }
2776  if (NYM_ID.empty()) {
2777  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2778  OT_FAIL;
2779  }
2780 
2781  OTIdentifier theNymID(NYM_ID);
2782  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2783 
2784  if (nullptr != pNym) {
2785  OTIdentifier theHash;
2786  const std::string str_acct_id(ACCOUNT_ID);
2787  const bool& bGothash =
2788  pNym->GetOutboxHash(str_acct_id, theHash); // (theHash is output.)
2789 
2790  if (!bGothash) {
2791  const OTString strNymID(theNymID); // You might ask, why create this
2792  // string and not just use
2793  // NYM_ID?
2794  // The answer is because I'm looking forward to a day soon when we
2795  // don't passconst std::string& in the first
2796  // place, and thus I can't always expect that variable will be
2797  // there.
2798  //
2799  otWarn << __FUNCTION__
2800  << ": OutboxHash not found, on client side, for account "
2801  << str_acct_id << " and nym " << strNymID
2802  << ". (Returning .)\n";
2803  }
2804  else // Success: the hash was there, for that Nym, for that server ID.
2805  {
2806  OTString strOutput(theHash);
2807 
2808  std::string pBuf = strOutput.Get();
2809 
2810  return pBuf;
2811  }
2812  }
2813 
2814  return "";
2815 }
2816 
2817 int32_t OTAPI_Exec::GetNym_MailCount(const std::string& NYM_ID) const
2818 {
2819  if (NYM_ID.empty()) {
2820  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2821  OT_FAIL;
2822  }
2823  OTIdentifier theNymID(NYM_ID);
2824  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2825  if (nullptr == pNym) return -1;
2826  return pNym->GetMailCount();
2827 }
2828 
2829 // returns the message, optionally with Subject: as first line.
2830 std::string OTAPI_Exec::GetNym_MailContentsByIndex(const std::string& NYM_ID,
2831  const int32_t& nIndex) const
2832 {
2833  if (NYM_ID.empty()) {
2834  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2835  OT_FAIL;
2836  }
2837  if (0 > nIndex) {
2838  otErr << __FUNCTION__
2839  << ": nIndex is out of bounds (it's in the negative!)\n";
2840  OT_FAIL;
2841  }
2842  OTIdentifier theNymID(NYM_ID);
2843  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2844  if (nullptr == pNym) return "";
2845  OTMessage* pMessage = pNym->GetMailByIndex(nIndex);
2846 
2847  if (nullptr != pMessage) {
2848  // SENDER: pMessage->m_strNymID
2849  // RECIPIENT: pMessage->m_strNymID2
2850  // MESSAGE: pMessage->m_ascPayload (in an OTEnvelope)
2851  //
2852  OTEnvelope theEnvelope;
2853  OTString strEnvelopeContents;
2854 
2855  // Decrypt the Envelope.
2856  if (theEnvelope.SetAsciiArmoredData(pMessage->m_ascPayload) &&
2857  theEnvelope.Open(*pNym, strEnvelopeContents)) {
2858  std::string pBuf = strEnvelopeContents.Get();
2859  return pBuf;
2860  }
2861  }
2862  return "";
2863 }
2864 
2865 // returns the sender ID for a piece of mail. (NymID).
2866 //
2867 std::string OTAPI_Exec::GetNym_MailSenderIDByIndex(const std::string& NYM_ID,
2868  const int32_t& nIndex) const
2869 {
2870  if (NYM_ID.empty()) {
2871  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2872  OT_FAIL;
2873  }
2874  if (0 > nIndex) {
2875  otErr << __FUNCTION__
2876  << ": nIndex is out of bounds (it's in the negative!)\n";
2877  OT_FAIL;
2878  }
2879  OTIdentifier theNymID(NYM_ID);
2880  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2881  if (nullptr == pNym) return "";
2882  OTMessage* pMessage = pNym->GetMailByIndex(nIndex);
2883 
2884  if (nullptr != pMessage) {
2885  // SENDER: pMessage->m_strNymID
2886  // SERVER: pMessage->m_strServerID
2887  // RECIPIENT: pMessage->m_strNymID2
2888  // MESSAGE: pMessage->m_ascPayload (in an OTEnvelope)
2889 
2890  std::string pBuf = pMessage->m_strNymID.Get();
2891  return pBuf;
2892  }
2893  return "";
2894 }
2895 
2896 // returns the server ID that a piece of mail came from.
2897 //
2898 std::string OTAPI_Exec::GetNym_MailServerIDByIndex(const std::string& NYM_ID,
2899  const int32_t& nIndex) const
2900 {
2901  if (NYM_ID.empty()) {
2902  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2903  OT_FAIL;
2904  }
2905 
2906  if (0 > nIndex) {
2907  otErr << __FUNCTION__
2908  << ": nIndex is out of bounds (it's in the negative!)\n";
2909  OT_FAIL;
2910  }
2911 
2912  OTIdentifier theNymID(NYM_ID);
2913  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2914  if (nullptr == pNym) return "";
2915  OTMessage* pMessage = pNym->GetMailByIndex(nIndex);
2916 
2917  if (nullptr != pMessage) {
2918  // SENDER: pMessage->m_strNymID
2919  // SERVER: pMessage->m_strServerID
2920  // RECIPIENT: pMessage->m_strNymID2
2921  // MESSAGE: pMessage->m_ascPayload (in an OTEnvelope)
2922 
2923  std::string pBuf = pMessage->m_strServerID.Get();
2924  return pBuf;
2925  }
2926  return "";
2927 }
2928 
2929 bool OTAPI_Exec::Nym_RemoveMailByIndex(const std::string& NYM_ID,
2930  const int32_t& nIndex) const
2931 {
2932  if (NYM_ID.empty()) {
2933  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2934  OT_FAIL;
2935  }
2936  if (0 > nIndex) {
2937  otErr << __FUNCTION__
2938  << ": nIndex is out of bounds (it's in the negative!)\n";
2939  OT_FAIL;
2940  }
2941  OTIdentifier theNymID(NYM_ID);
2942  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2943  if (nullptr == pNym) return false;
2944  OTPseudonym* pSignerNym = pNym;
2945 
2946  if (pNym->RemoveMailByIndex(nIndex)) {
2947  if (pNym->SaveSignedNymfile(*pSignerNym)) // <== save Nym to local
2948  // storage, since a mail was
2949  // erased.
2950  return true;
2951  else
2952  otErr << __FUNCTION__ << ": Error saving Nym: " << NYM_ID << "\n";
2953  }
2954  return false;
2955 }
2956 
2957 // Returns true (1) if the Sender ID on this piece of Mail (by index)
2958 // loads a public key from my wallet, and if the signature on the message
2959 // verifies with that public key.
2960 // (Not only must the signature be good, but I must have added the nym to
2961 // my wallet sometime in the past, since this func returns false if it's not
2962 // there.)
2963 //
2964 // A good wallet might be designed to automatically download any keys that
2965 // it doesn't already have, using OTAPI_Exec::checkUser(). I'll probably need to
2966 // add something to OTClient where the @checkUser response auto-saves the new
2967 // key into the wallet. That way you can wait for a tenth of a second and then
2968 // just read the Nym (by ID) straight out of your own wallet. Nifty, eh?
2969 //
2970 // All the wallet has to do is fire off a "check user" whenever this call fails,
2971 // then come back when that succeeds and try this again. If STILL failure, then
2972 // you've got a signature problem. Otherwise it'll usually download the nym
2973 // and verify the signature all in an instant, without the user even noticing
2974 // what happened.
2975 //
2976 bool OTAPI_Exec::Nym_VerifyMailByIndex(const std::string& NYM_ID,
2977  const int32_t& nIndex) const
2978 {
2979  if (NYM_ID.empty()) {
2980  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
2981  OT_FAIL;
2982  }
2983  if (0 > nIndex) {
2984  otErr << __FUNCTION__
2985  << ": nIndex is out of bounds (it's in the negative!)\n";
2986  OT_FAIL;
2987  }
2988  OTIdentifier theNymID(NYM_ID);
2989  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
2990  if (nullptr == pNym) return false;
2991  OTMessage* pMessage = pNym->GetMailByIndex(nIndex);
2992 
2993  if (nullptr != pMessage) {
2994  // Grab the NymID of the sender.
2995  const OTIdentifier theSenderNymID(pMessage->m_strNymID);
2996 
2997  // Grab a pointer to that Nym (if its public key is in my wallet.)
2998  OTPseudonym* pSenderNym = OTAPI()->GetNym(theSenderNymID, __FUNCTION__);
2999 
3000  // If it's there, use it to verify the signature on the message.
3001  // return true if successful signature verification.
3002  //
3003  if (nullptr != pSenderNym) {
3004  if (pMessage->VerifySignature(*pSenderNym)) return true;
3005  }
3006  }
3007  return false;
3008 }
3009 
3010 //
3011 // OUTMAIL!!
3012 
3013 int32_t OTAPI_Exec::GetNym_OutmailCount(const std::string& NYM_ID) const
3014 {
3015  if (NYM_ID.empty()) {
3016  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3017  OT_FAIL;
3018  }
3019  OTIdentifier theNymID(NYM_ID);
3020  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3021  if (nullptr == pNym) return -1;
3022  return pNym->GetOutmailCount();
3023 }
3024 
3025 // returns the message, optionally with Subject: as first line.
3027  const std::string& NYM_ID, const int32_t& nIndex) const
3028 {
3029  if (NYM_ID.empty()) {
3030  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3031  OT_FAIL;
3032  }
3033  if (0 > nIndex) {
3034  otErr << __FUNCTION__
3035  << ": nIndex is out of bounds (it's in the negative!)\n";
3036  OT_FAIL;
3037  }
3038  OTIdentifier theNymID(NYM_ID);
3039  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3040  if (nullptr == pNym) return "";
3041  OTMessage* pMessage = pNym->GetOutmailByIndex(nIndex);
3042  if (nullptr != pMessage) {
3043  // SENDER: pMessage->m_strNymID
3044  // RECIPIENT: pMessage->m_strNymID2
3045  // MESSAGE: pMessage->m_ascPayload (in an OTEnvelope)
3046  OTString strMailContents;
3047 
3048  if (pMessage->m_ascPayload.Exists() &&
3049  pMessage->m_ascPayload.GetString(strMailContents)) {
3050  std::string pBuf = strMailContents.Get();
3051  return pBuf;
3052  }
3053  }
3054  return "";
3055 }
3056 
3057 // returns the recipient ID for a piece of mail. (NymID).
3058 //
3060  const std::string& NYM_ID, const int32_t& nIndex) const
3061 {
3062  if (NYM_ID.empty()) {
3063  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3064  OT_FAIL;
3065  }
3066  if (0 > nIndex) {
3067  otErr << __FUNCTION__
3068  << ": nIndex is out of bounds (it's in the negative!)\n";
3069  OT_FAIL;
3070  }
3071  OTIdentifier theNymID(NYM_ID);
3072  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3073  if (nullptr == pNym) return "";
3074  OTMessage* pMessage = pNym->GetOutmailByIndex(nIndex);
3075  if (nullptr != pMessage) {
3076  // SENDER: pMessage->m_strNymID
3077  // SERVER: pMessage->m_strServerID
3078  // RECIPIENT: pMessage->m_strNymID2
3079  // MESSAGE: pMessage->m_ascPayload
3080 
3081  std::string pBuf = pMessage->m_strNymID2.Get();
3082  return pBuf;
3083  }
3084  return "";
3085 }
3086 
3087 // returns the server ID that a piece of mail came from.
3088 //
3090  const std::string& NYM_ID, const int32_t& nIndex) const
3091 {
3092  if (NYM_ID.empty()) {
3093  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3094  OT_FAIL;
3095  }
3096  if (0 > nIndex) {
3097  otErr << __FUNCTION__
3098  << ": nIndex is out of bounds (it's in the negative!)\n";
3099  OT_FAIL;
3100  }
3101  OTIdentifier theNymID(NYM_ID);
3102  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3103  if (nullptr == pNym) return "";
3104  OTMessage* pMessage = pNym->GetOutmailByIndex(nIndex);
3105 
3106  if (nullptr != pMessage) {
3107  // SENDER: pMessage->m_strNymID
3108  // SERVER: pMessage->m_strServerID
3109  // RECIPIENT: pMessage->m_strNymID2
3110  // MESSAGE: pMessage->m_ascPayload
3111 
3112  std::string pBuf = pMessage->m_strServerID.Get();
3113  return pBuf;
3114  }
3115  return "";
3116 }
3117 
3118 bool OTAPI_Exec::Nym_RemoveOutmailByIndex(const std::string& NYM_ID,
3119  const int32_t& nIndex) const
3120 {
3121  if (NYM_ID.empty()) {
3122  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3123  OT_FAIL;
3124  }
3125  if (0 > nIndex) {
3126  otErr << __FUNCTION__
3127  << ": nIndex is out of bounds (it's in the negative!)\n";
3128  OT_FAIL;
3129  }
3130  OTIdentifier theNymID(NYM_ID);
3131  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3132  if (nullptr == pNym) return false;
3133  OTPseudonym* pSignerNym = pNym;
3134 
3135  if (pNym->RemoveOutmailByIndex(nIndex)) {
3136  if (pNym->SaveSignedNymfile(*pSignerNym)) // <== save Nym to local
3137  // storage, since a mail was
3138  // erased.
3139  return true;
3140  else
3141  otErr << __FUNCTION__ << ": Error saving Nym: " << NYM_ID << "\n";
3142  }
3143  return false;
3144 }
3145 
3146 // Returns true (1) if the Sender ID on this piece of Mail (by index)
3147 // loads a public key from my wallet, and if the signature on the message
3148 // verifies with that public key.
3149 // (Not only must the signature be good, but I must have added the nym to
3150 // my wallet sometime in the past, since this func returns false if it's not
3151 // there.)
3152 //
3153 // A good wallet might be designed to automatically download any keys that
3154 // it doesn't already have, using OTAPI_Exec::checkUser(). I'll probably need to
3155 // add something to OTClient where the @checkUser response auto-saves the new
3156 // key into the wallet. That way you can wait for a tenth of a second and then
3157 // just read the Nym (by ID) straight out of your own wallet. Nifty, eh?
3158 //
3159 // All the wallet has to do is fire off a "check user" whenever this call fails,
3160 // then come back when that succeeds and try this again. If STILL failure, then
3161 // you've got a signature problem. Otherwise it'll usually download the nym
3162 // and verify the signature all in an instant, without the user even noticing
3163 // what happened.
3164 //
3165 bool OTAPI_Exec::Nym_VerifyOutmailByIndex(const std::string& NYM_ID,
3166  const int32_t& nIndex) const
3167 {
3168  if (NYM_ID.empty()) {
3169  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3170  OT_FAIL;
3171  }
3172  if (0 > nIndex) {
3173  otErr << __FUNCTION__
3174  << ": nIndex is out of bounds (it's in the negative!)\n";
3175  OT_FAIL;
3176  }
3177  OTIdentifier theNymID(NYM_ID);
3178  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3179  if (nullptr == pNym) return false;
3180  OTMessage* pMessage = pNym->GetOutmailByIndex(nIndex);
3181  if (nullptr != pMessage) {
3182  // Grab the NymID of the sender.
3183  const OTIdentifier theSenderNymID(pMessage->m_strNymID);
3184 
3185  // Grab a pointer to that Nym (if its public key is in my wallet.)
3186  OTPseudonym* pSenderNym = OTAPI()->GetNym(theSenderNymID, __FUNCTION__);
3187 
3188  // If it's there, use it to verify the signature on the message.
3189  // return true if successful signature verification.
3190  //
3191  if (nullptr != pSenderNym) {
3192  if (pMessage->VerifySignature(*pSenderNym)) return true;
3193  }
3194  }
3195  return false;
3196 }
3197 
3198 //
3199 // OUTPAYMENTS!!
3200 //
3201 // (Outbox on payments screen.)
3202 //
3203 // Todo: Move these and all functions to OpenTransactions.cpp. This should ONLY
3204 // be a wrapper for that class. That way we can eventually phase this file out
3205 // entirely and replace it with OTAPI_Wrapper.cpp directly on
3206 // OpenTransactions.cpp
3207 
3208 int32_t OTAPI_Exec::GetNym_OutpaymentsCount(const std::string& NYM_ID) const
3209 {
3210  if (NYM_ID.empty()) {
3211  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3212  OT_FAIL;
3213  }
3214  OTIdentifier theNymID(NYM_ID);
3215  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3216  if (nullptr == pNym) return -1;
3217  return pNym->GetOutpaymentsCount();
3218 }
3219 
3220 // Returns the payment instrument that was sent.
3221 //
3223  const std::string& NYM_ID, const int32_t& nIndex) const
3224 {
3225  if (NYM_ID.empty()) {
3226  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3227  OT_FAIL;
3228  }
3229  if (0 > nIndex) {
3230  otErr << __FUNCTION__
3231  << ": nIndex is out of bounds (it's in the negative!)\n";
3232  OT_FAIL;
3233  }
3234  OTIdentifier theNymID(NYM_ID);
3235  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3236  if (nullptr == pNym) return "";
3237  OTMessage* pMessage = pNym->GetOutpaymentsByIndex(nIndex);
3238  if (nullptr != pMessage) {
3239  // SENDER: pMessage->m_strNymID
3240  // RECIPIENT: pMessage->m_strNymID2
3241  // INSTRUMENT: pMessage->m_ascPayload (in an OTEnvelope)
3242  OTString strPayment;
3243 
3244  // There isn't any encrypted envelope this time, since it's my
3245  // outPayments box.
3246  //
3247  if (pMessage->m_ascPayload.Exists() &&
3248  pMessage->m_ascPayload.GetString(strPayment) &&
3249  strPayment.Exists()) {
3250  OTPayment thePayment(strPayment);
3251  if (thePayment.IsValid()) {
3252  std::string pBuf = strPayment.Get();
3253  return pBuf;
3254  }
3255  }
3256  }
3257  return "";
3258 }
3259 
3260 // returns the recipient ID for a piece of payments outmail. (NymID).
3261 //
3263  const std::string& NYM_ID, const int32_t& nIndex) const
3264 {
3265  if (NYM_ID.empty()) {
3266  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3267  OT_FAIL;
3268  }
3269  if (0 > nIndex) {
3270  otErr << __FUNCTION__
3271  << ": nIndex is out of bounds (it's in the negative!)\n";
3272  OT_FAIL;
3273  }
3274  OTIdentifier theNymID(NYM_ID);
3275  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3276  if (nullptr == pNym) return "";
3277  OTMessage* pMessage = pNym->GetOutpaymentsByIndex(nIndex);
3278  if (nullptr != pMessage) {
3279  // SENDER: pMessage->m_strNymID
3280  // SERVER: pMessage->m_strServerID
3281  // RECIPIENT: pMessage->m_strNymID2
3282  // MESSAGE: pMessage->m_ascPayload
3283 
3284  std::string pBuf = pMessage->m_strNymID2.Get();
3285  return pBuf;
3286  }
3287  return "";
3288 }
3289 
3290 // returns the server ID that a piece of payments outmail came from.
3291 //
3293  const std::string& NYM_ID, const int32_t& nIndex) const
3294 {
3295  if (NYM_ID.empty()) {
3296  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3297  OT_FAIL;
3298  }
3299  if (0 > nIndex) {
3300  otErr << __FUNCTION__
3301  << ": nIndex is out of bounds (it's in the negative!)\n";
3302  OT_FAIL;
3303  }
3304  OTIdentifier theNymID(NYM_ID);
3305  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3306  if (nullptr == pNym) return "";
3307  OTMessage* pMessage = pNym->GetOutpaymentsByIndex(nIndex);
3308 
3309  if (nullptr != pMessage) {
3310  // SENDER: pMessage->m_strNymID
3311  // SERVER: pMessage->m_strServerID
3312  // RECIPIENT: pMessage->m_strNymID2
3313  // MESSAGE: pMessage->m_ascPayload
3314 
3315  int32_t bServerIdLength = pMessage->m_strServerID.GetLength();
3316  if (1 >= bServerIdLength) {
3317  otErr << __FUNCTION__ << ": m_strServerID Length is 1 or less!\n";
3318  OT_FAIL;
3319  }
3320 
3321  std::string pBuf = pMessage->m_strServerID.Get();
3322  return pBuf;
3323  }
3324  return "";
3325 }
3326 
3327 bool OTAPI_Exec::Nym_RemoveOutpaymentsByIndex(const std::string& NYM_ID,
3328  const int32_t& nIndex) const
3329 {
3330  if (NYM_ID.empty()) {
3331  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3332  OT_FAIL;
3333  }
3334  if (0 > nIndex) {
3335  otErr << __FUNCTION__
3336  << ": nIndex is out of bounds (it's in the negative!)\n";
3337  OT_FAIL;
3338  }
3339 
3340  OTIdentifier theNymID(NYM_ID);
3341  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3342  if (nullptr == pNym) return false;
3343  OTPseudonym* pSignerNym = pNym;
3344 
3345  if (pNym->RemoveOutpaymentsByIndex(nIndex)) {
3346  if (pNym->SaveSignedNymfile(*pSignerNym)) // <== save Nym to local
3347  // storage, since a payment
3348  // outmail was erased.
3349  return true;
3350  else
3351  otErr << __FUNCTION__ << ": Error saving Nym: " << NYM_ID << "\n";
3352  }
3353  return false;
3354 }
3355 
3356 // Returns true (1) if the Sender ID on this piece of Mail (by index)
3357 // loads a public key from my wallet, and if the signature on the message
3358 // verifies with that public key.
3359 // (Not only must the signature be good, but I must have added the nym to
3360 // my wallet sometime in the past, since this func returns false if it's not
3361 // there.)
3362 //
3363 // A good wallet might be designed to automatically download any keys that
3364 // it doesn't already have, using OTAPI_Exec::checkUser(). I'll probably need to
3365 // add something to OTClient where the @checkUser response auto-saves the new
3366 // key into the wallet. That way you can wait for a tenth of a second and then
3367 // just read the Nym (by ID) straight out of your own wallet. Nifty, eh?
3368 //
3369 // All the wallet has to do is fire off a "check user" whenever this call fails,
3370 // then come back when that succeeds and try this again. If STILL failure, then
3371 // you've got a signature problem. Otherwise it'll usually download the nym
3372 // and verify the signature all in an instant, without the user even noticing
3373 // what happened.
3374 //
3375 bool OTAPI_Exec::Nym_VerifyOutpaymentsByIndex(const std::string& NYM_ID,
3376  const int32_t& nIndex) const
3377 {
3378  if (NYM_ID.empty()) {
3379  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3380  OT_FAIL;
3381  }
3382  if (0 > nIndex) {
3383  otErr << __FUNCTION__
3384  << ": nIndex is out of bounds (it's in the negative!)\n";
3385  OT_FAIL;
3386  }
3387  OTIdentifier theNymID(NYM_ID);
3388  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
3389  if (nullptr == pNym) return false;
3390  OTMessage* pMessage = pNym->GetOutpaymentsByIndex(nIndex);
3391  if (nullptr != pMessage) {
3392  // Grab the NymID of the sender.
3393  const OTIdentifier theSenderNymID(pMessage->m_strNymID);
3394 
3395  // Grab a pointer to that Nym (if its public key is in my wallet.)
3396  OTPseudonym* pSenderNym = OTAPI()->GetNym(theSenderNymID, __FUNCTION__);
3397 
3398  // If it's there, use it to verify the signature on the message.
3399  // return true if successful signature verification.
3400  //
3401  if (nullptr != pSenderNym) {
3402  if (pMessage->VerifySignature(*pSenderNym)) return true;
3403  }
3404  }
3405  return false;
3406 }
3407 
3408 //
3409 //
3410 // THESE FUNCTIONS were added for the PAYMENTS screen. (They are fairly new.)
3411 //
3412 // Basically there was a need to have DIFFERENT instruments, but to be able to
3413 // treat them as though they are a single type.
3414 //
3415 // In keeping with that, the below functions will work with disparate types.
3416 // You can pass [ CHEQUES / VOUCHERS / INVOICES ] and PAYMENT PLANS, and
3417 // SMART CONTRACTS, and PURSEs into these functions, and they should be able
3418 // to handle any of those types.
3419 //
3420 //
3421 
3422 int64_t OTAPI_Exec::Instrmnt_GetAmount(const std::string& THE_INSTRUMENT) const
3423 {
3424  if (THE_INSTRUMENT.empty()) {
3425  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3426  OT_FAIL;
3427  }
3428  const OTString strInstrument(THE_INSTRUMENT);
3429  OTPayment thePayment(strInstrument);
3430 
3431  if (!thePayment.IsValid()) {
3432  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3433  << strInstrument << "\n\n";
3434  return -1;
3435  }
3436  const bool& bSetValues = thePayment.SetTempValues();
3437  if (!bSetValues) {
3438  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3439  << strInstrument << "\n\n";
3440  return -1;
3441  }
3442  // BY THIS POINT, we have definitely loaded up all the values of the
3443  // instrument
3444  // into the OTPayment object. (Meaning we can now return the requested
3445  // data...)
3446 
3447  int64_t lOutput = 0;
3448  return thePayment.GetAmount(lOutput) ? lOutput : OT_ERROR_AMOUNT;
3449 }
3450 
3452  const std::string& THE_INSTRUMENT) const
3453 {
3454  if (THE_INSTRUMENT.empty()) {
3455  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3456  OT_FAIL;
3457  }
3458  const OTString strInstrument(THE_INSTRUMENT);
3459  OTPayment thePayment(strInstrument);
3460 
3461  if (!thePayment.IsValid()) {
3462  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3463  << strInstrument << "\n\n";
3464  return -1;
3465  }
3466  const bool& bSetValues = thePayment.SetTempValues();
3467  if (!bSetValues) {
3468  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3469  << strInstrument << "\n\n";
3470  return -1;
3471  }
3472  // BY THIS POINT, we have definitely loaded up all the values of the
3473  // instrument
3474  // into the OTPayment object. (Meaning we can now return the requested
3475  // data...)
3476  OTString strOutput;
3477  int64_t lOutput = 0;
3478  const bool& bGotData = thePayment.GetTransactionNum(lOutput); // <========
3479 
3480  return bGotData ? lOutput : -1;
3481 }
3482 
3484  const std::string& THE_INSTRUMENT) const
3485 {
3486  if (THE_INSTRUMENT.empty()) {
3487  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3488  OT_FAIL;
3489  }
3490  const OTString strInstrument(THE_INSTRUMENT);
3491  OTPayment thePayment(strInstrument);
3492 
3493  if (!thePayment.IsValid()) {
3494  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3495  << strInstrument << "\n\n";
3496  return OTTimeGetTimeFromSeconds(-1);
3497  }
3498  const bool& bSetValues = thePayment.SetTempValues();
3499  if (!bSetValues) {
3500  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3501  << strInstrument << "\n\n";
3502  return OTTimeGetTimeFromSeconds(-1);
3503  }
3504 
3505  // BY THIS POINT, we have definitely loaded up all the values of the
3506  // instrument
3507  // into the OTPayment object. (Meaning we can now return the requested
3508  // data...)
3509 
3510  OTString strOutput;
3511  time64_t tOutput = OT_TIME_ZERO;
3512  const bool& bGotData = thePayment.GetValidFrom(tOutput); // <========
3513 
3514  return bGotData ? tOutput : OTTimeGetTimeFromSeconds(-1);
3515 }
3516 
3518  const std::string& THE_INSTRUMENT) const
3519 {
3520  if (THE_INSTRUMENT.empty()) {
3521  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3522  OT_FAIL;
3523  }
3524  const OTString strInstrument(THE_INSTRUMENT);
3525  OTPayment thePayment(strInstrument);
3526 
3527  if (!thePayment.IsValid()) {
3528  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3529  << strInstrument << "\n\n";
3530  return OTTimeGetTimeFromSeconds(-1);
3531  }
3532  const bool& bSetValues = thePayment.SetTempValues();
3533  if (!bSetValues) {
3534  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3535  << strInstrument << "\n\n";
3536  return OTTimeGetTimeFromSeconds(-1);
3537  }
3538 
3539  // BY THIS POINT, we have definitely loaded up all the values of the
3540  // instrument
3541  // into the OTPayment object. (Meaning we can now return the requested
3542  // data...)
3543 
3544  OTString strOutput;
3545  time64_t tOutput = OT_TIME_ZERO;
3546  const bool& bGotData = thePayment.GetValidTo(tOutput); // <========
3547 
3548  return bGotData ? tOutput : OTTimeGetTimeFromSeconds(-1);
3549 }
3550 
3552  const std::string& THE_INSTRUMENT) const
3553 {
3554  if (THE_INSTRUMENT.empty()) {
3555  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3556  OT_FAIL;
3557  }
3558  const OTString strInstrument(THE_INSTRUMENT);
3559  OTPayment thePayment(strInstrument);
3560 
3561  if (!thePayment.IsValid()) {
3562  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3563  << strInstrument << "\n\n";
3564  return "";
3565  }
3566  const bool& bSetValues = thePayment.SetTempValues();
3567  if (!bSetValues) {
3568  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3569  << strInstrument << "\n\n";
3570  return "";
3571  }
3572  // BY THIS POINT, we have definitely loaded up all the values of the
3573  // instrument
3574  // into the OTPayment object. (Meaning we can now return the requested
3575  // data...)
3576 
3577  const OTString strOutput(thePayment.GetTypeString());
3578 
3579  if (strOutput.Exists()) {
3580  std::string pBuf = strOutput.Get();
3581 
3582  return pBuf;
3583  }
3584 
3585  return "";
3586 }
3587 
3589  const std::string& THE_INSTRUMENT) const
3590 {
3591  if (THE_INSTRUMENT.empty()) {
3592  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3593  OT_FAIL;
3594  }
3595  const OTString strInstrument(THE_INSTRUMENT);
3596  OTPayment thePayment(strInstrument);
3597 
3598  if (!thePayment.IsValid()) {
3599  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3600  << strInstrument << "\n\n";
3601  return "";
3602  }
3603  const bool& bSetValues = thePayment.SetTempValues();
3604  if (!bSetValues) {
3605  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3606  << strInstrument << "\n\n";
3607  return "";
3608  }
3609 
3610  // BY THIS POINT, we have definitely loaded up all the values of the
3611  // instrument
3612  // into the OTPayment object. (Meaning we can now return the requested
3613  // data...)
3614 
3615  OTString strOutput;
3616  const bool& bGotData = thePayment.GetMemo(strOutput); // <========
3617 
3618  if (bGotData) {
3619  std::string pBuf = strOutput.Get();
3620  return pBuf;
3621  }
3622 
3623  return "";
3624 }
3625 
3627  const std::string& THE_INSTRUMENT) const
3628 {
3629  if (THE_INSTRUMENT.empty()) {
3630  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3631  OT_FAIL;
3632  }
3633  const OTString strInstrument(THE_INSTRUMENT);
3634  OTPayment thePayment(strInstrument);
3635 
3636  if (!thePayment.IsValid()) {
3637  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3638  << strInstrument << "\n\n";
3639  return "";
3640  }
3641  const bool& bSetValues = thePayment.SetTempValues();
3642  if (!bSetValues) {
3643  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3644  << strInstrument << "\n\n";
3645  return "";
3646  }
3647 
3648  // BY THIS POINT, we have definitely loaded up all the values of the
3649  // instrument
3650  // into the OTPayment object. (Meaning we can now return the requested
3651  // data...)
3652 
3653  OTIdentifier theOutput;
3654  const bool& bGotData = thePayment.GetServerID(theOutput); // <========
3655 
3656  if (bGotData) {
3657  const OTString strOutput(theOutput);
3658  std::string pBuf = strOutput.Get();
3659  return pBuf;
3660  }
3661 
3662  return "";
3663 }
3664 
3666  const std::string& THE_INSTRUMENT) const
3667 {
3668  if (THE_INSTRUMENT.empty()) {
3669  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3670  OT_FAIL;
3671  }
3672  const OTString strInstrument(THE_INSTRUMENT);
3673  OTPayment thePayment(strInstrument);
3674 
3675  if (!thePayment.IsValid()) {
3676  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3677  << strInstrument << "\n\n";
3678  return "";
3679  }
3680  const bool& bSetValues = thePayment.SetTempValues();
3681  if (!bSetValues) {
3682  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3683  << strInstrument << "\n\n";
3684  return "";
3685  }
3686 
3687  // BY THIS POINT, we have definitely loaded up all the values of the
3688  // instrument
3689  // into the OTPayment object. (Meaning we can now return the requested
3690  // data...)
3691 
3692  OTIdentifier theOutput;
3693  const bool& bGotData = thePayment.GetAssetTypeID(theOutput); // <========
3694 
3695  if (bGotData) {
3696  const OTString strOutput(theOutput);
3697  std::string pBuf = strOutput.Get();
3698  return pBuf;
3699  }
3700 
3701  return "";
3702 }
3703 
3705  const std::string& THE_INSTRUMENT) const
3706 {
3707  if (THE_INSTRUMENT.empty()) {
3708  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3709  OT_FAIL;
3710  }
3711  const OTString strInstrument(THE_INSTRUMENT);
3712  OTPayment thePayment(strInstrument);
3713 
3714  if (!thePayment.IsValid()) {
3715  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3716  << strInstrument << "\n\n";
3717  return "";
3718  }
3719  const bool& bSetValues = thePayment.SetTempValues();
3720  if (!bSetValues) {
3721  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3722  << strInstrument << "\n\n";
3723  return "";
3724  }
3725 
3726  // BY THIS POINT, we have definitely loaded up all the values of the
3727  // instrument
3728  // into the OTPayment object. (Meaning we can now return the requested
3729  // data...)
3730 
3731  OTIdentifier theOutput;
3732  const bool& bGotData = thePayment.GetRemitterUserID(theOutput); // <========
3733 
3734  if (bGotData) {
3735  const OTString strOutput(theOutput);
3736  std::string pBuf = strOutput.Get();
3737  return pBuf;
3738  }
3739 
3740  return "";
3741 }
3742 
3744  const std::string& THE_INSTRUMENT) const
3745 {
3746  if (THE_INSTRUMENT.empty()) {
3747  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3748  OT_FAIL;
3749  }
3750  const OTString strInstrument(THE_INSTRUMENT);
3751  OTPayment thePayment(strInstrument);
3752 
3753  if (!thePayment.IsValid()) {
3754  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3755  << strInstrument << "\n\n";
3756  return "";
3757  }
3758  const bool& bSetValues = thePayment.SetTempValues();
3759  if (!bSetValues) {
3760  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3761  << strInstrument << "\n\n";
3762  return "";
3763  }
3764 
3765  // BY THIS POINT, we have definitely loaded up all the values of the
3766  // instrument
3767  // into the OTPayment object. (Meaning we can now return the requested
3768  // data...)
3769 
3770  OTIdentifier theOutput;
3771  const bool& bGotData = thePayment.GetRemitterAcctID(theOutput); // <========
3772 
3773  if (bGotData) {
3774  const OTString strOutput(theOutput);
3775  std::string pBuf = strOutput.Get();
3776  return pBuf;
3777  }
3778 
3779  return "";
3780 }
3781 
3783  const std::string& THE_INSTRUMENT) const
3784 {
3785  if (THE_INSTRUMENT.empty()) {
3786  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3787  OT_FAIL;
3788  }
3789  const OTString strInstrument(THE_INSTRUMENT);
3790  OTPayment thePayment(strInstrument);
3791 
3792  if (!thePayment.IsValid()) {
3793  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3794  << strInstrument << "\n\n";
3795  return "";
3796  }
3797  const bool& bSetValues = thePayment.SetTempValues();
3798  if (!bSetValues) {
3799  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3800  << strInstrument << "\n\n";
3801  return "";
3802  }
3803 
3804  // BY THIS POINT, we have definitely loaded up all the values of the
3805  // instrument
3806  // into the OTPayment object. (Meaning we can now return the requested
3807  // data...)
3808 
3809  OTIdentifier theOutput;
3810  const bool& bGotData = thePayment.GetSenderUserID(theOutput); // <========
3811 
3812  if (bGotData) {
3813  const OTString strOutput(theOutput);
3814  std::string pBuf = strOutput.Get();
3815  return pBuf;
3816  }
3817 
3818  return "";
3819 }
3820 
3822  const std::string& THE_INSTRUMENT) const
3823 {
3824  if (THE_INSTRUMENT.empty()) {
3825  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3826  OT_FAIL;
3827  }
3828  const OTString strInstrument(THE_INSTRUMENT);
3829  OTPayment thePayment(strInstrument);
3830 
3831  if (!thePayment.IsValid()) {
3832  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3833  << strInstrument << "\n\n";
3834  return "";
3835  }
3836  const bool& bSetValues = thePayment.SetTempValues();
3837  if (!bSetValues) {
3838  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3839  << strInstrument << "\n\n";
3840  return "";
3841  }
3842 
3843  // BY THIS POINT, we have definitely loaded up all the values of the
3844  // instrument
3845  // into the OTPayment object. (Meaning we can now return the requested
3846  // data...)
3847 
3848  OTIdentifier theOutput;
3849  const bool& bGotData = thePayment.GetSenderAcctID(theOutput); // <========
3850 
3851  if (bGotData) {
3852  const OTString strOutput(theOutput);
3853  std::string pBuf = strOutput.Get();
3854  return pBuf;
3855  }
3856 
3857  return "";
3858 }
3859 
3861  const std::string& THE_INSTRUMENT) const
3862 {
3863  if (THE_INSTRUMENT.empty()) {
3864  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3865  OT_FAIL;
3866  }
3867  const OTString strInstrument(THE_INSTRUMENT);
3868  OTPayment thePayment(strInstrument);
3869 
3870  if (!thePayment.IsValid()) {
3871  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3872  << strInstrument << "\n\n";
3873  return "";
3874  }
3875  const bool& bSetValues = thePayment.SetTempValues();
3876  if (!bSetValues) {
3877  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3878  << strInstrument << "\n\n";
3879  return "";
3880  }
3881 
3882  // BY THIS POINT, we have definitely loaded up all the values of the
3883  // instrument
3884  // into the OTPayment object. (Meaning we can now return the requested
3885  // data...)
3886 
3887  OTIdentifier theOutput;
3888  const bool& bGotData =
3889  thePayment.GetRecipientUserID(theOutput); // <========
3890 
3891  if (bGotData) {
3892  const OTString strOutput(theOutput);
3893  std::string pBuf = strOutput.Get();
3894  return pBuf;
3895  }
3896 
3897  return "";
3898 }
3899 
3901  const std::string& THE_INSTRUMENT) const
3902 {
3903  if (THE_INSTRUMENT.empty()) {
3904  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
3905  OT_FAIL;
3906  }
3907  const OTString strInstrument(THE_INSTRUMENT);
3908  OTPayment thePayment(strInstrument);
3909 
3910  if (!thePayment.IsValid()) {
3911  otOut << __FUNCTION__ << ": Unable to parse instrument:\n\n"
3912  << strInstrument << "\n\n";
3913  return "";
3914  }
3915  const bool& bSetValues = thePayment.SetTempValues();
3916  if (!bSetValues) {
3917  otOut << __FUNCTION__ << ": Unable to load instrument:\n\n"
3918  << strInstrument << "\n\n";
3919  return "";
3920  }
3921  // BY THIS POINT, we have definitely loaded up all the values of the
3922  // instrument
3923  // into the OTPayment object. (Meaning we can now return the requested
3924  // data...)
3925 
3926  OTIdentifier theOutput;
3927  const bool& bGotData =
3928  thePayment.GetRecipientAcctID(theOutput); // <========
3929 
3930  if (bGotData) {
3931  const OTString strOutput(theOutput);
3932  std::string pBuf = strOutput.Get();
3933  return pBuf;
3934  }
3935 
3936  return "";
3937 }
3938 
3939 // SET NYM NAME
3940 //
3941 // You might have 40 of your friends' public nyms in
3942 // your wallet. You might have labels on each of them.
3943 // But whenever you change a label (and thus re-sign the
3944 // file for that Nym when you save it), you only SIGN
3945 // using one of your OWN nyms, for which you have a private
3946 // key available for signing.
3947 //
3948 // When testing, there is only one nym, so you just pass it
3949 // twice. But in real production, a user will have a default
3950 // signing nym, the same way that he might have a default
3951 // signing key in PGP, and that must be passed in whenever
3952 // he changes the name on any of the other nyms in his wallet.
3953 // (In order to properly sign and save the change.)
3954 //
3955 // Returns true (1) or false (0)
3956 //
3957 bool OTAPI_Exec::SetNym_Name(const std::string& NYM_ID,
3958  const std::string& SIGNER_NYM_ID,
3959  const std::string& NYM_NEW_NAME) const
3960 {
3961  if (NYM_ID.empty()) {
3962  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
3963  OT_FAIL;
3964  }
3965  if (SIGNER_NYM_ID.empty()) {
3966  otErr << __FUNCTION__ << ": Null: SINGER_NYM_ID passed in!\n";
3967  OT_FAIL;
3968  }
3969  if (NYM_NEW_NAME.empty()) {
3970  otErr << __FUNCTION__ << ": Null: NYM_NEW_NAME passed in!\n";
3971  OT_FAIL;
3972  }
3973 
3974  const OTIdentifier theNymID(NYM_ID), theSignerNymID(SIGNER_NYM_ID);
3975  const OTString strNymName(NYM_NEW_NAME);
3976 
3977  bool bSuccess = OTAPI()->SetNym_Name(theNymID, theSignerNymID, strNymName);
3978 
3979  return bSuccess;
3980 }
3981 
3982 // Merely a client-side label
3983 bool OTAPI_Exec::SetServer_Name(const std::string& SERVER_ID,
3984  const std::string& STR_NEW_NAME) const
3985 {
3986  if (SERVER_ID.empty()) {
3987  otErr << __FUNCTION__ << ": Null SERVER_ID passed in!\n";
3988  OT_FAIL;
3989  }
3990  if (STR_NEW_NAME.empty()) {
3991  otErr << __FUNCTION__ << ": Null STR_NEW_NAME passed in!\n";
3992  OT_FAIL;
3993  }
3994 
3995  const OTIdentifier theContractID(SERVER_ID);
3996  const OTString strNewName(STR_NEW_NAME);
3997 
3998  bool bSuccess = OTAPI()->SetServer_Name(theContractID, strNewName);
3999 
4000  return bSuccess;
4001 }
4002 
4003 // Merely a client-side label
4004 bool OTAPI_Exec::SetAssetType_Name(const std::string& ASSET_ID,
4005  const std::string& STR_NEW_NAME) const
4006 {
4007  if (ASSET_ID.empty()) {
4008  otErr << __FUNCTION__ << ": Null: ASSET_ID passed in!\n";
4009  OT_FAIL;
4010  }
4011  if (STR_NEW_NAME.empty()) {
4012  otErr << __FUNCTION__ << ": Null: STR_NEW_NAME passed in!\n";
4013  OT_FAIL;
4014  }
4015 
4016  const OTIdentifier theContractID(ASSET_ID);
4017  const OTString strNewName(STR_NEW_NAME);
4018 
4019  bool bSuccess = OTAPI()->SetAssetType_Name(theContractID, strNewName);
4020 
4021  return bSuccess;
4022 }
4023 
4024 // GET NYM TRANSACTION NUM COUNT
4025 // How many transaction numbers does the Nym have (for a given server?)
4026 //
4027 // This function returns the count of numbers available. If 0, then no
4028 // transactions will work until you call OTAPI_Exec::getTransactionNumber()
4029 // to replenish your Nym's supply for that ServerID...
4030 //
4031 // Returns a count (0 through N numbers available),
4032 // or -1 for error (no nym found.)
4033 //
4034 int32_t OTAPI_Exec::GetNym_TransactionNumCount(const std::string& SERVER_ID,
4035  const std::string& NYM_ID) const
4036 {
4037  if (SERVER_ID.empty()) {
4038  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
4039  OT_FAIL;
4040  }
4041  if (NYM_ID.empty()) {
4042  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
4043  OT_FAIL;
4044  }
4045 
4046  OTIdentifier theServerID(SERVER_ID);
4047  OTIdentifier theNymID(NYM_ID);
4048 
4049  int32_t nReturnValue = 0;
4050  OTPseudonym* pNym = OTAPI()->GetNym(theNymID, __FUNCTION__);
4051 
4052  if (nullptr != pNym)
4053  nReturnValue = pNym->GetTransactionNumCount(theServerID);
4054  else
4055  nReturnValue = -1;
4056 
4057  return nReturnValue;
4058 }
4059 
4060 // based on Index (above 4 functions) this returns the Server's ID
4061 std::string OTAPI_Exec::GetServer_ID(const int32_t& nIndex) const
4062 {
4063  if (0 > nIndex) {
4064  otErr << __FUNCTION__
4065  << ": nIndex is out of bounds (it's in the negative!)\n";
4066  OT_FAIL;
4067  }
4068 
4069  OTIdentifier theID;
4070  OTString strName;
4071  bool bGetServer = OTAPI()->GetServer(nIndex, theID, strName);
4072 
4073  if (bGetServer) {
4074  OTString strID(theID);
4075 
4076  std::string pBuf = strID.Get();
4077 
4078  return pBuf;
4079  }
4080  return "";
4081 }
4082 
4083 // Return's Server's name (based on server ID)
4084 std::string OTAPI_Exec::GetServer_Name(const std::string& THE_ID) const
4085 {
4086  if (THE_ID.empty()) {
4087  otErr << __FUNCTION__ << ": Null: THE_ID passed in!\n";
4088  OT_FAIL;
4089  }
4090  OTIdentifier theID(THE_ID);
4091 
4092  OTServerContract* pServer = OTAPI()->GetServer(theID, __FUNCTION__);
4093  if (nullptr == pServer) return "";
4094  OTString strName;
4095  pServer->GetName(strName);
4096  std::string pBuf = strName.Get();
4097 
4098  return pBuf;
4099 }
4100 
4101 // returns Asset Type ID (based on index from GetAssetTypeCount)
4102 std::string OTAPI_Exec::GetAssetType_ID(const int32_t& nIndex) const
4103 {
4104  if (0 > nIndex) {
4105  otErr << __FUNCTION__
4106  << ": nIndex is out of bounds (it's in the negative!)\n";
4107  OT_FAIL;
4108  }
4109 
4110  OTIdentifier theID;
4111  OTString strName;
4112 
4113  bool bGetServer = OTAPI()->GetAssetType(nIndex, theID, strName);
4114 
4115  if (bGetServer) {
4116  OTString strID(theID);
4117  std::string pBuf = strID.Get();
4118 
4119  return pBuf;
4120  }
4121  return "";
4122 }
4123 
4124 // Returns asset type Name based on Asset Type ID
4125 std::string OTAPI_Exec::GetAssetType_Name(const std::string& THE_ID) const
4126 {
4127  if (THE_ID.empty()) {
4128  otErr << __FUNCTION__ << ": Null: THE_ID passed in!\n";
4129  OT_FAIL;
4130  }
4131 
4132  OTIdentifier theID(THE_ID);
4133  OTAssetContract* pContract = OTAPI()->GetAssetType(theID, __FUNCTION__);
4134  if (nullptr == pContract) return "";
4135  OTString strName;
4136  pContract->GetName(strName);
4137  std::string pBuf = strName.Get();
4138 
4139  return pBuf;
4140 }
4141 
4142 // Returns asset type TLA based on Asset Type ID
4143 std::string OTAPI_Exec::GetAssetType_TLA(const std::string& THE_ID) const
4144 {
4145  if (THE_ID.empty()) {
4146  otErr << __FUNCTION__ << ": Null: THE_ID passed in!\n";
4147  OT_FAIL;
4148  }
4149 
4150  OTIdentifier theID(THE_ID);
4151  OTAssetContract* pContract = OTAPI()->GetAssetType(theID, __FUNCTION__);
4152  if (nullptr == pContract) return "";
4153  OTString strTLA;
4154  strTLA = pContract->GetCurrencyTLA();
4155  std::string pBuf = strTLA.Get();
4156 
4157  return pBuf;
4158 }
4159 
4160 // returns a string containing the account ID, based on index.
4161 std::string OTAPI_Exec::GetAccountWallet_ID(const int32_t& nIndex) const
4162 {
4163  if (0 > nIndex) {
4164  otErr << __FUNCTION__
4165  << ": nIndex is out of bounds (it's in the negative!)\n";
4166  OT_FAIL;
4167  }
4168 
4169  OTIdentifier theID;
4170  OTString strName;
4171 
4172  bool bGetServer = OTAPI()->GetAccount(nIndex, theID, strName);
4173 
4174  if (bGetServer) {
4175  OTString strID(theID);
4176 
4177  std::string pBuf = strID.Get();
4178 
4179  return pBuf;
4180  }
4181  return "";
4182 }
4183 
4184 // returns the account name, based on account ID.
4185 std::string OTAPI_Exec::GetAccountWallet_Name(const std::string& THE_ID) const
4186 {
4187  if (THE_ID.empty()) {
4188  otErr << __FUNCTION__ << ": Null: THE_ID passed in!\n";
4189  OT_FAIL;
4190  }
4191 
4192  OTIdentifier theID(THE_ID);
4193 
4194  std::string strFunc = "OTAPI_Exec::GetAccountWallet_Name";
4195  OTAccount* pAccount = OTAPI()->GetAccount(theID, strFunc.c_str());
4196  if (nullptr == pAccount) return "";
4197  OTString strName;
4198  pAccount->GetName(strName);
4199  std::string pBuf = strName.Get();
4200 
4201  return pBuf;
4202 }
4203 
4205  const std::string& ACCOUNT_ID) const // returns latest InboxHash according
4206  // to the
4207 // account file. (Usually more recent than:
4208 // OTAPI_Exec::GetNym_InboxHash)
4209 {
4210  if (ACCOUNT_ID.empty()) {
4211  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
4212  OT_FAIL;
4213  }
4214 
4215  OTIdentifier theID(ACCOUNT_ID);
4216 
4217  OTAccount* pAccount = OTAPI()->GetAccount(theID, __FUNCTION__);
4218  if (nullptr == pAccount) return "";
4219 
4220  OTIdentifier theOutput;
4221  const bool& bGotHash = pAccount->GetInboxHash(theOutput);
4222 
4223  OTString strOutput;
4224 
4225  if (bGotHash) theOutput.GetString(strOutput);
4226 
4227  std::string pBuf = strOutput.Get();
4228 
4229  return pBuf;
4230 }
4231 
4233  const std::string& ACCOUNT_ID) const // returns latest OutboxHash according
4234  // to the
4235 // account file. (Usually more recent than:
4236 // OTAPI_Exec::GetNym_OutboxHash)
4237 {
4238  if (ACCOUNT_ID.empty()) {
4239  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
4240  OT_FAIL;
4241  }
4242 
4243  OTIdentifier theID(ACCOUNT_ID);
4244 
4245  OTAccount* pAccount = OTAPI()->GetAccount(theID, __FUNCTION__);
4246  if (nullptr == pAccount) return "";
4247 
4248  OTIdentifier theOutput;
4249  const bool& bGotHash = pAccount->GetOutboxHash(theOutput);
4250 
4251  OTString strOutput;
4252 
4253  if (bGotHash) theOutput.GetString(strOutput);
4254 
4255  std::string pBuf = strOutput.Get();
4256 
4257  return pBuf;
4258 }
4259 
4270 {
4271  return OTAPI()->GetTime();
4272 }
4273 
4287 std::string OTAPI_Exec::Encode(const std::string& strPlaintext,
4288  const bool& bLineBreaks) const // bLineBreaks
4289  // should
4290 // usually be set to
4291 // true.
4292 {
4293  if (strPlaintext.empty()) {
4294  otErr << __FUNCTION__ << ": Null: strPlaintext passed in!\n";
4295  OT_FAIL;
4296  }
4297 
4298  const OTString otstrPlaintext(strPlaintext);
4299  OTString strOutput;
4300 
4301  bool bEncoded = OTAPI()->Encode(otstrPlaintext, strOutput,
4302  (true == bLineBreaks) ? true : false);
4303 
4304  if (!bEncoded) return "";
4305 
4306  std::string pBuf = strOutput.Get();
4307 
4308  return pBuf;
4309 }
4310 
4324 std::string OTAPI_Exec::Decode(const std::string& strEncoded,
4325  const bool& bLineBreaks) const
4326 {
4327  if (strEncoded.empty()) {
4328  return "";
4329  }
4330 
4331  const OTString otstrEncoded(strEncoded);
4332  OTString strOutput;
4333 
4334  bool bDecoded = OTAPI()->Decode(otstrEncoded, strOutput,
4335  (true == bLineBreaks) ? true : false);
4336 
4337  if (!bDecoded) return "";
4338 
4339  std::string pBuf = strOutput.Get();
4340 
4341  return pBuf;
4342 }
4343 
4362 std::string OTAPI_Exec::Encrypt(const std::string& RECIPIENT_NYM_ID,
4363  const std::string& strPlaintext) const
4364 {
4365  if (RECIPIENT_NYM_ID.empty()) {
4366  otErr << __FUNCTION__ << ": Null: RECIPIENT_NYM_ID passed in!\n";
4367  OT_FAIL;
4368  }
4369  if (strPlaintext.empty()) {
4370  otErr << __FUNCTION__ << ": Null: strPlaintext passed in!\n";
4371  OT_FAIL;
4372  }
4373  const OTString otstrPlaintext(strPlaintext);
4374  const OTIdentifier theRecipientNymID(RECIPIENT_NYM_ID);
4375  OTString strOutput;
4376 
4377  bool bEncrypted =
4378  OTAPI()->Encrypt(theRecipientNymID, otstrPlaintext, strOutput);
4379 
4380  if (!bEncrypted || !strOutput.Exists()) return "";
4381 
4382  std::string pBuf = strOutput.Get();
4383 
4384  return pBuf;
4385 }
4386 
4411 std::string OTAPI_Exec::Decrypt(const std::string& RECIPIENT_NYM_ID,
4412  const std::string& strCiphertext) const
4413 {
4414  if (RECIPIENT_NYM_ID.empty()) {
4415  otErr << __FUNCTION__ << ": Null: RECIPIENT_NYM_ID passed in!\n";
4416  OT_FAIL;
4417  }
4418  if (strCiphertext.empty()) {
4419  otErr << __FUNCTION__ << ": Null: strCiphertext passed in!\n";
4420  OT_FAIL;
4421  }
4422  const OTString otstrCiphertext(strCiphertext);
4423  const OTIdentifier theRecipientNymID(RECIPIENT_NYM_ID);
4424  OTString strOutput;
4425 
4426  bool bDecrypted =
4427  OTAPI()->Decrypt(theRecipientNymID, otstrCiphertext, strOutput);
4428 
4429  if (!bDecrypted || !strOutput.Exists()) return "";
4430 
4431  std::string pBuf = strOutput.Get();
4432 
4433  return pBuf;
4434 }
4435 
4436 // SYMMETRIC
4437 
4438 // Generates a new symmetric key, based on a passphrase,
4439 // and returns it (or "".)
4440 //
4442 {
4443  OTString strOutput;
4444  std::string strDisplay = "OTAPI: Creating a new symmetric key.";
4445  const OTString otstrDisplay(strDisplay);
4446  const bool& bSuccess = OTSymmetricKey::CreateNewKey(
4447  strOutput, &otstrDisplay); // pAlreadyHavePW=""
4448 
4449  if (!bSuccess) return "";
4450 
4451  std::string pBuf = strOutput.Get();
4452 
4453  return pBuf;
4454 }
4455 
4456 // OTEnvelope:
4457 // bool Encrypt(const OTString& theInput, OTSymmetricKey& theKey,
4458 // const OTPassword& thePassword);
4459 // bool Decrypt(OTString& theOutput, const OTSymmetricKey& theKey,
4460 // const OTPassword& thePassword);
4461 
4462 // Returns the CIPHERTEXT_ENVELOPE (the Envelope encrypted with the Symmetric
4463 // Key.)
4464 //
4465 std::string OTAPI_Exec::SymmetricEncrypt(const std::string& SYMMETRIC_KEY,
4466  const std::string& PLAINTEXT) const
4467 {
4468  if (SYMMETRIC_KEY.empty()) {
4469  otErr << __FUNCTION__ << ": Null: SYMMETRIC_KEY passed in!\n";
4470  OT_FAIL;
4471  }
4472  if (PLAINTEXT.empty()) {
4473  otErr << __FUNCTION__ << ": Null: PLAINTEXT passed in!\n";
4474  OT_FAIL;
4475  }
4476  const OTString strKey(SYMMETRIC_KEY);
4477  const OTString strPlaintext(PLAINTEXT);
4478  OTString strOutput;
4479  std::string strDisplay = "OTAPI: Password-protecting a plaintext.";
4480  const OTString otstrDisplay(strDisplay);
4481  const bool& bSuccess = OTSymmetricKey::Encrypt(
4482  strKey, strPlaintext, strOutput,
4483  &otstrDisplay); // bBookends=true, pAlreadyHavePW=""
4484 
4485  if (!bSuccess) return "";
4486 
4487  std::string pBuf = strOutput.Get();
4488 
4489  return pBuf;
4490 }
4491 
4492 // Returns the PLAINTEXT.
4493 //
4495  const std::string& SYMMETRIC_KEY,
4496  const std::string& CIPHERTEXT_ENVELOPE) const
4497 {
4498  if (SYMMETRIC_KEY.empty()) {
4499  otErr << __FUNCTION__ << ": Null: SYMMETRIC_KEY passed in!\n";
4500  OT_FAIL;
4501  }
4502  if (CIPHERTEXT_ENVELOPE.empty()) {
4503  otErr << __FUNCTION__ << ": Null: CIPHERTEXT_ENVELOPE passed in!\n";
4504  OT_FAIL;
4505  }
4506  const OTString strKey(SYMMETRIC_KEY);
4507  OTString strCiphertext(CIPHERTEXT_ENVELOPE);
4508  OTString strOutput;
4509  std::string strDisplay =
4510  "OTAPI: Decrypting a password-protected ciphertext.";
4511  const OTString otstrDisplay(strDisplay);
4512  const bool& bSuccess = OTSymmetricKey::Decrypt(
4513  strKey, strCiphertext, strOutput, &otstrDisplay); // pAlreadyHavePW=""
4514 
4515  if (!bSuccess) return "";
4516 
4517  std::string pBuf = strOutput.Get();
4518 
4519  return pBuf;
4520 }
4521 
4539 std::string OTAPI_Exec::SignContract(const std::string& SIGNER_NYM_ID,
4540  const std::string& THE_CONTRACT) const
4541 {
4542  bool bIsInitialized = OTAPI()->IsInitialized();
4543  if (!bIsInitialized) {
4544  otErr << __FUNCTION__
4545  << ": Not initialized; call OT_API::Init first.\n";
4546  OT_FAIL;
4547  }
4548 
4549  if (SIGNER_NYM_ID.empty()) {
4550  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
4551  OT_FAIL;
4552  }
4553  if (THE_CONTRACT.empty()) {
4554  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
4555  OT_FAIL;
4556  }
4557 
4558  const OTString strContract(THE_CONTRACT);
4559  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
4560  OTString strOutput;
4561 
4562  const bool& bSigned =
4563  OTAPI()->SignContract(theSignerNymID, strContract, strOutput);
4564 
4565  if (!bSigned || !strOutput.Exists()) return "";
4566 
4567  std::string pBuf = strOutput.Get();
4568 
4569  return pBuf;
4570 }
4571 
4572 // Instead of signing an existing contract, this is for just signing a flat
4573 // message.
4574 // Or, for example, for signing a new contract that has no signature yet. Let's
4575 // say you
4576 // have a ledger, for example, with no signatures yet. Pass "LEDGER" as the
4577 // CONTRACT_TYPE
4578 // and the resulting output will start like this: -----BEGIN OT SIGNED
4579 // LEDGER----- ...
4580 // Returns the signed output, or "".
4581 //
4582 std::string OTAPI_Exec::FlatSign(const std::string& SIGNER_NYM_ID,
4583  const std::string& THE_INPUT,
4584  const std::string& CONTRACT_TYPE) const
4585 {
4586  bool bIsInitialized = OTAPI()->IsInitialized();
4587  if (!bIsInitialized) {
4588  otErr << __FUNCTION__
4589  << ": Not initialized; call OT_API::Init first.\n";
4590  OT_FAIL;
4591  }
4592 
4593  if (SIGNER_NYM_ID.empty()) {
4594  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
4595  OT_FAIL;
4596  }
4597  if (THE_INPUT.empty()) {
4598  otErr << __FUNCTION__ << ": Null: THE_INPUT passed in!\n";
4599  OT_FAIL;
4600  }
4601  if (CONTRACT_TYPE.empty()) {
4602  otErr << __FUNCTION__ << ": Null: CONTRACT_TYPE passed in!\n";
4603  OT_FAIL;
4604  }
4605 
4606  const OTString strContract(THE_INPUT);
4607  const OTString strContractType(CONTRACT_TYPE);
4608  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
4609  OTString strOutput;
4610 
4611  const bool& bSigned = OTAPI()->FlatSign(theSignerNymID, strContract,
4612  strContractType, strOutput);
4613 
4614  if (!bSigned || !strOutput.Exists()) return "";
4615 
4616  std::string pBuf = strOutput.Get();
4617 
4618  return pBuf;
4619 }
4620 
4639 std::string OTAPI_Exec::AddSignature(const std::string& SIGNER_NYM_ID,
4640  const std::string& THE_CONTRACT) const
4641 {
4642  bool bIsInitialized = OTAPI()->IsInitialized();
4643  if (!bIsInitialized) {
4644  otErr << __FUNCTION__
4645  << ": Not initialized; call OT_API::Init first.\n";
4646  OT_FAIL;
4647  }
4648 
4649  if (SIGNER_NYM_ID.empty()) {
4650  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
4651  OT_FAIL;
4652  }
4653  if (THE_CONTRACT.empty()) {
4654  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
4655  OT_FAIL;
4656  }
4657 
4658  const OTString strContract(THE_CONTRACT);
4659  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
4660  OTString strOutput;
4661 
4662  const bool& bSigned =
4663  OTAPI()->AddSignature(theSignerNymID, strContract, strOutput);
4664 
4665  if (!bSigned || !strOutput.Exists()) return "";
4666 
4667  std::string pBuf = strOutput.Get();
4668 
4669  return pBuf;
4670 }
4671 
4676 bool OTAPI_Exec::VerifySignature(const std::string& SIGNER_NYM_ID,
4677  const std::string& THE_CONTRACT) const
4678 {
4679  if (SIGNER_NYM_ID.empty()) {
4680  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
4681  OT_FAIL;
4682  }
4683  if (THE_CONTRACT.empty()) {
4684  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
4685  OT_FAIL;
4686  }
4687  const OTString strContract(THE_CONTRACT);
4688  const OTIdentifier theNymID(SIGNER_NYM_ID);
4689  const bool& bVerified = OTAPI()->VerifySignature(
4690  strContract, theNymID); /*ppContract="" (optional third parameter for
4691  retrieving loaded contract.)*/
4692  return bVerified ? true : false;
4693 }
4694 
4695 // Verify and Retrieve XML Contents.
4696 //
4697 // Pass in a contract and a user ID, and this function will:
4698 // -- Load the contract up and verify it.
4699 // -- Verify the user's signature on it.
4700 // -- Remove the PGP-style bookends (the signatures, etc)
4701 // and return the XML contents of the contract in string form.
4702 //
4704  const std::string& THE_CONTRACT, const std::string& SIGNER_ID) const
4705 {
4706  if (THE_CONTRACT.empty()) {
4707  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
4708  OT_FAIL;
4709  }
4710  if (SIGNER_ID.empty()) {
4711  otErr << __FUNCTION__ << ": Null: SIGNER_ID passed in!\n";
4712  OT_FAIL;
4713  }
4714 
4715  const OTString strContract(THE_CONTRACT);
4716  const OTIdentifier theSignerID(SIGNER_ID);
4717  OTString strOutput;
4718 
4719  if (false ==
4720  OTAPI()->VerifyAndRetrieveXMLContents(strContract, theSignerID,
4721  strOutput)) {
4722  otOut << __FUNCTION__ << ": Failure: "
4723  "OTAPI()->VerifyAndRetrieveXMLContents() "
4724  "returned false.\n";
4725  return "";
4726  }
4727  std::string pBuf = strOutput.Get();
4728 
4729  return pBuf;
4730 }
4731 
4732 // === Verify Account Receipt ===
4733 // Returns bool. Verifies any asset account (intermediary files) against its own
4734 // last signed receipt.
4735 // Obviously this will fail for any new account that hasn't done any
4736 // transactions yet, and thus has no receipts.
4737 //
4738 bool OTAPI_Exec::VerifyAccountReceipt(const std::string& SERVER_ID,
4739  const std::string& NYM_ID,
4740  const std::string& ACCT_ID) const
4741 {
4742  if (SERVER_ID.empty()) {
4743  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
4744  OT_FAIL;
4745  }
4746  if (NYM_ID.empty()) {
4747  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
4748  OT_FAIL;
4749  }
4750  if (ACCT_ID.empty()) {
4751  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
4752  OT_FAIL;
4753  }
4754 
4755  const OTIdentifier theServerID(SERVER_ID), theNymID(NYM_ID),
4756  theAcctID(ACCT_ID);
4757  const bool& bVerified =
4758  OTAPI()->VerifyAccountReceipt(theServerID, theNymID, theAcctID);
4759  return bVerified ? true : false;
4760 }
4761 
4762 // SET ACCOUNT NAME (client side only. Server cares not about such labels.)
4763 //
4764 // Returns true (1) or false (0)
4765 //
4766 bool OTAPI_Exec::SetAccountWallet_Name(const std::string& ACCT_ID,
4767  const std::string& SIGNER_NYM_ID,
4768  const std::string& ACCT_NEW_NAME) const
4769 {
4770  if (ACCT_ID.empty()) {
4771  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
4772  OT_FAIL;
4773  }
4774  if (SIGNER_NYM_ID.empty()) {
4775  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
4776  OT_FAIL;
4777  }
4778  if (ACCT_NEW_NAME.empty()) {
4779  otErr << __FUNCTION__ << ": Null: ACCT_NEW_NAME passed in!\n";
4780  OT_FAIL;
4781  }
4782 
4783  OTIdentifier theAcctID(ACCT_ID), theSignerNymID(SIGNER_NYM_ID);
4784  OTString strAcctNewName(ACCT_NEW_NAME);
4785 
4786  bool bSuccess =
4787  OTAPI()->SetAccount_Name(theAcctID, theSignerNymID, strAcctNewName);
4788 
4789  return bSuccess ? true : false;
4790 }
4791 
4792 // returns the account balance, based on account ID.
4793 int64_t OTAPI_Exec::GetAccountWallet_Balance(const std::string& THE_ID) const
4794 {
4795  if (THE_ID.empty()) {
4796  otErr << __FUNCTION__ << ": Null: THE_ID passed in!\n";
4797  OT_FAIL;
4798  }
4799 
4800  OTIdentifier theID(THE_ID);
4801  OTAccount* pAccount = OTAPI()->GetAccount(theID, __FUNCTION__);
4802  return nullptr == pAccount ? OT_ERROR_AMOUNT : pAccount->GetBalance();
4803 }
4804 
4805 // returns an account's "account type", (simple, issuer, etc.)
4806 std::string OTAPI_Exec::GetAccountWallet_Type(const std::string& THE_ID) const
4807 {
4808  if (THE_ID.empty()) {
4809  otErr << __FUNCTION__ << ": Null: THE_ID passed in!\n";
4810  OT_FAIL;
4811  }
4812 
4813  OTIdentifier theID(THE_ID);
4814  OTAccount* pAccount = OTAPI()->GetAccount(theID, __FUNCTION__);
4815  if (nullptr == pAccount) return "";
4816  std::string pBuf = pAccount->GetTypeString();
4817 
4818  return pBuf;
4819 }
4820 
4821 // Returns an account's asset type ID.
4822 // (Which is a hash of the contract used to issue the asset type.)
4824  const std::string& THE_ID) const
4825 {
4826  if (THE_ID.empty()) {
4827  otErr << __FUNCTION__ << ": Null: THE_ID passed in!\n";
4828  OT_FAIL;
4829  }
4830 
4831  OTIdentifier theID(THE_ID);
4832  OTAccount* pAccount = OTAPI()->GetAccount(theID, __FUNCTION__);
4833  if (nullptr == pAccount) return "";
4834  OTIdentifier theAssetID(pAccount->GetAssetTypeID());
4835 
4836  OTString strAssetTypeID(theAssetID);
4837 
4838  otWarn << __FUNCTION__ << ": Returning asset type " << strAssetTypeID
4839  << " for account " << THE_ID << "\n";
4840 
4841  std::string pBuf = strAssetTypeID.Get();
4842 
4843  return pBuf;
4844 }
4845 
4846 // Returns an account's Server ID.
4847 // (Which is a hash of the server contract.)
4849  const std::string& THE_ID) const
4850 {
4851  if (THE_ID.empty()) {
4852  otErr << __FUNCTION__ << ": Null: THE_ID passed in!\n";
4853  OT_FAIL;
4854  }
4855 
4856  OTIdentifier theID(THE_ID);
4857  OTAccount* pAccount = OTAPI()->GetAccount(theID, __FUNCTION__);
4858  if (nullptr == pAccount) return "";
4859  OTIdentifier theServerID(pAccount->GetPurportedServerID());
4860  OTString strServerID(theServerID);
4861 
4862  std::string pBuf = strServerID.Get();
4863 
4864  return pBuf;
4865 }
4866 
4867 // Returns an account's Nym ID.
4868 // (Which is a hash of the Nym's public key for the owner of this account.)
4869 std::string OTAPI_Exec::GetAccountWallet_NymID(const std::string& THE_ID) const
4870 {
4871  if (THE_ID.empty()) {
4872  otErr << __FUNCTION__ << ": Null: THE_ID passed in!\n";
4873  OT_FAIL;
4874  }
4875 
4876  const OTIdentifier theID(THE_ID);
4877 
4878  OTAccount* pAccount = OTAPI()->GetAccount(theID, __FUNCTION__);
4879  if (nullptr == pAccount) return "";
4880  OTIdentifier theUserID(pAccount->GetUserID());
4881  OTString strUserID(theUserID);
4882 
4883  std::string pBuf = strUserID.Get();
4884 
4885  return pBuf;
4886 }
4887 
4888 /*
4889 
4890 WRITE A CHEQUE --- (Returns the cheque in string form.)
4891 
4892 ==> OTAPI_Exec::WriteCheque() internally constructs an OTCheque and issues it,
4893 like so:
4894 
4895 OTCheque theCheque( SERVER_ID, ASSET_TYPE_ID );
4896 
4897 theCheque.IssueCheque( AMOUNT // The amount of the cheque, in string form, which
4898 OTAPI
4899 // will convert to a int64_t integer. Negative amounts
4900 // allowed, since that is how OT implements invoices.
4901 // (An invoice is just a cheque with a negative amount.)
4902 
4903 lTransactionNumber, // The API will supply this automatically, as long as
4904 // there are some transaction numbers in the wallet. (Call
4905 // OTAPI_Exec::getTransactionNumber() if your wallet needs more.)
4906 
4907 VALID_FROM, VALID_TO, // Valid date range (in seconds since Jan 1970...)
4908 
4909 ACCOUNT_ID, USER_ID, // User ID and Acct ID for SENDER.
4910 
4911 CHEQUE_MEMO, // The memo for the cheque.
4912 
4913 RECIPIENT_USER_ID); // Recipient User ID is optional. (You can use an
4914 // empty string here, to write a blank cheque.)
4915 */
4917  const std::string& SERVER_ID, const int64_t& CHEQUE_AMOUNT,
4918  const time64_t& VALID_FROM, const time64_t& VALID_TO,
4919  const std::string& SENDER_ACCT_ID, const std::string& SENDER_USER_ID,
4920  const std::string& CHEQUE_MEMO, const std::string& RECIPIENT_USER_ID) const
4921 {
4922  if (SERVER_ID.empty()) {
4923  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
4924  OT_FAIL;
4925  }
4926  if (0 == CHEQUE_AMOUNT) {
4927  otErr << __FUNCTION__ << ": Null: CHEQUE_AMOUNT passed in!\n";
4928  OT_FAIL;
4929  }
4930  if (OT_TIME_ZERO > VALID_FROM) {
4931  otErr << __FUNCTION__ << ": Null: VALID_FROM passed in!\n";
4932  OT_FAIL;
4933  }
4934  if (OT_TIME_ZERO > VALID_TO) {
4935  otErr << __FUNCTION__ << ": Null: VALID_TO passed in!\n";
4936  OT_FAIL;
4937  }
4938  if (SENDER_ACCT_ID.empty()) {
4939  otErr << __FUNCTION__ << ": Null: SENDER_ACCT_ID passed in!\n";
4940  OT_FAIL;
4941  }
4942  if (SENDER_USER_ID.empty()) {
4943  otErr << __FUNCTION__ << ": Null: SENDER_USER_ID passed in!\n";
4944  OT_FAIL;
4945  }
4946  // if (CHEQUE_MEMO.empty()) { otErr << __FUNCTION__ << ": Null:
4947  // CHEQUE_MEMO passed
4948  // in!\n"; OT_FAIL; } // optional
4949  // if (RECIPIENT_USER_ID.empty()) { otErr << __FUNCTION__ << ": Null:
4950  // RECIPIENT_USER_ID passed
4951  // in!\n"; OT_FAIL; } // optional
4952 
4953  const int64_t lAmount = CHEQUE_AMOUNT;
4954  const time64_t time_From = static_cast<time64_t>(VALID_FROM),
4955  time_To = static_cast<time64_t>(VALID_TO);
4956 
4957  const OTIdentifier theServerID(SERVER_ID);
4958  const OTIdentifier theSenderAcctID(SENDER_ACCT_ID);
4959  const OTIdentifier theSenderUserID(SENDER_USER_ID);
4960  OTIdentifier theRecipientUserID;
4961  bool bHasRecipient = !RECIPIENT_USER_ID.empty();
4962  if (bHasRecipient) theRecipientUserID.SetString(RECIPIENT_USER_ID);
4963  OTString strMemo;
4964 
4965  if (!CHEQUE_MEMO.empty()) strMemo.Set(CHEQUE_MEMO);
4966 
4967  std::unique_ptr<OTCheque> pCheque(OTAPI()->WriteCheque(
4968  theServerID, static_cast<int64_t>(lAmount), time_From, time_To,
4969  theSenderAcctID, theSenderUserID, strMemo,
4970  bHasRecipient ? &(theRecipientUserID) : nullptr));
4971 
4972  if (nullptr == pCheque) {
4973  otErr << __FUNCTION__ << ": OT_API::WriteCheque failed.\n";
4974  return "";
4975  }
4976  // At this point, I know pCheque is good (and will be cleaned up
4977  // automatically.)
4978 
4979  OTString strCheque(*pCheque); // Extract the cheque to string form.
4980 
4981  std::string pBuf = strCheque.Get();
4982 
4983  return pBuf;
4984 }
4985 
4986 bool OTAPI_Exec::DiscardCheque(const std::string& SERVER_ID,
4987  const std::string& USER_ID,
4988  const std::string& ACCT_ID,
4989  const std::string& THE_CHEQUE) const
4990 {
4991  if (SERVER_ID.empty()) {
4992  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
4993  OT_FAIL;
4994  }
4995  if (USER_ID.empty()) {
4996  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
4997  OT_FAIL;
4998  }
4999  if (ACCT_ID.empty()) {
5000  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
5001  OT_FAIL;
5002  }
5003  if (THE_CHEQUE.empty()) {
5004  otErr << __FUNCTION__ << ": Null: THE_CHEQUE passed in!\n";
5005  OT_FAIL;
5006  }
5007 
5008  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID);
5009  OTString strCheque(THE_CHEQUE);
5010 
5011  const bool bDiscarded =
5012  OTAPI()->DiscardCheque(theServerID, theUserID, theAcctID, strCheque);
5013 
5014  return (bDiscarded ? true : false);
5015 }
5016 
5017 // PROPOSE PAYMENT PLAN
5018 //
5019 // (Return as STRING)
5020 //
5021 // PARAMETER NOTES:
5022 // -- Payment Plan Delay, and Payment Plan Period, both default to 30 days (if
5023 // you pass 0.)
5024 //
5025 // -- Payment Plan Length, and Payment Plan Max Payments, both default to 0,
5026 // which means
5027 // no maximum length and no maximum number of payments.
5028 //
5029 // FYI, the payment plan creation process (finally) is:
5030 //
5031 // 1) Payment plan is written, and signed, by the recipient. (This function:
5032 // OTAPI_Exec::ProposePaymentPlan)
5033 // 2) He sends it to the sender, who signs it and submits it.
5034 // (OTAPI_Exec::ConfirmPaymentPlan and OTAPI_Exec::depositPaymentPlan)
5035 // 3) The server loads the recipient nym to verify the transaction
5036 // number. The sender also had to burn a transaction number (to
5037 // submit it) so now, both have verified trns#s in this way.
5038 //
5040  const std::string& SERVER_ID,
5041  const time64_t& VALID_FROM, // Default (0 or nullptr) == current time
5042  // measured
5043  // in seconds since Jan 1970.
5044  const time64_t& VALID_TO, // Default (0 or nullptr) == no expiry / cancel
5045  // anytime. Otherwise this is ADDED to VALID_FROM
5046  // (it's a length.)
5047  const std::string& SENDER_ACCT_ID, // Mandatory parameters.
5048  const std::string& SENDER_USER_ID, // Both sender and recipient must sign
5049  // before submitting.
5050  const std::string& PLAN_CONSIDERATION, // Like a memo.
5051  const std::string& RECIPIENT_ACCT_ID, // NOT optional.
5052  const std::string& RECIPIENT_USER_ID, // Both sender and recipient must sign
5053  // before submitting.
5054  const int64_t& INITIAL_PAYMENT_AMOUNT, // zero or "" is no initial payment.
5055  const time64_t& INITIAL_PAYMENT_DELAY, // seconds from creation date.
5056  // Default is zero or "".
5057  const int64_t& PAYMENT_PLAN_AMOUNT, // Zero or "" is no regular payments.
5058  const time64_t& PAYMENT_PLAN_DELAY, // No. of seconds from creation date.
5059  // Default is zero or "".
5060  const time64_t& PAYMENT_PLAN_PERIOD, // No. of seconds between payments.
5061  // Default is zero or "".
5062  const time64_t& PAYMENT_PLAN_LENGTH, // In seconds. Defaults to 0 or "" (no
5063  // maximum length.)
5064  const int32_t& PAYMENT_PLAN_MAX_PAYMENTS // Integer. Defaults to 0 or "" (no
5065  // maximum payments.)
5066  ) const
5067 {
5068  if (SERVER_ID.empty()) {
5069  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
5070  OT_FAIL;
5071  }
5072  if (OT_TIME_ZERO > VALID_FROM) {
5073  otErr << __FUNCTION__ << ": Negative: VALID_FROM passed in!\n";
5074  OT_FAIL;
5075  }
5076  if (OT_TIME_ZERO > VALID_TO) {
5077  otErr << __FUNCTION__ << ": Negative: VALID_TO passed in!\n";
5078  OT_FAIL;
5079  }
5080  if (SENDER_ACCT_ID.empty()) {
5081  otErr << __FUNCTION__ << ": Null: SENDER_ACCT_ID passed in!\n";
5082  OT_FAIL;
5083  }
5084  if (SENDER_USER_ID.empty()) {
5085  otErr << __FUNCTION__ << ": Null: SENDER_USER_ID passed in!\n";
5086  OT_FAIL;
5087  }
5088  if (PLAN_CONSIDERATION.empty()) {
5089  otErr << __FUNCTION__ << ": Null: PLAN_CONSIDERATION passed in!\n";
5090  OT_FAIL;
5091  }
5092  if (RECIPIENT_ACCT_ID.empty()) {
5093  otErr << __FUNCTION__ << ": Null: RECIPIENT_ACCT_ID passed in!\n";
5094  OT_FAIL;
5095  }
5096  if (RECIPIENT_USER_ID.empty()) {
5097  otErr << __FUNCTION__ << ": Null: RECIPIENT_USER_ID passed in!\n";
5098  OT_FAIL;
5099  }
5100  if (0 > INITIAL_PAYMENT_AMOUNT) {
5101  otErr << __FUNCTION__
5102  << ": Negative: INITIAL_PAYMENT_AMOUNT passed in!\n";
5103  OT_FAIL;
5104  }
5105  if (OT_TIME_ZERO > INITIAL_PAYMENT_DELAY) {
5106  otErr << __FUNCTION__
5107  << ": Negative: INITIAL_PAYMENT_DELAY passed in!\n";
5108  OT_FAIL;
5109  }
5110  if (0 > PAYMENT_PLAN_AMOUNT) {
5111  otErr << __FUNCTION__ << ": Negative: PAYMENT_PLAN_AMOUNT passed in!\n";
5112  OT_FAIL;
5113  }
5114  if (OT_TIME_ZERO > PAYMENT_PLAN_DELAY) {
5115  otErr << __FUNCTION__ << ": Negative: PAYMENT_PLAN_DELAY passed in!\n";
5116  OT_FAIL;
5117  }
5118  if (OT_TIME_ZERO > PAYMENT_PLAN_PERIOD) {
5119  otErr << __FUNCTION__ << ": Negative: PAYMENT_PLAN_PERIOD passed in!\n";
5120  OT_FAIL;
5121  }
5122  if (OT_TIME_ZERO > PAYMENT_PLAN_LENGTH) {
5123  otErr << __FUNCTION__ << ": Negative: PAYMENT_PLAN_LENGTH passed in!\n";
5124  OT_FAIL;
5125  }
5126  if (0 > PAYMENT_PLAN_MAX_PAYMENTS) {
5127  otErr << __FUNCTION__
5128  << ": Negative: PAYMENT_PLAN_MAX_PAYMENTS passed in!\n";
5129  OT_FAIL;
5130  }
5131  std::unique_ptr<OTPaymentPlan> pPlan(OTAPI()->ProposePaymentPlan(
5132  OTIdentifier(SERVER_ID), VALID_FROM, // Default (0) == NOW
5133  VALID_TO, // Default (0) == no expiry / cancel anytime
5134  OTIdentifier(SENDER_ACCT_ID), OTIdentifier(SENDER_USER_ID),
5135  PLAN_CONSIDERATION.empty() ? "(Consideration for the agreement between "
5136  "the parties is meant to be recorded "
5137  "here.)"
5138  : PLAN_CONSIDERATION, // Like a memo.
5139  OTIdentifier(RECIPIENT_ACCT_ID),
5140  OTIdentifier(RECIPIENT_USER_ID),
5141  static_cast<int64_t>(INITIAL_PAYMENT_AMOUNT), INITIAL_PAYMENT_DELAY,
5142  static_cast<int64_t>(PAYMENT_PLAN_AMOUNT), PAYMENT_PLAN_DELAY,
5143  PAYMENT_PLAN_PERIOD, PAYMENT_PLAN_LENGTH,
5144  static_cast<int32_t>(PAYMENT_PLAN_MAX_PAYMENTS)));
5145  if (nullptr == pPlan) {
5146  otErr << __FUNCTION__
5147  << ": failed in OTAPI_Exec::ProposePaymentPlan.\n";
5148  return "";
5149  }
5150  // At this point, I know pPlan is good (and will be cleaned up
5151  // automatically.)
5152  OTString strOutput(*pPlan); // Extract the payment plan to string form.
5153  std::string pBuf = strOutput.Get();
5154  return pBuf;
5155 }
5156 
5157 // TODO RESUME:
5158 // 1. Find out what DiscardCheque is used for.
5159 // 2. Make sure we don't need a "Discard Payment Plan" and "Discard Smart
5160 // Contract" as well.
5161 // 3. Add "EasyProposePlan" to the rest of the API like OTAPI_Basic
5162 // 4. Add 'propose' and 'confirm' (for payment plan) commands to opentxs client.
5163 // 5. Finish opentxs basket commands, so opentxs is COMPLETE.
5164 
5166  const std::string& SERVER_ID,
5167  const std::string& DATE_RANGE, // "from,to" Default 'from' (0 or "") ==
5168  // NOW, and default 'to' (0 or "") == no
5169  // expiry / cancel anytime
5170  const std::string& SENDER_ACCT_ID, // Mandatory parameters.
5171  const std::string& SENDER_USER_ID, // Both sender and recipient must sign
5172  // before submitting.
5173  const std::string& PLAN_CONSIDERATION, // Like a memo.
5174  const std::string& RECIPIENT_ACCT_ID, // NOT optional.
5175  const std::string& RECIPIENT_USER_ID, // Both sender and recipient must sign
5176  // before submitting.
5177  const std::string& INITIAL_PAYMENT, // "amount,delay" Default 'amount' (0
5178  // or "") == no initial payment. Default
5179  // 'delay' (0 or nullptr) is seconds from
5180  // creation date.
5181  const std::string& PAYMENT_PLAN, // "amount,delay,period" 'amount' is a
5182  // recurring payment. 'delay' and 'period'
5183  // cause 30 days if you pass 0 or "".
5184  const std::string& PLAN_EXPIRY // "length,number" 'length' is maximum
5185  // lifetime in seconds. 'number' is maximum
5186  // number of payments in seconds. 0 or "" is
5187  // unlimited.
5188  ) const
5189 {
5190  if (SERVER_ID.empty()) {
5191  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
5192  OT_FAIL;
5193  }
5194  if (SENDER_ACCT_ID.empty()) {
5195  otErr << __FUNCTION__ << ": Null: SENDER_ACCT_ID passed in!\n";
5196  OT_FAIL;
5197  }
5198  if (SENDER_USER_ID.empty()) {
5199  otErr << __FUNCTION__ << ": Null: SENDER_USER_ID passed in!\n";
5200  OT_FAIL;
5201  }
5202  if (PLAN_CONSIDERATION.empty()) {
5203  otErr << __FUNCTION__ << ": Null: PLAN_CONSIDERATION passed in!\n";
5204  OT_FAIL;
5205  }
5206  if (RECIPIENT_ACCT_ID.empty()) {
5207  otErr << __FUNCTION__ << ": Null: RECIPIENT_ACCT_ID passed in!\n";
5208  OT_FAIL;
5209  }
5210  if (RECIPIENT_USER_ID.empty()) {
5211  otErr << __FUNCTION__ << ": Null: RECIPIENT_USER_ID passed in!\n";
5212  OT_FAIL;
5213  }
5214  time64_t VALID_FROM = OT_TIME_ZERO;
5215  time64_t VALID_TO = OT_TIME_ZERO;
5216  int64_t INITIAL_PAYMENT_AMOUNT = 0;
5217  time64_t INITIAL_PAYMENT_DELAY = OT_TIME_ZERO;
5218  int64_t PAYMENT_PLAN_AMOUNT = 0;
5219  time64_t PAYMENT_PLAN_DELAY = OT_TIME_ZERO;
5220  time64_t PAYMENT_PLAN_PERIOD = OT_TIME_ZERO;
5221  time64_t PAYMENT_PLAN_LENGTH = OT_TIME_ZERO;
5222  int32_t PAYMENT_PLAN_MAX_PAYMENTS = 0;
5223  if (!DATE_RANGE.empty()) {
5224  OTNumList theList;
5225  const OTString otstrNumList(DATE_RANGE);
5226  theList.Add(otstrNumList);
5227  // VALID_FROM
5228  if (theList.Count() > 0) {
5229  int64_t lVal = 0;
5230  if (theList.Peek(lVal)) VALID_FROM = OTTimeGetTimeFromSeconds(lVal);
5231  theList.Pop();
5232  }
5233  // VALID_TO
5234  if (theList.Count() > 0) {
5235  int64_t lVal = 0;
5236  if (theList.Peek(lVal)) VALID_TO = OTTimeGetTimeFromSeconds(lVal);
5237  theList.Pop();
5238  }
5239  }
5240  if (!INITIAL_PAYMENT.empty()) {
5241  OTNumList theList;
5242  const OTString otstrNumList(INITIAL_PAYMENT);
5243  theList.Add(otstrNumList);
5244  // INITIAL_PAYMENT_AMOUNT
5245  if (theList.Count() > 0) {
5246  int64_t lVal = 0;
5247  if (theList.Peek(lVal))
5248  INITIAL_PAYMENT_AMOUNT = static_cast<int64_t>(lVal);
5249  theList.Pop();
5250  }
5251  // INITIAL_PAYMENT_DELAY
5252  if (theList.Count() > 0) {
5253  int64_t lVal = 0;
5254  if (theList.Peek(lVal))
5255  INITIAL_PAYMENT_DELAY = OTTimeGetTimeFromSeconds(lVal);
5256  theList.Pop();
5257  }
5258  }
5259  if (!PAYMENT_PLAN.empty()) {
5260  OTNumList theList;
5261  const OTString otstrNumList(PAYMENT_PLAN);
5262  theList.Add(otstrNumList);
5263  // PAYMENT_PLAN_AMOUNT
5264  if (theList.Count() > 0) {
5265  int64_t lVal = 0;
5266  if (theList.Peek(lVal))
5267  PAYMENT_PLAN_AMOUNT = static_cast<int64_t>(lVal);
5268  theList.Pop();
5269  }
5270  // PAYMENT_PLAN_DELAY
5271  if (theList.Count() > 0) {
5272  int64_t lVal = 0;
5273  if (theList.Peek(lVal))
5274  PAYMENT_PLAN_DELAY = OTTimeGetTimeFromSeconds(lVal);
5275  theList.Pop();
5276  }
5277  // PAYMENT_PLAN_PERIOD
5278  if (theList.Count() > 0) {
5279  int64_t lVal = 0;
5280  if (theList.Peek(lVal))
5281  PAYMENT_PLAN_PERIOD = OTTimeGetTimeFromSeconds(lVal);
5282  theList.Pop();
5283  }
5284  }
5285  if (!PLAN_EXPIRY.empty()) {
5286  OTNumList theList;
5287  const OTString otstrNumList(PLAN_EXPIRY);
5288  theList.Add(otstrNumList);
5289  // PAYMENT_PLAN_LENGTH
5290  if (theList.Count() > 0) {
5291  int64_t lVal = 0;
5292  if (theList.Peek(lVal))
5293  PAYMENT_PLAN_LENGTH = OTTimeGetTimeFromSeconds(lVal);
5294  theList.Pop();
5295  }
5296  // PAYMENT_PLAN_MAX_PAYMENTS
5297  if (theList.Count() > 0) {
5298  int64_t lVal = 0;
5299  if (theList.Peek(lVal))
5300  PAYMENT_PLAN_MAX_PAYMENTS = static_cast<int32_t>(lVal);
5301  theList.Pop();
5302  }
5303  }
5305  SERVER_ID, VALID_FROM, VALID_TO, SENDER_ACCT_ID, SENDER_USER_ID,
5306  PLAN_CONSIDERATION, RECIPIENT_ACCT_ID, RECIPIENT_USER_ID,
5307  INITIAL_PAYMENT_AMOUNT, INITIAL_PAYMENT_DELAY, PAYMENT_PLAN_AMOUNT,
5308  PAYMENT_PLAN_DELAY, PAYMENT_PLAN_PERIOD, PAYMENT_PLAN_LENGTH,
5309  PAYMENT_PLAN_MAX_PAYMENTS);
5310 }
5311 
5312 // Called by CUSTOMER.
5313 // "PAYMENT_PLAN" is the output of the above function (ProposePaymentPlan)
5314 // Customer should call OTAPI_Exec::depositPaymentPlan after this.
5315 //
5317  const std::string& SERVER_ID, const std::string& SENDER_USER_ID,
5318  const std::string& SENDER_ACCT_ID, const std::string& RECIPIENT_USER_ID,
5319  const std::string& PAYMENT_PLAN) const
5320 {
5321  if (SERVER_ID.empty()) {
5322  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
5323  OT_FAIL;
5324  }
5325  if (SENDER_ACCT_ID.empty()) {
5326  otErr << __FUNCTION__ << ": Null: SENDER_ACCT_ID passed in!\n";
5327  OT_FAIL;
5328  }
5329  if (SENDER_USER_ID.empty()) {
5330  otErr << __FUNCTION__ << ": Null: SENDER_USER_ID passed in!\n";
5331  OT_FAIL;
5332  }
5333  if (RECIPIENT_USER_ID.empty()) {
5334  otErr << __FUNCTION__ << ": Null: RECIPIENT_USER_ID passed in!\n";
5335  OT_FAIL;
5336  }
5337  if (PAYMENT_PLAN.empty()) {
5338  otErr << __FUNCTION__ << ": Null: PAYMENT_PLAN passed in!\n";
5339  OT_FAIL;
5340  }
5341 
5342  const OTIdentifier theServerID(SERVER_ID);
5343  const OTIdentifier theSenderUserID(SENDER_USER_ID);
5344  const OTIdentifier theSenderAcctID(SENDER_ACCT_ID);
5345  const OTIdentifier theRecipientUserID(RECIPIENT_USER_ID);
5346 
5347  OTPaymentPlan thePlan;
5348  const OTString strPlan(PAYMENT_PLAN);
5349 
5350  if (!strPlan.Exists() ||
5351  (false == thePlan.LoadContractFromString(strPlan))) {
5352  otOut << __FUNCTION__
5353  << ": Failure loading payment plan from string.\n";
5354  return "";
5355  }
5356  bool bConfirmed = OTAPI()->ConfirmPaymentPlan(theServerID, theSenderUserID,
5357  theSenderAcctID,
5358  theRecipientUserID, thePlan);
5359  if (!bConfirmed) {
5360  otOut << __FUNCTION__
5361  << ": failed in OTAPI_Exec::ConfirmPaymentPlan().\n";
5362  return "";
5363  }
5364 
5365  OTString strOutput(thePlan); // Extract the payment plan to string form.
5366 
5367  std::string pBuf = strOutput.Get();
5368 
5369  return pBuf;
5370 }
5371 
5372 // RETURNS: the Smart Contract itself. (Or "".)
5373 //
5375  const std::string& SIGNER_NYM_ID, // Use any Nym you wish here. (The signing
5376  // at this point32_t is only to cause a
5377  // save.)
5378  const time64_t& VALID_FROM, // Default (0 or "") == NOW
5379  const time64_t& VALID_TO) const // Default (0 or "") == no expiry / cancel
5380  // anytime
5381 {
5382  if (SIGNER_NYM_ID.empty()) {
5383  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
5384  OT_FAIL;
5385  }
5386  if (OT_TIME_ZERO > VALID_FROM) {
5387  otErr << __FUNCTION__ << ": Negative: VALID_FROM passed in!\n";
5388  OT_FAIL;
5389  }
5390  if (OT_TIME_ZERO > VALID_TO) {
5391  otErr << __FUNCTION__ << ": Negative: VALID_TO passed in!\n";
5392  OT_FAIL;
5393  }
5394  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
5395  time64_t tValidFrom = VALID_FROM;
5396  time64_t tValidTo = VALID_TO;
5397  OTString strOutput;
5398 
5399  const bool& bCreated = OTAPI()->Create_SmartContract(
5400  theSignerNymID, tValidFrom, // Default (0 or "") == NOW
5401  tValidTo, // Default (0 or "") == no expiry / cancel anytime
5402  strOutput);
5403  if (!bCreated || !strOutput.Exists()) return "";
5404  // Success!
5405  //
5406  std::string pBuf = strOutput.Get();
5407  return pBuf;
5408 }
5409 
5410 //
5411 // todo: Someday add a parameter here BYLAW_LANGUAGE so that people can use
5412 // custom languages in their scripts. For now I have a default language, so
5413 // I'll just make that the default. (There's only one language right now
5414 // anyway.)
5415 //
5416 // returns: the updated smart contract (or "")
5418  const std::string& THE_CONTRACT, // The contract, about to have the bylaw
5419  // added to it.
5420  const std::string& SIGNER_NYM_ID, // Use any Nym you wish here. (The signing
5421  // at this point32_t is only to cause a
5422  // save.)
5423  const std::string& BYLAW_NAME) const // The Bylaw's NAME as referenced in
5424  // the
5425  // smart contract. (And the scripts...)
5426 {
5427  if (THE_CONTRACT.empty()) {
5428  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5429  OT_FAIL;
5430  }
5431  if (SIGNER_NYM_ID.empty()) {
5432  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
5433  OT_FAIL;
5434  }
5435  if (BYLAW_NAME.empty()) {
5436  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
5437  OT_FAIL;
5438  }
5439  const OTString strContract(THE_CONTRACT), strBylawName(BYLAW_NAME);
5440  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
5441  OTString strOutput;
5442 
5443  const bool& bAdded = OTAPI()->SmartContract_AddBylaw(
5444  strContract, // The contract, about to have the bylaw added to it.
5445  theSignerNymID, // Use any Nym you wish here. (The signing at this
5446  // point32_t is only to cause a save.)
5447  strBylawName, // The Bylaw's NAME as referenced in the smart contract.
5448  // (And the scripts...)
5449  strOutput);
5450  if (!bAdded || !strOutput.Exists()) return "";
5451  // Success!
5452  //
5453  std::string pBuf = strOutput.Get();
5454 
5455  return pBuf;
5456 }
5457 
5458 // returns: the updated smart contract (or "")
5460  const std::string& THE_CONTRACT, // The contract, about to have the clause
5461  // added to it.
5462  const std::string& SIGNER_NYM_ID, // Use any Nym you wish here. (The signing
5463  // at this point32_t is only to cause a
5464  // save.)
5465  const std::string& BYLAW_NAME, // Should already be on the contract. (This
5466  // way we can find it.)
5467  const std::string& CLAUSE_NAME, // The Clause's name as referenced in the
5468  // smart contract. (And the scripts...)
5469  const std::string& SOURCE_CODE) const // The actual source code for the
5470  // clause.
5471 {
5472  if (THE_CONTRACT.empty()) {
5473  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5474  OT_FAIL;
5475  }
5476  if (SIGNER_NYM_ID.empty()) {
5477  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
5478  OT_FAIL;
5479  }
5480  if (BYLAW_NAME.empty()) {
5481  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
5482  OT_FAIL;
5483  }
5484  if (CLAUSE_NAME.empty()) {
5485  otErr << __FUNCTION__ << ": Null: CLAUSE_NAME passed in!\n";
5486  OT_FAIL;
5487  }
5488  if (SOURCE_CODE.empty()) {
5489  otErr << __FUNCTION__ << ": Null: SOURCE_CODE passed in!\n";
5490  OT_FAIL;
5491  }
5492 
5493  const OTString strContract(THE_CONTRACT), strBylawName(BYLAW_NAME),
5494  strClauseName(CLAUSE_NAME), strSourceCode(SOURCE_CODE);
5495  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
5496  OTString strOutput;
5497 
5498  const bool& bAdded = OTAPI()->SmartContract_AddClause(
5499  strContract, // The contract, about to have the clause added to it.
5500  theSignerNymID, // Use any Nym you wish here. (The signing at this
5501  // point32_t is only to cause a save.)
5502  strBylawName, // Should already be on the contract. (This way we can
5503  // find it.)
5504  strClauseName, // The Clause's name as referenced in the smart contract.
5505  // (And the scripts...)
5506  strSourceCode, // The actual source code for the clause.
5507  strOutput);
5508  if (!bAdded || !strOutput.Exists()) return "";
5509  // Success!
5510  //
5511  std::string pBuf = strOutput.Get();
5512 
5513  return pBuf;
5514 }
5515 
5516 // returns: the updated smart contract (or "")
5518  const std::string& THE_CONTRACT, // The contract, about to have the variable
5519  // added to it.
5520  const std::string& SIGNER_NYM_ID, // Use any Nym you wish here. (The signing
5521  // at this point32_t is only to cause a
5522  // save.)
5523  const std::string& BYLAW_NAME, // Should already be on the contract. (This
5524  // way we can find it.)
5525  const std::string& VAR_NAME, // The Variable's name as referenced in the
5526  // smart contract. (And the scripts...)
5527  const std::string& VAR_ACCESS, // "constant", "persistent", or "important".
5528  const std::string& VAR_TYPE, // "string", "int64_t", or "bool"
5529  const std::string& VAR_VALUE) const // Contains a string. If type is
5530  // int64_t,
5531 // StringToLong() will be used to convert
5532 // value to a int64_t. If type is bool, the
5533 // strings "true" or "false" are expected here
5534 // in order to convert to a bool.
5535 {
5536  if (THE_CONTRACT.empty()) {
5537  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5538  OT_FAIL;
5539  }
5540  if (SIGNER_NYM_ID.empty()) {
5541  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
5542  OT_FAIL;
5543  }
5544  if (BYLAW_NAME.empty()) {
5545  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
5546  OT_FAIL;
5547  }
5548  if (VAR_NAME.empty()) {
5549  otErr << __FUNCTION__ << ": Null: VAR_NAME passed in!\n";
5550  OT_FAIL;
5551  }
5552  if (VAR_ACCESS.empty()) {
5553  otErr << __FUNCTION__ << ": Null: VAR_ACCESS passed in!\n";
5554  OT_FAIL;
5555  }
5556  if (VAR_TYPE.empty()) {
5557  otErr << __FUNCTION__ << ": Null: VAR_TYPE passed in!\n";
5558  OT_FAIL;
5559  }
5560  // if (VAR_VALUE.empty()) { otErr << __FUNCTION__ << ": Null:
5561  // VAR_VALUE passed
5562  // in!\n"; OT_FAIL; }
5563  const OTString strContract(THE_CONTRACT), strBylawName(BYLAW_NAME),
5564  strVarName(VAR_NAME), strVarAccess(VAR_ACCESS), strVarType(VAR_TYPE),
5565  strVarValue(VAR_VALUE);
5566  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
5567  OTString strOutput;
5568 
5569  const bool& bAdded = OTAPI()->SmartContract_AddVariable(
5570  strContract, // The contract, about to have the clause added to it.
5571  theSignerNymID, // Use any Nym you wish here. (The signing at this
5572  // point32_t is only to cause a save.)
5573  strBylawName, // Should already be on the contract. (This way we can
5574  // find it.)
5575  strVarName, // The Variable's name as referenced in the smart contract.
5576  // (And the scripts...)
5577  strVarAccess, // "constant", "persistent", or "important".
5578  strVarType, // "string", "int64_t", or "bool"
5579  strVarValue, // Contains a string. If type is int64_t, StringToLong()
5580  // will be used to convert value to a int64_t. If type is
5581  // bool, the strings "true" or "false" are expected here in
5582  // order to convert to a bool.
5583  strOutput);
5584  if (!bAdded || !strOutput.Exists()) return "";
5585  // Success!
5586  //
5587  std::string pBuf = strOutput.Get();
5588  return pBuf;
5589 }
5590 
5591 // returns: the updated smart contract (or "")
5593  const std::string& THE_CONTRACT, // The contract, about to have the callback
5594  // added to it.
5595  const std::string& SIGNER_NYM_ID, // Use any Nym you wish here. (The signing
5596  // at this point32_t is only to cause a
5597  // save.)
5598  const std::string& BYLAW_NAME, // Should already be on the contract. (This
5599  // way we can find it.)
5600  const std::string& CALLBACK_NAME, // The Callback's name as referenced in
5601  // the smart contract. (And the
5602  // scripts...)
5603  const std::string& CLAUSE_NAME) const // The actual clause that will be
5604  // triggered
5605  // by the callback. (Must exist.)
5606 {
5607  if (THE_CONTRACT.empty()) {
5608  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5609  OT_FAIL;
5610  }
5611  if (SIGNER_NYM_ID.empty()) {
5612  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
5613  OT_FAIL;
5614  }
5615  if (BYLAW_NAME.empty()) {
5616  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
5617  OT_FAIL;
5618  }
5619  if (CALLBACK_NAME.empty()) {
5620  otErr << __FUNCTION__ << ": Null: CALLBACK_NAME passed in!\n";
5621  OT_FAIL;
5622  }
5623  if (CLAUSE_NAME.empty()) {
5624  otErr << __FUNCTION__ << ": Null: CLAUSE_NAME passed in!\n";
5625  OT_FAIL;
5626  }
5627 
5628  const OTString strContract(THE_CONTRACT), strBylawName(BYLAW_NAME),
5629  strCallbackName(CALLBACK_NAME), strClauseName(CLAUSE_NAME);
5630  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
5631  OTString strOutput;
5632 
5633  const bool& bAdded = OTAPI()->SmartContract_AddCallback(
5634  strContract, // The contract, about to have the clause added to it.
5635  theSignerNymID, // Use any Nym you wish here. (The signing at this
5636  // point32_t is only to cause a save.)
5637  strBylawName, // Should already be on the contract. (This way we can
5638  // find it.)
5639  strCallbackName, // The Callback's name as referenced in the smart
5640  // contract. (And the scripts...)
5641  strClauseName, // The actual clause that will be triggered by the
5642  // callback. (Must exist.)
5643  strOutput);
5644  if (!bAdded || !strOutput.Exists()) return "";
5645  // Success!
5646  //
5647  std::string pBuf = strOutput.Get();
5648 
5649  return pBuf;
5650 }
5651 
5652 // returns: the updated smart contract (or "")
5654  const std::string& THE_CONTRACT, // The contract, about to have the hook
5655  // added to it.
5656  const std::string& SIGNER_NYM_ID, // Use any Nym you wish here. (The signing
5657  // at this point32_t is only to cause a
5658  // save.)
5659  const std::string& BYLAW_NAME, // Should already be on the contract. (This
5660  // way we can find it.)
5661  const std::string& HOOK_NAME, // The Hook's name as referenced in the smart
5662  // contract. (And the scripts...)
5663  const std::string& CLAUSE_NAME) const // The actual clause that will be
5664  // triggered
5665 // by the hook. (You can call this multiple
5666 // times, and have multiple clauses trigger
5667 // on the same hook.)
5668 {
5669  if (THE_CONTRACT.empty()) {
5670  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5671  OT_FAIL;
5672  }
5673  if (SIGNER_NYM_ID.empty()) {
5674  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
5675  OT_FAIL;
5676  }
5677  if (BYLAW_NAME.empty()) {
5678  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
5679  OT_FAIL;
5680  }
5681  if (HOOK_NAME.empty()) {
5682  otErr << __FUNCTION__ << ": Null: HOOK_NAME passed in!\n";
5683  OT_FAIL;
5684  }
5685  if (CLAUSE_NAME.empty()) {
5686  otErr << __FUNCTION__ << ": Null: CLAUSE_NAME passed in!\n";
5687  OT_FAIL;
5688  }
5689 
5690  const OTString strContract(THE_CONTRACT), strBylawName(BYLAW_NAME),
5691  strHookName(HOOK_NAME), strClauseName(CLAUSE_NAME);
5692  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
5693  OTString strOutput;
5694 
5695  const bool& bAdded = OTAPI()->SmartContract_AddHook(
5696  strContract, // The contract, about to have the clause added to it.
5697  theSignerNymID, // Use any Nym you wish here. (The signing at this
5698  // point32_t is only to cause a save.)
5699  strBylawName, // Should already be on the contract. (This way we can
5700  // find it.)
5701  strHookName, // The Hook's name as referenced in the smart contract.
5702  // (And the scripts...)
5703  strClauseName, // The actual clause that will be triggered by the hook.
5704  // (You can call this multiple times, and have multiple
5705  // clauses trigger on the same hook.)
5706  strOutput);
5707  if (!bAdded || !strOutput.Exists()) return "";
5708  // Success!
5709  //
5710  std::string pBuf = strOutput.Get();
5711 
5712  return pBuf;
5713 }
5714 
5715 // RETURNS: Updated version of THE_CONTRACT. (Or "".)
5717  const std::string& THE_CONTRACT, // The contract, about to have the party
5718  // added to it.
5719  const std::string& SIGNER_NYM_ID, // Use any Nym you wish here. (The signing
5720  // at this point32_t is only to cause a
5721  // save.)
5722  const std::string& PARTY_NAME, // The Party's NAME as referenced in the
5723  // smart contract. (And the scripts...)
5724  const std::string& AGENT_NAME) const // An AGENT will be added by default
5725  // for this
5726  // party. Need Agent NAME.
5727 // (FYI, that is basically the only option, until I code Entities and Roles.
5728 // Until then, a party can ONLY be
5729 // a Nym, with himself as the agent representing that same party. Nym ID is
5730 // supplied on ConfirmParty() below.)
5731 {
5732  if (THE_CONTRACT.empty()) {
5733  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5734  OT_FAIL;
5735  }
5736  if (SIGNER_NYM_ID.empty()) {
5737  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
5738  OT_FAIL;
5739  }
5740  if (PARTY_NAME.empty()) {
5741  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
5742  OT_FAIL;
5743  }
5744  if (AGENT_NAME.empty()) {
5745  otErr << __FUNCTION__ << ": Null: AGENT_NAME passed in!\n";
5746  OT_FAIL;
5747  }
5748  const OTString strContract(THE_CONTRACT), strPartyName(PARTY_NAME),
5749  strAgentName(AGENT_NAME);
5750  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
5751  OTString strOutput;
5752 
5753  const bool& bAdded = OTAPI()->SmartContract_AddParty(
5754  strContract, // The contract, about to have the bylaw added to it.
5755  theSignerNymID, // Use any Nym you wish here. (The signing at this
5756  // point32_t is only to cause a save.)
5757  strPartyName, // The Party's NAME as referenced in the smart contract.
5758  // (And the scripts...)
5759  strAgentName, // An AGENT will be added by default for this party. Need
5760  // Agent NAME.
5761  strOutput);
5762  if (!bAdded || !strOutput.Exists()) return "";
5763  // Success!
5764  //
5765  std::string pBuf = strOutput.Get();
5766  return pBuf;
5767 }
5768 
5769 // Used when creating a theoretical smart contract (that could be used over and
5770 // over again with different parties.)
5771 //
5772 // returns: the updated smart contract (or "")
5774  const std::string& THE_CONTRACT, // The contract, about to have the account
5775  // added to it.
5776  const std::string& SIGNER_NYM_ID, // Use any Nym you wish here. (The signing
5777  // at this point32_t is only to cause a
5778  // save.)
5779  const std::string& PARTY_NAME, // The Party's NAME as referenced in the
5780  // smart contract. (And the scripts...)
5781  const std::string& ACCT_NAME, // The Account's name as referenced in the
5782  // smart contract
5783  const std::string& ASSET_TYPE_ID) const // Asset Type ID for the Account.
5784 {
5785  if (THE_CONTRACT.empty()) {
5786  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5787  OT_FAIL;
5788  }
5789  if (SIGNER_NYM_ID.empty()) {
5790  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
5791  OT_FAIL;
5792  }
5793  if (PARTY_NAME.empty()) {
5794  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
5795  OT_FAIL;
5796  }
5797  if (ACCT_NAME.empty()) {
5798  otErr << __FUNCTION__ << ": Null: ACCT_NAME passed in!\n";
5799  OT_FAIL;
5800  }
5801  // if (ASSET_TYPE_ID.empty()) { otErr << __FUNCTION__ << ": Null:
5802  // ASSET_TYPE_ID passed
5803  // in!\n"; OT_FAIL; }
5804 
5805  const OTString strContract(THE_CONTRACT), strPartyName(PARTY_NAME),
5806  strAcctName(ACCT_NAME), strAssetTypeID(ASSET_TYPE_ID);
5807  const OTIdentifier theSignerNymID(SIGNER_NYM_ID);
5808  OTString strOutput;
5809 
5810  const bool& bAdded = OTAPI()->SmartContract_AddAccount(
5811  strContract, // The contract, about to have the clause added to it.
5812  theSignerNymID, // Use any Nym you wish here. (The signing at this
5813  // point32_t is only to cause a save.)
5814  strPartyName, // The Party's NAME as referenced in the smart contract.
5815  // (And the scripts...)
5816  strAcctName, // The Account's name as referenced in the smart contract
5817  strAssetTypeID, // Asset Type ID for the Account.
5818  strOutput);
5819  if (!bAdded || !strOutput.Exists()) return "";
5820  // Success!
5821  //
5822  std::string pBuf = strOutput.Get();
5823 
5824  return pBuf;
5825 }
5826 
5827 // This function returns the count of how many trans#s a Nym needs in order to
5828 // confirm as
5829 // a specific agent for a contract. (An opening number is needed for every party
5830 // of which
5831 // agent is the authorizing agent, plus a closing number for every acct of which
5832 // agent is the
5833 // authorized agent.)
5834 //
5835 // Otherwise a Nym might try to confirm a smart contract and be unable to, since
5836 // he doesn't
5837 // have enough transaction numbers, yet he would have no way of finding out HOW
5838 // MANY HE *DOES*
5839 // NEED. This function allows him to find out, before confirmation, so he can
5840 // first grab however
5841 // many transaction#s he will need in order to confirm this smart contract.
5842 //
5844  const std::string& THE_CONTRACT, // The smart contract, about to be queried
5845  // by this function.
5846  const std::string& AGENT_NAME) const
5847 {
5848  if (THE_CONTRACT.empty()) {
5849  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5850  OT_FAIL;
5851  }
5852  if (AGENT_NAME.empty()) {
5853  otErr << __FUNCTION__ << ": Null: AGENT_NAME passed in!\n";
5854  OT_FAIL;
5855  }
5856  const OTString strContract(THE_CONTRACT), strAgentName(AGENT_NAME);
5857  //
5858  const int32_t& nCount =
5859  OTAPI()->SmartContract_CountNumsNeeded(strContract, strAgentName);
5860 
5861  return nCount;
5862 }
5863 
5864 // Used when taking a theoretical smart contract, and setting it up to use
5865 // specific Nyms and accounts.
5866 // This function sets the ACCT ID and the AGENT NAME for the acct specified by
5867 // party name and acct name.
5868 // Returns the updated smart contract (or "".)
5869 //
5871  const std::string& THE_CONTRACT, const std::string& SIGNER_NYM_ID,
5872  const std::string& PARTY_NAME, // Should already be on the contract.
5873  const std::string& ACCT_NAME, // Should already be on the contract.
5874  const std::string& AGENT_NAME, // The agent name for this asset account.
5875  const std::string& ACCT_ID) const // AcctID for the asset account. (For
5876  // acct_name).
5877 {
5878  if (THE_CONTRACT.empty()) {
5879  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5880  OT_FAIL;
5881  }
5882  if (SIGNER_NYM_ID.empty()) {
5883  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
5884  OT_FAIL;
5885  }
5886  if (PARTY_NAME.empty()) {
5887  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
5888  OT_FAIL;
5889  }
5890  if (ACCT_NAME.empty()) {
5891  otErr << __FUNCTION__ << ": Null: ACCT_NAME passed in!\n";
5892  OT_FAIL;
5893  }
5894  if (AGENT_NAME.empty()) {
5895  otErr << __FUNCTION__ << ": Null: AGENT_NAME passed in!\n";
5896  OT_FAIL;
5897  }
5898  if (ACCT_ID.empty()) {
5899  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
5900  OT_FAIL;
5901  }
5902  const OTString strContract(THE_CONTRACT), strPartyName(PARTY_NAME);
5903  const OTString strAccountID(ACCT_ID), strAcctName(ACCT_NAME),
5904  strAgentName(AGENT_NAME);
5905  const OTIdentifier theSignerNymID(SIGNER_NYM_ID), theAcctID(strAccountID);
5906  OTString strOutput;
5907 
5908  const bool& bConfirmed = OTAPI()->SmartContract_ConfirmAccount(
5909  strContract, theSignerNymID, strPartyName, strAcctName, strAgentName,
5910  strAccountID, strOutput);
5911  if (!bConfirmed || !strOutput.Exists()) return "";
5912  // Success!
5913  //
5914  std::string pBuf = strOutput.Get();
5915  return pBuf;
5916 }
5917 
5918 // Called by each Party. Pass in the smart contract obtained in the above call.
5919 // Call OTAPI_Exec::SmartContract_ConfirmAccount() first, as much as you need
5920 // to, THEN call this (for final signing.)
5921 // This is the last call you make before either passing it on to another party
5922 // to confirm, or calling OTAPI_Exec::activateSmartContract().
5923 // Returns the updated smart contract (or "".)
5925  const std::string& THE_CONTRACT, // The smart contract, about to be changed
5926  // by this function.
5927  const std::string& PARTY_NAME, // Should already be on the contract. This
5928  // way we can find it.
5929  const std::string& NYM_ID) const // Nym ID for the party, the actual owner,
5930 // ===> AS WELL AS for the default AGENT of that party. (For now, until I code
5931 // entities)
5932 {
5933  if (THE_CONTRACT.empty()) {
5934  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5935  OT_FAIL;
5936  }
5937  if (PARTY_NAME.empty()) {
5938  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
5939  OT_FAIL;
5940  }
5941  if (NYM_ID.empty()) {
5942  otErr << __FUNCTION__ << ": Null: NYM_ID passed in!\n";
5943  OT_FAIL;
5944  }
5945  const OTIdentifier theNymID(NYM_ID);
5946  const OTString strContract(THE_CONTRACT), strPartyName(PARTY_NAME);
5947  OTString strOutput;
5948 
5949  const bool& bConfirmed = OTAPI()->SmartContract_ConfirmParty(
5950  strContract, // The smart contract, about to be changed by this
5951  // function.
5952  strPartyName, // Should already be on the contract. This way we can find
5953  // it.
5954  theNymID, // Nym ID for the party, the actual owner,
5955  strOutput);
5956  if (!bConfirmed || !strOutput.Exists()) return "";
5957  // Success!
5958  //
5959  std::string pBuf = strOutput.Get();
5960  return pBuf;
5961 }
5962 
5964  const std::string& THE_CONTRACT) const // true or false?
5965 {
5966  if (THE_CONTRACT.empty()) {
5967  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
5968  OT_FAIL;
5969  }
5970  OTString strContract(THE_CONTRACT);
5971  std::unique_ptr<OTScriptable> pScriptable(
5973  if (nullptr == pScriptable) {
5974  otOut << __FUNCTION__
5975  << ": Failed trying to load smart contract from string : \n\n"
5976  << strContract << "\n\n";
5977  }
5978  else {
5979  const bool bConfirmed =
5980  pScriptable->AllPartiesHaveSupposedlyConfirmed();
5981  const bool bVerified =
5983  if (!bConfirmed) {
5984  // otOut << __FUNCTION__ << ": Smart contract loaded up,
5985  // but all
5986  // parties are NOT confirmed:\n\n" << strContract << "\n\n";
5987  otWarn << __FUNCTION__ << ": Smart contract loaded up, but all "
5988  "parties are NOT confirmed.\n";
5989  return false;
5990  }
5991  else if (bVerified) {
5992  // otOut << __FUNCTION__ << ": Success: Smart contract
5993  // loaded
5994  // up, and all parties have confirmed,\n"
5995  // "AND their signed versions verified
5996  // also.\n";
5997 
5998  // Todo security: We have confirmed that all parties have provided
5999  // signed copies, but we have
6000  // not actually verified the signatures themselves. (Though we HAVE
6001  // verified that their copies of
6002  // the contract match the main copy.)
6003  // The server DOES verify this before activation, but the client
6004  // should as well, just in case. Todo.
6005  // (I'd want MY client to do it...)
6006  //
6007  return true;
6008  }
6009  otOut << __FUNCTION__
6010  << ": Suspicious: Smart contract loaded up, and is supposedly "
6011  "confirmed by all parties, but failed to verify:\n\n"
6012  << strContract << "\n\n";
6013  }
6014  return false;
6015 }
6016 
6018  const std::string& THE_CONTRACT,
6019  const std::string& PARTY_NAME) const // true
6020  // or
6021  // false?
6022 {
6023  if (THE_CONTRACT.empty()) {
6024  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6025  OT_FAIL;
6026  }
6027  if (PARTY_NAME.empty()) {
6028  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
6029  OT_FAIL;
6030  }
6031  const OTString strContract(THE_CONTRACT);
6032  std::unique_ptr<OTScriptable> pScriptable(
6034  if (nullptr == pScriptable) {
6035  otOut << __FUNCTION__
6036  << ": Failed trying to load smart contract from string : \n\n"
6037  << strContract << "\n\n";
6038  }
6039  else {
6040  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
6041  if (nullptr == pParty) {
6042  otOut << __FUNCTION__
6043  << ": Smart contract loaded up, but failed to find a party "
6044  "with the name: " << PARTY_NAME << "\n";
6045  }
6046  else // We found the party...
6047  {
6048  //...is he confirmed?
6049  //
6050  if (!pParty->GetMySignedCopy().Exists()) {
6051  otWarn << __FUNCTION__
6052  << ": Smart contract loaded up, and party " << PARTY_NAME
6053  << " was found, but didn't find a signed copy of the "
6054  "agreement for that party.\n";
6055  }
6056  else // FYI, this block comes from
6057  // OTScriptable::VerifyThisAgainstAllPartiesSignedCopies.
6058  {
6059  std::unique_ptr<OTScriptable> pPartySignedCopy(
6061  pParty->GetMySignedCopy()));
6062 
6063  if (nullptr == pPartySignedCopy) {
6064  const std::string current_party_name(
6065  pParty->GetPartyName());
6066  otErr << __FUNCTION__ << ": Error loading party's ("
6067  << current_party_name
6068  << ") signed copy of agreement. Has it been "
6069  "executed?\n";
6070  }
6071  else {
6072  if (!pScriptable->Compare(*pPartySignedCopy)) {
6073  const std::string current_party_name(
6074  pParty->GetPartyName());
6075  otErr << __FUNCTION__ << ": Suspicious: Party's ("
6076  << current_party_name
6077  << ") signed copy of agreement doesn't match the "
6078  "contract.\n";
6079  }
6080  else {
6081  // TODO Security: This function doesn't actually verify
6082  // the party's SIGNATURE on his signed
6083  // version, only that it exists and it matches the main
6084  // contract.
6085  //
6086  // The actual signatures are all verified by the server
6087  // before activation, but I'd still like the client
6088  // to have the option to do so as well. I can imagine
6089  // getting someone's signature on something (without
6090  // signing it yourself) and then just retaining the
6091  // OPTION to sign it later -- but he might not have
6092  // actually signed it if he knew that you hadn't either.
6093  // He'd want his client to tell him, if this were
6094  // the case. Todo.
6095 
6096  return true;
6097  }
6098  }
6099  }
6100  }
6101  }
6102  return false;
6103 }
6104 
6105 int32_t OTAPI_Exec::Smart_GetPartyCount(const std::string& THE_CONTRACT) const
6106 {
6107  if (THE_CONTRACT.empty()) {
6108  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6109  OT_FAIL;
6110  }
6111  OTString strContract(THE_CONTRACT);
6112  std::unique_ptr<OTScriptable> pScriptable(
6114  if (nullptr == pScriptable) {
6115  otOut << __FUNCTION__
6116  << " Failed trying to load smart contract from string:\n\n"
6117  << strContract << "\n\n";
6118  }
6119  else {
6120  const int32_t nReturnValue =
6121  static_cast<int32_t>(pScriptable->GetPartyCount());
6122  return nReturnValue;
6123  }
6124  return -1; // Error condition.
6125 }
6126 
6127 int32_t OTAPI_Exec::Smart_GetBylawCount(const std::string& THE_CONTRACT) const
6128 {
6129  if (THE_CONTRACT.empty()) {
6130  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6131  OT_FAIL;
6132  }
6133  OTString strContract(THE_CONTRACT);
6134  std::unique_ptr<OTScriptable> pScriptable(
6136  if (nullptr == pScriptable) {
6137  otOut << __FUNCTION__
6138  << ": Failed trying to load smart contract from string : \n\n"
6139  << strContract << "\n\n";
6140  }
6141  else {
6142  const int32_t nReturnValue =
6143  static_cast<int32_t>(pScriptable->GetBylawCount());
6144  return nReturnValue;
6145  }
6146  return -1; // Error condition.
6147 }
6148 
6150 std::string OTAPI_Exec::Smart_GetPartyByIndex(const std::string& THE_CONTRACT,
6151  const int32_t& nIndex) const
6152 {
6153  if (THE_CONTRACT.empty()) {
6154  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6155  OT_FAIL;
6156  }
6157  const OTString strContract(THE_CONTRACT);
6158  std::unique_ptr<OTScriptable> pScriptable(
6160  if (nullptr == pScriptable) {
6161  otOut << __FUNCTION__
6162  << ": Failed trying to load smart contract from string:\n\n"
6163  << strContract << "\n\n";
6164  }
6165  else {
6166  const int32_t nTempIndex = static_cast<const int32_t>(nIndex);
6167  OTParty* pParty = pScriptable->GetPartyByIndex(
6168  nTempIndex); // has range-checking built-in.
6169  if (nullptr == pParty) {
6170  otOut << __FUNCTION__
6171  << ": Smart contract loaded up, but failed to retrieve the "
6172  "party using index: " << nTempIndex << "\n";
6173  }
6174  else // We found the party...
6175  {
6176  return pParty->GetPartyName();
6177  }
6178  }
6179  return "";
6180 }
6181 
6183 std::string OTAPI_Exec::Smart_GetBylawByIndex(const std::string& THE_CONTRACT,
6184  const int32_t& nIndex) const
6185 {
6186  if (THE_CONTRACT.empty()) {
6187  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6188  OT_FAIL;
6189  }
6190  const OTString strContract(THE_CONTRACT);
6191  std::unique_ptr<OTScriptable> pScriptable(
6193  if (nullptr == pScriptable) {
6194  otOut << __FUNCTION__
6195  << ": Failed trying to load smart contract from string : \n\n"
6196  << strContract << "\n\n";
6197  }
6198  else {
6199  const int32_t nTempIndex = static_cast<const int32_t>(nIndex);
6200  OTBylaw* pBylaw = pScriptable->GetBylawByIndex(
6201  nTempIndex); // has range-checking built-in.
6202  if (nullptr == pBylaw) {
6203  otOut << __FUNCTION__
6204  << ": Smart contract loaded up, but failed to retrieve the "
6205  "bylaw using index: " << nTempIndex << "\n";
6206  }
6207  else // We found the bylaw...
6208  {
6209  const std::string str_name(pBylaw->GetName().Get()); // Success.
6210  return str_name;
6211  }
6212  }
6213  return "";
6214 }
6215 
6216 std::string OTAPI_Exec::Bylaw_GetLanguage(const std::string& THE_CONTRACT,
6217  const std::string& BYLAW_NAME) const
6218 {
6219  if (THE_CONTRACT.empty()) {
6220  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6221  OT_FAIL;
6222  }
6223  if (BYLAW_NAME.empty()) {
6224  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6225  OT_FAIL;
6226  }
6227  OTString strContract(THE_CONTRACT);
6228  std::unique_ptr<OTScriptable> pScriptable(
6230  if (nullptr == pScriptable) {
6231  otOut << __FUNCTION__
6232  << ": Failed trying to load smart contract from string : \n\n"
6233  << strContract << "\n\n";
6234  }
6235  else {
6236  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6237  if (nullptr == pBylaw) {
6238  otOut << __FUNCTION__
6239  << ": Smart contract loaded up, but failed to find a bylaw "
6240  "with the name: " << BYLAW_NAME << "\n";
6241  }
6242  else // We found the bylaw...
6243  {
6244  const std::string str_return(nullptr == pBylaw->GetLanguage()
6245  ? "error_no_language"
6246  : pBylaw->GetLanguage());
6247  return str_return;
6248  }
6249  }
6250  return "";
6251 }
6252 
6253 int32_t OTAPI_Exec::Bylaw_GetClauseCount(const std::string& THE_CONTRACT,
6254  const std::string& BYLAW_NAME) const
6255 {
6256  if (THE_CONTRACT.empty()) {
6257  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6258  OT_FAIL;
6259  }
6260  if (BYLAW_NAME.empty()) {
6261  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6262  OT_FAIL;
6263  }
6264  OTString strContract(THE_CONTRACT);
6265  std::unique_ptr<OTScriptable> pScriptable(
6267  if (nullptr == pScriptable) {
6268  otOut << __FUNCTION__
6269  << ": Failed trying to load smart contract from string : \n\n"
6270  << strContract << "\n\n";
6271  }
6272  else {
6273  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6274  if (nullptr == pBylaw) {
6275  otOut << __FUNCTION__
6276  << ": Smart contract loaded up, but failed to find a bylaw "
6277  "with the name: " << BYLAW_NAME << "\n";
6278  }
6279  else // We found the bylaw...
6280  {
6281  const int32_t nReturnValue =
6282  static_cast<int32_t>(pBylaw->GetClauseCount());
6283  return nReturnValue;
6284  }
6285  }
6286  return (-1);
6287 }
6288 
6289 int32_t OTAPI_Exec::Bylaw_GetVariableCount(const std::string& THE_CONTRACT,
6290  const std::string& BYLAW_NAME) const
6291 {
6292  if (THE_CONTRACT.empty()) {
6293  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6294  OT_FAIL;
6295  }
6296  if (BYLAW_NAME.empty()) {
6297  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6298  OT_FAIL;
6299  }
6300  OTString strContract(THE_CONTRACT);
6301  std::unique_ptr<OTScriptable> pScriptable(
6303  if (nullptr == pScriptable) {
6304  otOut << __FUNCTION__
6305  << ": Failed trying to load smart contract from string : \n\n"
6306  << strContract << "\n\n";
6307  }
6308  else {
6309  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6310  if (nullptr == pBylaw) {
6311  otOut << __FUNCTION__
6312  << ": Smart contract loaded up, but failed to find a bylaw "
6313  "with the name: " << BYLAW_NAME << "\n";
6314  }
6315  else // We found the bylaw...
6316  {
6317  const int32_t nReturnValue =
6318  static_cast<int32_t>(pBylaw->GetVariableCount());
6319  return nReturnValue;
6320  }
6321  }
6322  return (-1);
6323 }
6324 
6325 int32_t OTAPI_Exec::Bylaw_GetHookCount(const std::string& THE_CONTRACT,
6326  const std::string& BYLAW_NAME) const
6327 {
6328  if (THE_CONTRACT.empty()) {
6329  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6330  OT_FAIL;
6331  }
6332  if (BYLAW_NAME.empty()) {
6333  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6334  OT_FAIL;
6335  }
6336  OTString strContract(THE_CONTRACT);
6337  std::unique_ptr<OTScriptable> pScriptable(
6339  if (nullptr == pScriptable) {
6340  otOut << __FUNCTION__
6341  << ": Failed trying to load smart contract from string : \n\n"
6342  << strContract << "\n\n";
6343  }
6344  else {
6345  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6346  if (nullptr == pBylaw) {
6347  otOut << __FUNCTION__
6348  << ": Smart contract loaded up, but failed to find a bylaw "
6349  "with the name: " << BYLAW_NAME << "\n";
6350  }
6351  else // We found the bylaw...
6352  {
6353  const int32_t nReturnValue =
6354  static_cast<int32_t>(pBylaw->GetHookCount());
6355  return nReturnValue;
6356  }
6357  }
6358  return (-1);
6359 }
6360 
6361 int32_t OTAPI_Exec::Bylaw_GetCallbackCount(const std::string& THE_CONTRACT,
6362  const std::string& BYLAW_NAME) const
6363 {
6364  if (THE_CONTRACT.empty()) {
6365  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6366  OT_FAIL;
6367  }
6368  if (BYLAW_NAME.empty()) {
6369  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6370  OT_FAIL;
6371  }
6372  OTString strContract(THE_CONTRACT);
6373  std::unique_ptr<OTScriptable> pScriptable(
6375  if (nullptr == pScriptable) {
6376  otOut << __FUNCTION__
6377  << ": Failed trying to load smart contract from string:\n\n"
6378  << strContract << "\n\n";
6379  }
6380  else {
6381  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6382  if (nullptr == pBylaw) {
6383  otOut << __FUNCTION__
6384  << ": Smart contract loaded up, but failed to find a bylaw "
6385  "with the name: " << BYLAW_NAME << "\n";
6386  }
6387  else // We found the bylaw...
6388  {
6389  const int32_t nReturnValue =
6390  static_cast<int32_t>(pBylaw->GetCallbackCount());
6391  return nReturnValue;
6392  }
6393  }
6394  return (-1);
6395 }
6396 
6398  const std::string& THE_CONTRACT, const std::string& BYLAW_NAME,
6399  const int32_t& nIndex) const // returns the name of the clause.
6400 {
6401  if (THE_CONTRACT.empty()) {
6402  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6403  OT_FAIL;
6404  }
6405  if (BYLAW_NAME.empty()) {
6406  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6407  OT_FAIL;
6408  }
6409  const OTString strContract(THE_CONTRACT);
6410  std::unique_ptr<OTScriptable> pScriptable(
6412  if (nullptr == pScriptable) {
6413  otOut << __FUNCTION__
6414  << ": Failed trying to load smart contract from string:\n\n"
6415  << strContract << "\n\n";
6416  }
6417  else {
6418  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6419  if (nullptr == pBylaw) {
6420  otOut << __FUNCTION__
6421  << ": Smart contract loaded up, but failed to retrieve the "
6422  "bylaw with name: " << BYLAW_NAME << "\n";
6423  }
6424  else // We found the bylaw...
6425  {
6426  const int32_t nTempIndex = static_cast<const int32_t>(nIndex);
6427 
6428  OTClause* pClause = pBylaw->GetClauseByIndex(nTempIndex);
6429 
6430  if (nullptr == pClause) {
6431  otOut << __FUNCTION__ << ": Smart contract loaded up, and "
6432  "bylaw found, but failed to retrieve "
6433  "the clause at index: " << nTempIndex
6434  << "\n";
6435  }
6436  else // We found the clause...
6437  {
6438  const std::string str_name(
6439  pClause->GetName().Get()); // Success.
6440  return str_name;
6441  }
6442  }
6443  }
6444  return "";
6445 }
6446 
6448  const std::string& THE_CONTRACT, const std::string& BYLAW_NAME,
6449  const std::string& CLAUSE_NAME) const // returns the contents of the clause.
6450 {
6451  if (THE_CONTRACT.empty()) {
6452  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6453  OT_FAIL;
6454  }
6455  if (BYLAW_NAME.empty()) {
6456  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6457  OT_FAIL;
6458  }
6459  if (CLAUSE_NAME.empty()) {
6460  otErr << __FUNCTION__ << ": Null: CLAUSE_NAME passed in!\n";
6461  OT_FAIL;
6462  }
6463  const OTString strContract(THE_CONTRACT);
6464  std::unique_ptr<OTScriptable> pScriptable(
6466  if (nullptr == pScriptable) {
6467  otOut << __FUNCTION__
6468  << ": Failed trying to load smart contract from string:\n\n"
6469  << strContract << "\n\n";
6470  }
6471  else {
6472  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6473  if (nullptr == pBylaw) {
6474  otOut << __FUNCTION__
6475  << ": Smart contract loaded up, but failed to retrieve the "
6476  "bylaw with name: " << BYLAW_NAME << "\n";
6477  }
6478  else // We found the bylaw...
6479  {
6480  OTClause* pClause = pBylaw->GetClause(CLAUSE_NAME);
6481 
6482  if (nullptr == pClause) {
6483  otOut << __FUNCTION__ << ": Smart contract loaded up, and "
6484  "bylaw found, but failed to retrieve "
6485  "the clause with name: " << CLAUSE_NAME
6486  << "\n";
6487  }
6488  else // We found the clause...
6489  {
6490  const std::string str_return(pClause->GetCode()); // Success.
6491  return str_return;
6492  }
6493  }
6494  }
6495  return "";
6496 }
6497 
6499  const std::string& THE_CONTRACT, const std::string& BYLAW_NAME,
6500  const int32_t& nIndex) const // returns the name of the variable.
6501 {
6502  if (THE_CONTRACT.empty()) {
6503  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6504  OT_FAIL;
6505  }
6506  if (BYLAW_NAME.empty()) {
6507  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6508  OT_FAIL;
6509  }
6510  const OTString strContract(THE_CONTRACT);
6511  std::unique_ptr<OTScriptable> pScriptable(
6513  if (nullptr == pScriptable) {
6514  otOut << __FUNCTION__
6515  << ": Failed trying to load smart contract from string:\n\n"
6516  << strContract << "\n\n";
6517  }
6518  else {
6519  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6520  if (nullptr == pBylaw) {
6521  otOut << __FUNCTION__
6522  << ": Smart contract loaded up, but failed to retrieve the "
6523  "bylaw with name: " << BYLAW_NAME << "\n";
6524  }
6525  else // We found the bylaw...
6526  {
6527  const int32_t nTempIndex = static_cast<const int32_t>(nIndex);
6528 
6529  OTVariable* pVar = pBylaw->GetVariableByIndex(nTempIndex);
6530 
6531  if (nullptr == pVar) {
6532  otOut << __FUNCTION__ << ": Smart contract loaded up, and "
6533  "bylaw found, but failed to retrieve "
6534  "the variable at index: " << nTempIndex
6535  << "\n";
6536  }
6537  else // We found the variable...
6538  {
6539  const std::string str_name(pVar->GetName().Get()); // Success.
6540  return str_name;
6541  }
6542  }
6543  }
6544  return "";
6545 }
6546 
6548  const std::string& THE_CONTRACT, const std::string& BYLAW_NAME,
6549  const std::string& VARIABLE_NAME) const // returns the type of the variable.
6550 {
6551  if (THE_CONTRACT.empty()) {
6552  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6553  OT_FAIL;
6554  }
6555  if (BYLAW_NAME.empty()) {
6556  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6557  OT_FAIL;
6558  }
6559  if (VARIABLE_NAME.empty()) {
6560  otErr << __FUNCTION__ << ": Null: VARIABLE_NAME passed in!\n";
6561  OT_FAIL;
6562  }
6563  const OTString strContract(THE_CONTRACT);
6564  std::unique_ptr<OTScriptable> pScriptable(
6566  if (nullptr == pScriptable) {
6567  otOut << __FUNCTION__
6568  << ": Failed trying to load smart contract from string:\n\n"
6569  << strContract << "\n\n";
6570  }
6571  else {
6572  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6573  if (nullptr == pBylaw) {
6574  otOut << __FUNCTION__
6575  << ": Smart contract loaded up, but failed to retrieve the "
6576  "bylaw with name: " << BYLAW_NAME << "\n";
6577  }
6578  else // We found the bylaw...
6579  {
6580  OTVariable* pVar = pBylaw->GetVariable(VARIABLE_NAME);
6581 
6582  if (nullptr == pVar) {
6583  otOut << __FUNCTION__
6584  << ": Smart contract loaded up, and bylaw found, but "
6585  "failed to retrieve the variable with name: "
6586  << VARIABLE_NAME << "\n";
6587  }
6588  else // We found the variable...
6589  {
6590  const std::string str_return(
6591  pVar->IsInteger()
6592  ? "integer"
6593  : (pVar->IsBool() ? "boolean"
6594  : (pVar->IsString()
6595  ? "string"
6596  : "error_type"))); // Success.
6597  return str_return;
6598  }
6599  }
6600  }
6601  return "";
6602 }
6603 
6605  const std::string& THE_CONTRACT, const std::string& BYLAW_NAME,
6606  const std::string& VARIABLE_NAME) const // returns the access level of the
6607  // variable.
6608 {
6609  if (THE_CONTRACT.empty()) {
6610  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6611  OT_FAIL;
6612  }
6613  if (BYLAW_NAME.empty()) {
6614  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6615  OT_FAIL;
6616  }
6617  if (VARIABLE_NAME.empty()) {
6618  otErr << __FUNCTION__ << ": Null: VARIABLE_NAME passed in!\n";
6619  OT_FAIL;
6620  }
6621  const OTString strContract(THE_CONTRACT);
6622  std::unique_ptr<OTScriptable> pScriptable(
6624  if (nullptr == pScriptable) {
6625  otOut << __FUNCTION__
6626  << ": Failed trying to load smart contract from string:\n\n"
6627  << strContract << "\n\n";
6628  }
6629  else {
6630  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6631  if (nullptr == pBylaw) {
6632  otOut << __FUNCTION__
6633  << ": Smart contract loaded up, but failed to retrieve the "
6634  "bylaw with name: " << BYLAW_NAME << "\n";
6635  }
6636  else // We found the bylaw...
6637  {
6638  OTVariable* pVar = pBylaw->GetVariable(VARIABLE_NAME);
6639 
6640  if (nullptr == pVar) {
6641  otOut << __FUNCTION__
6642  << ": Smart contract loaded up, and bylaw found, but "
6643  "failed to retrieve the variable with name: "
6644  << VARIABLE_NAME << "\n";
6645  }
6646  else // We found the variable...
6647  {
6648  const std::string str_return(
6649  pVar->IsConstant()
6650  ? "constant"
6651  : (pVar->IsImportant()
6652  ? "important"
6653  : (pVar->IsPersistent()
6654  ? "persistent"
6655  : "error_access"))); // Success.
6656  return str_return;
6657  }
6658  }
6659  }
6660  return "";
6661 }
6662 
6663 std::string OTAPI_Exec::Variable_GetContents(const std::string& THE_CONTRACT,
6664  const std::string& BYLAW_NAME,
6665  const std::string& VARIABLE_NAME)
6666  const // returns the contents of the variable.
6667 {
6668  if (THE_CONTRACT.empty()) {
6669  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6670  OT_FAIL;
6671  }
6672  if (BYLAW_NAME.empty()) {
6673  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6674  OT_FAIL;
6675  }
6676  if (VARIABLE_NAME.empty()) {
6677  otErr << __FUNCTION__ << ": Null: VARIABLE_NAME passed in!\n";
6678  OT_FAIL;
6679  }
6680  const OTString strContract(THE_CONTRACT);
6681  std::unique_ptr<OTScriptable> pScriptable(
6683  if (nullptr == pScriptable) {
6684  otOut << __FUNCTION__
6685  << ": Failed trying to load smart contract from string:\n\n"
6686  << strContract << "\n\n";
6687  }
6688  else {
6689  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6690  if (nullptr == pBylaw) {
6691  otOut << __FUNCTION__
6692  << ": Smart contract loaded up, but failed to retrieve the "
6693  "bylaw with name: " << BYLAW_NAME << "\n";
6694  }
6695  else // We found the bylaw...
6696  {
6697  OTVariable* pVar = pBylaw->GetVariable(VARIABLE_NAME);
6698 
6699  if (nullptr == pVar) {
6700  otOut << __FUNCTION__
6701  << ": Smart contract loaded up, and bylaw found, but "
6702  "failed to retrieve the variable with name: "
6703  << VARIABLE_NAME << "\n";
6704  }
6705  else // We found the variable...
6706  {
6707  std::string str_return;
6708 
6709  switch (pVar->GetType()) {
6711  str_return = pVar->GetValueString();
6712  break;
6714  str_return = OTAPI_Exec::LongToString(
6715  static_cast<int64_t>(pVar->GetValueInteger()));
6716  break;
6717  case OTVariable::Var_Bool:
6718  str_return = pVar->GetValueBool() ? "true" : "false";
6719  break;
6720  default:
6721  otErr << __FUNCTION__
6722  << ": Error: Unknown variable type.\n";
6723  break;
6724  }
6725  return str_return;
6726  }
6727  }
6728  }
6729  return "";
6730 }
6731 
6733  const std::string& THE_CONTRACT, const std::string& BYLAW_NAME,
6734  const int32_t& nIndex) const // returns the name of the hook.
6735 {
6736  if (THE_CONTRACT.empty()) {
6737  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6738  OT_FAIL;
6739  }
6740  if (BYLAW_NAME.empty()) {
6741  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6742  OT_FAIL;
6743  }
6744  const OTString strContract(THE_CONTRACT);
6745  std::unique_ptr<OTScriptable> pScriptable(
6747  if (nullptr == pScriptable) {
6748  otOut << __FUNCTION__
6749  << ": Failed trying to load smart contract from string:\n\n"
6750  << strContract << "\n\n";
6751  }
6752  else {
6753  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6754  if (nullptr == pBylaw) {
6755  otOut << __FUNCTION__
6756  << ": Smart contract loaded up, but failed to retrieve the "
6757  "bylaw with name: " << BYLAW_NAME << "\n";
6758  }
6759  else // We found the bylaw...
6760  {
6761  const int32_t nTempIndex = static_cast<const int32_t>(nIndex);
6762  const std::string str_name(pBylaw->GetHookNameByIndex(nTempIndex));
6763  return str_name;
6764  }
6765  }
6766  return "";
6767 }
6768 
6770 int32_t OTAPI_Exec::Hook_GetClauseCount(const std::string& THE_CONTRACT,
6771  const std::string& BYLAW_NAME,
6772  const std::string& HOOK_NAME) const
6773 {
6774  if (THE_CONTRACT.empty()) {
6775  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6776  OT_FAIL;
6777  }
6778  if (BYLAW_NAME.empty()) {
6779  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6780  OT_FAIL;
6781  }
6782  if (HOOK_NAME.empty()) {
6783  otErr << __FUNCTION__ << ": Null: HOOK_NAME passed in!\n";
6784  OT_FAIL;
6785  }
6786  const OTString strContract(THE_CONTRACT);
6787  std::unique_ptr<OTScriptable> pScriptable(
6789  if (nullptr == pScriptable) {
6790  otOut << __FUNCTION__
6791  << ": Failed trying to load smart contract from string:\n\n"
6792  << strContract << "\n\n";
6793  }
6794  else {
6795  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6796  if (nullptr == pBylaw) {
6797  otOut << __FUNCTION__
6798  << ": Smart contract loaded up, but failed to retrieve the "
6799  "bylaw with name: " << BYLAW_NAME << "\n";
6800  }
6801  else // We found the bylaw...
6802  {
6803  mapOfClauses theResults;
6804  const bool bGotHooks = pBylaw->GetHooks(
6805  HOOK_NAME,
6806  theResults); // Look up all clauses matching a specific hook.
6807  const int32_t nReturnValue =
6808  bGotHooks ? static_cast<const int32_t>(theResults.size())
6809  : (-1);
6810  return nReturnValue;
6811  }
6812  }
6813  return (-1);
6814 }
6815 
6821 std::string OTAPI_Exec::Hook_GetClauseAtIndex(const std::string& THE_CONTRACT,
6822  const std::string& BYLAW_NAME,
6823  const std::string& HOOK_NAME,
6824  const int32_t& nIndex) const
6825 {
6826  if (THE_CONTRACT.empty()) {
6827  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6828  OT_FAIL;
6829  }
6830  if (BYLAW_NAME.empty()) {
6831  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6832  OT_FAIL;
6833  }
6834  if (HOOK_NAME.empty()) {
6835  otErr << __FUNCTION__ << ": Null: HOOK_NAME passed in!\n";
6836  OT_FAIL;
6837  }
6838  const OTString strContract(THE_CONTRACT);
6839  std::unique_ptr<OTScriptable> pScriptable(
6841  if (nullptr == pScriptable) {
6842  otOut << __FUNCTION__
6843  << ": Failed trying to load smart contract from string:\n\n"
6844  << strContract << "\n\n";
6845  }
6846  else {
6847  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6848  if (nullptr == pBylaw) {
6849  otOut << __FUNCTION__
6850  << ": Smart contract loaded up, but failed to retrieve the "
6851  "bylaw with name: " << BYLAW_NAME << "\n";
6852  }
6853  else // We found the bylaw...
6854  {
6855  mapOfClauses theResults;
6856 
6857  if (pBylaw->GetHooks(HOOK_NAME, theResults)) // Look up all clauses
6858  // matching a specific
6859  // hook.
6860  {
6861  if ((nIndex >= 0) &&
6862  (nIndex < static_cast<int64_t>(theResults.size()))) {
6863  int32_t nLoopIndex = -1;
6864 
6865  for (auto& it : theResults) {
6866  OTClause* pClause = it.second;
6867  OT_ASSERT(nullptr != pClause);
6868  ++nLoopIndex; // on first iteration, this is now 0.
6869 
6870  if (nLoopIndex == nIndex) {
6871  const std::string str_return(
6872  pClause->GetName().Get());
6873  return str_return;
6874  }
6875  }
6876  }
6877  }
6878  }
6879  }
6880  return "";
6881 }
6882 
6884  const std::string& THE_CONTRACT, const std::string& BYLAW_NAME,
6885  const int32_t& nIndex) const // returns the name of the callback.
6886 {
6887  if (THE_CONTRACT.empty()) {
6888  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6889  OT_FAIL;
6890  }
6891  if (BYLAW_NAME.empty()) {
6892  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6893  OT_FAIL;
6894  }
6895  const OTString strContract(THE_CONTRACT);
6896  std::unique_ptr<OTScriptable> pScriptable(
6898  if (nullptr == pScriptable) {
6899  otOut << __FUNCTION__
6900  << ": Failed trying to load smart contract from string:\n\n"
6901  << strContract << "\n\n";
6902  }
6903  else {
6904  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6905  if (nullptr == pBylaw) {
6906  otOut << __FUNCTION__
6907  << ": Smart contract loaded up, but failed to retrieve the "
6908  "bylaw with name: " << BYLAW_NAME << "\n";
6909  }
6910  else // We found the bylaw...
6911  {
6912  const int32_t nTempIndex = static_cast<const int32_t>(nIndex);
6913  const std::string str_name(
6914  pBylaw->GetCallbackNameByIndex(nTempIndex));
6915  return str_name;
6916  }
6917  }
6918  return "";
6919 }
6920 
6921 std::string OTAPI_Exec::Callback_GetClause(const std::string& THE_CONTRACT,
6922  const std::string& BYLAW_NAME,
6923  const std::string& CALLBACK_NAME)
6924  const // returns name of clause attached to
6925  // callback.
6926 {
6927  if (THE_CONTRACT.empty()) {
6928  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6929  OT_FAIL;
6930  }
6931  if (BYLAW_NAME.empty()) {
6932  otErr << __FUNCTION__ << ": Null: BYLAW_NAME passed in!\n";
6933  OT_FAIL;
6934  }
6935  if (CALLBACK_NAME.empty()) {
6936  otErr << __FUNCTION__ << ": Null: CALLBACK_NAME passed in!\n";
6937  OT_FAIL;
6938  }
6939  const OTString strContract(THE_CONTRACT);
6940  std::unique_ptr<OTScriptable> pScriptable(
6942  if (nullptr == pScriptable) {
6943  otOut << __FUNCTION__
6944  << ": Failed trying to load smart contract from string:\n\n"
6945  << strContract << "\n\n";
6946  }
6947  else {
6948  OTBylaw* pBylaw = pScriptable->GetBylaw(BYLAW_NAME);
6949  if (nullptr == pBylaw) {
6950  otOut << __FUNCTION__
6951  << ": Smart contract loaded up, but failed to retrieve the "
6952  "bylaw with name: " << BYLAW_NAME << "\n";
6953  }
6954  else // We found the bylaw...
6955  {
6956  OTClause* pClause = pBylaw->GetCallback(CALLBACK_NAME);
6957 
6958  if (nullptr == pClause) {
6959  otOut << __FUNCTION__
6960  << ": Smart contract loaded up, and bylaw found, but "
6961  "failed to retrieve the clause for callback: "
6962  << CALLBACK_NAME << "\n";
6963  }
6964  else // We found the clause...
6965  {
6966  const std::string str_return(pClause->GetName().Get());
6967  return str_return;
6968  }
6969  }
6970  }
6971  return "";
6972 }
6973 
6974 int32_t OTAPI_Exec::Party_GetAcctCount(const std::string& THE_CONTRACT,
6975  const std::string& PARTY_NAME) const
6976 {
6977  if (THE_CONTRACT.empty()) {
6978  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
6979  OT_FAIL;
6980  }
6981  if (PARTY_NAME.empty()) {
6982  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
6983  OT_FAIL;
6984  }
6985  OTString strContract(THE_CONTRACT);
6986  std::unique_ptr<OTScriptable> pScriptable(
6988  if (nullptr == pScriptable) {
6989  otOut << __FUNCTION__
6990  << ": Failed trying to load smart contract from string:\n\n"
6991  << strContract << "\n\n";
6992  }
6993  else {
6994  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
6995  if (nullptr == pParty) {
6996  otOut << __FUNCTION__
6997  << ": Smart contract loaded up, but failed to find a party "
6998  "with the name: " << PARTY_NAME << "\n";
6999  }
7000  else // We found the party...
7001  {
7002  const int32_t nReturnValue =
7003  static_cast<int32_t>(pParty->GetAccountCount());
7004  return nReturnValue;
7005  }
7006  }
7007  return (-1);
7008 }
7009 
7010 int32_t OTAPI_Exec::Party_GetAgentCount(const std::string& THE_CONTRACT,
7011  const std::string& PARTY_NAME) const
7012 {
7013  if (THE_CONTRACT.empty()) {
7014  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
7015  OT_FAIL;
7016  }
7017  if (PARTY_NAME.empty()) {
7018  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
7019  OT_FAIL;
7020  }
7021  OTString strContract(THE_CONTRACT);
7022  std::unique_ptr<OTScriptable> pScriptable(
7024  if (nullptr == pScriptable) {
7025  otOut << __FUNCTION__
7026  << ": Failed trying to load smart contract from string:\n\n"
7027  << strContract << "\n\n";
7028  }
7029  else {
7030  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
7031  if (nullptr == pParty) {
7032  otOut << __FUNCTION__
7033  << ": Smart contract loaded up, but failed to find a party "
7034  "with the name: " << PARTY_NAME << "\n";
7035  }
7036  else // We found the party...
7037  {
7038  const int32_t nReturnValue =
7039  static_cast<int32_t>(pParty->GetAgentCount());
7040  return nReturnValue;
7041  }
7042  }
7043  return (-1);
7044 }
7045 
7047  const std::string& THE_CONTRACT,
7048  const std::string& PARTY_NAME) const // returns
7049  // either
7050  // NymID or
7051  // Entity ID.
7052  // (If
7053 // there is one... Contract might not be
7054 // signed yet.)
7055 {
7056  if (THE_CONTRACT.empty()) {
7057  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
7058  OT_FAIL;
7059  }
7060  if (PARTY_NAME.empty()) {
7061  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
7062  OT_FAIL;
7063  }
7064  OTString strContract(THE_CONTRACT);
7065  std::unique_ptr<OTScriptable> pScriptable(
7067  if (nullptr == pScriptable) {
7068  otOut << __FUNCTION__
7069  << ": Failed trying to load smart contract from string:\n\n"
7070  << strContract << "\n\n";
7071  }
7072  else {
7073  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
7074  if (nullptr == pParty) {
7075  otOut << __FUNCTION__
7076  << ": Smart contract loaded up, but failed to find a party "
7077  "with the name: " << PARTY_NAME << "\n";
7078  }
7079  else // We found the party...
7080  {
7081  return pParty->GetPartyID();
7082  }
7083  }
7084  return "";
7085 }
7086 
7088  const std::string& THE_CONTRACT, const std::string& PARTY_NAME,
7089  const int32_t& nIndex) const // returns the name of the clause.
7090 {
7091  if (THE_CONTRACT.empty()) {
7092  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
7093  OT_FAIL;
7094  }
7095  if (PARTY_NAME.empty()) {
7096  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
7097  OT_FAIL;
7098  }
7099  const OTString strContract(THE_CONTRACT);
7100  std::unique_ptr<OTScriptable> pScriptable(
7102  if (nullptr == pScriptable) {
7103  otOut << __FUNCTION__
7104  << ": Failed trying to load smart contract from string:\n\n"
7105  << strContract << "\n\n";
7106  }
7107  else {
7108  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
7109  if (nullptr == pParty) {
7110  otOut << __FUNCTION__
7111  << ": Smart contract loaded up, but failed to retrieve the "
7112  "party with name: " << PARTY_NAME << "\n";
7113  }
7114  else // We found the party...
7115  {
7116  const int32_t nTempIndex = static_cast<const int32_t>(nIndex);
7117  OTPartyAccount* pAcct = pParty->GetAccountByIndex(nTempIndex);
7118 
7119  if (nullptr == pAcct) {
7120  otOut << __FUNCTION__ << ": Smart contract loaded up, and "
7121  "party found, but failed to retrieve "
7122  "the account at index: " << nTempIndex
7123  << "\n";
7124  }
7125  else // We found the account...
7126  {
7127  const std::string str_name(pAcct->GetName().Get()); // Success.
7128  return str_name;
7129  }
7130  }
7131  }
7132  return "";
7133 }
7134 
7135 std::string OTAPI_Exec::Party_GetAcctID(const std::string& THE_CONTRACT,
7136  const std::string& PARTY_NAME,
7137  const std::string& ACCT_NAME)
7138  const // returns the account ID based on the account
7139  // name. (If there is one yet...)
7140 {
7141  if (THE_CONTRACT.empty()) {
7142  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
7143  OT_FAIL;
7144  }
7145  if (PARTY_NAME.empty()) {
7146  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
7147  OT_FAIL;
7148  }
7149  if (ACCT_NAME.empty()) {
7150  otErr << __FUNCTION__ << ": Null: ACCT_NAME passed in!\n";
7151  OT_FAIL;
7152  }
7153  const OTString strContract(THE_CONTRACT);
7154  std::unique_ptr<OTScriptable> pScriptable(
7156  if (nullptr == pScriptable) {
7157  otOut << __FUNCTION__
7158  << ": Failed trying to load smart contract from string:\n\n"
7159  << strContract << "\n\n";
7160  }
7161  else {
7162  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
7163  if (nullptr == pParty) {
7164  otOut << __FUNCTION__
7165  << ": Smart contract loaded up, but failed to retrieve the "
7166  "party with name: " << PARTY_NAME << "\n";
7167  }
7168  else // We found the party...
7169  {
7170  const OTPartyAccount* pAcct = pParty->GetAccount(ACCT_NAME);
7171 
7172  if (nullptr == pAcct) {
7173  otOut << __FUNCTION__ << ": Smart contract loaded up, and "
7174  "party found, but failed to retrieve "
7175  "party's account named: " << ACCT_NAME
7176  << "\n";
7177  }
7178  else // We found the account...
7179  {
7180  const std::string str_return(
7181  pAcct->GetAcctID().Get()); // Success.
7182  return str_return;
7183  }
7184  }
7185  }
7186  return "";
7187 }
7188 
7189 std::string OTAPI_Exec::Party_GetAcctAssetID(const std::string& THE_CONTRACT,
7190  const std::string& PARTY_NAME,
7191  const std::string& ACCT_NAME)
7192  const // returns the asset type ID based on the
7193  // account name.
7194 {
7195  if (THE_CONTRACT.empty()) {
7196  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
7197  OT_FAIL;
7198  }
7199  if (PARTY_NAME.empty()) {
7200  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
7201  OT_FAIL;
7202  }
7203  if (ACCT_NAME.empty()) {
7204  otErr << __FUNCTION__ << ": Null: ACCT_NAME passed in!\n";
7205  OT_FAIL;
7206  }
7207  const OTString strContract(THE_CONTRACT);
7208  std::unique_ptr<OTScriptable> pScriptable(
7210  if (nullptr == pScriptable) {
7211  otOut << __FUNCTION__
7212  << ": Failed trying to load smart contract from string:\n\n"
7213  << strContract << "\n\n";
7214  }
7215  else {
7216  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
7217  if (nullptr == pParty) {
7218  otOut << __FUNCTION__
7219  << ": Smart contract loaded up, but failed to retrieve the "
7220  "party with name: " << PARTY_NAME << "\n";
7221  }
7222  else // We found the party...
7223  {
7224  const OTPartyAccount* pAcct = pParty->GetAccount(ACCT_NAME);
7225 
7226  if (nullptr == pAcct) {
7227  otOut << __FUNCTION__ << ": Smart contract loaded up, and "
7228  "party found, but failed to retrieve "
7229  "party's account named: " << ACCT_NAME
7230  << "\n";
7231  }
7232  else // We found the account...
7233  {
7234  const std::string str_return(
7235  pAcct->GetAssetTypeID().Get()); // Success.
7236  return str_return;
7237  }
7238  }
7239  }
7240  return "";
7241 }
7242 
7243 std::string OTAPI_Exec::Party_GetAcctAgentName(const std::string& THE_CONTRACT,
7244  const std::string& PARTY_NAME,
7245  const std::string& ACCT_NAME)
7246  const // returns the authorized agent for the named
7247  // account.
7248 {
7249  if (THE_CONTRACT.empty()) {
7250  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
7251  OT_FAIL;
7252  }
7253  if (PARTY_NAME.empty()) {
7254  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
7255  OT_FAIL;
7256  }
7257  if (ACCT_NAME.empty()) {
7258  otErr << __FUNCTION__ << ": Null: ACCT_NAME passed in!\n";
7259  OT_FAIL;
7260  }
7261  const OTString strContract(THE_CONTRACT);
7262  std::unique_ptr<OTScriptable> pScriptable(
7264  if (nullptr == pScriptable) {
7265  otOut << __FUNCTION__
7266  << ": Failed trying to load smart contract from string:\n\n"
7267  << strContract << "\n\n";
7268  }
7269  else {
7270  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
7271  if (nullptr == pParty) {
7272  otOut << __FUNCTION__
7273  << ": Smart contract loaded up, but failed to retrieve the "
7274  "party with name: " << PARTY_NAME << "\n";
7275  }
7276  else // We found the party...
7277  {
7278  const OTPartyAccount* pAcct = pParty->GetAccount(ACCT_NAME);
7279 
7280  if (nullptr == pAcct) {
7281  otOut << __FUNCTION__ << ": Smart contract loaded up, and "
7282  "party found, but failed to retrieve "
7283  "party's account named: " << ACCT_NAME
7284  << "\n";
7285  }
7286  else // We found the account...
7287  {
7288  const std::string str_return(
7289  pAcct->GetAgentName().Get()); // Success.
7290  return str_return;
7291  }
7292  }
7293  }
7294  return "";
7295 }
7296 
7298  const std::string& THE_CONTRACT, const std::string& PARTY_NAME,
7299  const int32_t& nIndex) const // returns the name of the agent.
7300 {
7301  if (THE_CONTRACT.empty()) {
7302  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
7303  OT_FAIL;
7304  }
7305  if (PARTY_NAME.empty()) {
7306  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
7307  OT_FAIL;
7308  }
7309  const OTString strContract(THE_CONTRACT);
7310  std::unique_ptr<OTScriptable> pScriptable(
7312  if (nullptr == pScriptable) {
7313  otOut << __FUNCTION__
7314  << ": Failed trying to load smart contract from string:\n\n"
7315  << strContract << "\n\n";
7316  }
7317  else {
7318  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
7319  if (nullptr == pParty) {
7320  otOut << __FUNCTION__
7321  << ": Smart contract loaded up, but failed to retrieve the "
7322  "party with name: " << PARTY_NAME << "\n";
7323  }
7324  else // We found the party...
7325  {
7326  const int32_t nTempIndex = static_cast<const int32_t>(nIndex);
7327  OTAgent* pAgent = pParty->GetAgentByIndex(nTempIndex);
7328 
7329  if (nullptr == pAgent) {
7330  otOut << __FUNCTION__
7331  << ": Smart contract loaded up, and party found, but "
7332  "failed to retrieve the agent at index: " << nTempIndex
7333  << "\n";
7334  }
7335  else // We found the agent...
7336  {
7337  const std::string str_name(pAgent->GetName().Get()); // Success.
7338  return str_name;
7339  }
7340  }
7341  }
7342  return "";
7343 }
7344 
7345 std::string OTAPI_Exec::Party_GetAgentID(const std::string& THE_CONTRACT,
7346  const std::string& PARTY_NAME,
7347  const std::string& AGENT_NAME)
7348  const // returns ID of the agent. (If there is
7349  // one...)
7350 {
7351  if (THE_CONTRACT.empty()) {
7352  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
7353  OT_FAIL;
7354  }
7355  if (PARTY_NAME.empty()) {
7356  otErr << __FUNCTION__ << ": Null: PARTY_NAME passed in!\n";
7357  OT_FAIL;
7358  }
7359  if (AGENT_NAME.empty()) {
7360  otErr << __FUNCTION__ << ": Null: AGENT_NAME passed in!\n";
7361  OT_FAIL;
7362  }
7363  const OTString strContract(THE_CONTRACT);
7364  std::unique_ptr<OTScriptable> pScriptable(
7366  if (nullptr == pScriptable) {
7367  otOut << __FUNCTION__
7368  << ": Failed trying to load smart contract from string:\n\n"
7369  << strContract << "\n\n";
7370  }
7371  else {
7372  OTParty* pParty = pScriptable->GetParty(PARTY_NAME);
7373  if (nullptr == pParty) {
7374  otOut << __FUNCTION__
7375  << ": Smart contract loaded up, but failed to retrieve the "
7376  "party with name: " << PARTY_NAME << "\n";
7377  }
7378  else // We found the party...
7379  {
7380  OTAgent* pAgent = pParty->GetAgent(AGENT_NAME);
7381 
7382  if (nullptr == pAgent) {
7383  otOut << __FUNCTION__ << ": Smart contract loaded up, and "
7384  "party found, but failed to retrieve "
7385  "party's agent named: " << AGENT_NAME
7386  << "\n";
7387  }
7388  else // We found the agent...
7389  {
7390  std::string str_return;
7391  OTIdentifier theAgentID;
7392  if (pAgent->IsAnIndividual() && pAgent->GetNymID(theAgentID)) {
7393  const OTString strTemp(theAgentID);
7394  str_return = strTemp.Get();
7395  return str_return;
7396  }
7397  }
7398  }
7399  }
7400  return "";
7401 }
7402 
7403 // ACTIVATE SMART CONTRACT (This is a transaction, and messages the server.)
7404 // Take an existing smart contract, which has already been set up, confirmed,
7405 // etc,
7406 // and then activate it on the server so it can start processing.
7407 //
7408 // See OTAPI_Exec::Create_SmartContract (etc.)
7409 //
7410 // Returns int32_t:
7411 // -1 means error; no message was sent.
7412 // -2 means the message was sent, but the request number must be passed as a
7413 // string, so call OTAPI_Exec::GetLargeRequestNum.
7414 // 0 means NO error, but also: no message was sent.
7415 // >0 means NO error, and the message was sent, and the request number fits into
7416 // an integer...
7417 // ...and in fact the requestNum IS the return value!
7418 // ===> In 99% of cases, this LAST option is what actually happens!!
7419 //
7421  const std::string& SERVER_ID, const std::string& USER_ID,
7422  const std::string& THE_SMART_CONTRACT) const
7423 {
7424  if (SERVER_ID.empty()) {
7425  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
7426  OT_FAIL;
7427  }
7428  if (USER_ID.empty()) {
7429  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
7430  OT_FAIL;
7431  }
7432  if (THE_SMART_CONTRACT.empty()) {
7433  otErr << __FUNCTION__ << ": Null: THE_SMART_CONTRACT passed in!\n";
7434  OT_FAIL;
7435  }
7436 
7437  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
7438  const OTString strContract(THE_SMART_CONTRACT);
7439 
7440  return OTAPI()->activateSmartContract(theServerID, theUserID, strContract);
7441 }
7442 
7443 // If a smart contract is already running on the server, this allows a party
7444 // to trigger clauses on that smart contract, by name. This is NOT a
7445 // transaction,
7446 // but it DOES message the server.
7447 //
7448 // Returns int32_t:
7449 // -1 means error; no message was sent.
7450 // -2 means the message was sent, but the request number must be passed as a
7451 // string, so call OTAPI_Exec::GetLargeRequestNum.
7452 // 0 means NO error, but also: no message was sent.
7453 // >0 means NO error, and the message was sent, and the request number fits into
7454 // an integer...
7455 // ...and in fact the requestNum IS the return value!
7456 // ===> In 99% of cases, this LAST option is what actually happens!!
7457 //
7459  const std::string& SERVER_ID, const std::string& USER_ID,
7460  const int64_t& TRANSACTION_NUMBER, const std::string& CLAUSE_NAME,
7461  const std::string& STR_PARAM) const // optional param
7462 {
7463  if (SERVER_ID.empty()) {
7464  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
7465  OT_FAIL;
7466  }
7467  if (USER_ID.empty()) {
7468  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
7469  OT_FAIL;
7470  }
7471  if (0 > TRANSACTION_NUMBER) {
7472  otErr << __FUNCTION__ << ": Null: TRANSACTION_NUMBER passed in!\n";
7473  OT_FAIL;
7474  }
7475  if (CLAUSE_NAME.empty()) {
7476  otErr << __FUNCTION__ << ": Null: CLAUSE_NAME passed in!\n";
7477  OT_FAIL;
7478  }
7479  // if (STR_PARAM.empty()) { otErr << __FUNCTION__ << ": Null:
7480  // STR_PARAM passed
7481  // in!\n"; OT_FAIL; } // optional
7482  // param
7483  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
7484  const OTString strClauseName(CLAUSE_NAME);
7485  const int64_t lTransactionNum = TRANSACTION_NUMBER;
7486  const OTString strParam((STR_PARAM.empty()) ? "" : STR_PARAM);
7487  return OTAPI()->triggerClause(
7488  theServerID, theUserID, static_cast<int64_t>(lTransactionNum),
7489  strClauseName, STR_PARAM.empty() ? nullptr : &strParam);
7490 }
7491 
7492 /*
7493 OTAPI_Exec::Msg_HarvestTransactionNumbers
7494 
7495 This function will load up the cron item (which is either a market offer, a
7496 payment plan,
7497 or a SMART CONTRACT.) UPDATE: this function operates on messages, not cron
7498 items.
7499 
7500 Then it will try to harvest all of the closing transaction numbers for NYM_ID
7501 that are
7502 available to be harvested from THE_CRON_ITEM. (There might be zero #s available
7503 for that
7504 Nym, which is still a success and will return true. False means error.)
7505 
7506 YOU MIGHT ASK:
7507 
7508 WHY WOULD I WANT to harvest ONLY the closing numbers for the Nym, and not the
7509 OPENING
7510 numbers as well? The answer is because for this Nym, the opening number might
7511 already
7512 be burned. For example, if Nym just tried to activate a smart contract, and the
7513 activation
7514 FAILED, then maybe the opening number is already gone, even though his closing
7515 numbers, on the
7516 other hand, are still valid for retrieval. (I have to double check this.)
7517 
7518 HOWEVER, what if the MESSAGE failed, before it even TRIED the transaction? In
7519 which case,
7520 the opening number is still good also, and should be retrieved.
7521 
7522 Remember, I have to keep signing for my transaction numbers until they are
7523 finally closed out.
7524 They will appear on EVERY balance agreement and transaction statement from here
7525 until the end
7526 of time, whenever I finally close out those numbers. If some of them are still
7527 good on a failed
7528 transaction, then I want to retrieve them so I can use them, and eventually
7529 close them out.
7530 
7531 ==> Whereas, what if I am the PARTY to a smart contract, but I am not the actual
7532 ACTIVATOR / ORIGINATOR
7533 (who activated the smart contract on the server). Therefore I never sent any
7534 transaction to the
7535 server, and I never burned my opening number. It's probably still a good #. If
7536 my wallet is not a piece
7537 of shit, then I should have a stored copy of any contract that I signed. If it
7538 turns out in the future
7539 that that contract wasn't activated, then I can retrieve not only my closing
7540 numbers, but my OPENING
7541 number as well! IN THAT CASE, I would call OTAPI_Exec::HarvestAllNumbers()
7542 instead of OTAPI_Exec::HarvestClosingNumbers().
7543 
7544 
7545 UPDATE: The above logic is now handled automatically in
7546 OTAPI_Exec::HarvestTransactionNumbers.
7547 Therefore OTAPI_Exec::HarvestClosingNumbers and OTAPI_Exec::HarvestAllNumbers
7548 have been removed.
7549 
7550 */
7551 
7553  const std::string& THE_MESSAGE, const std::string& USER_ID,
7554  const bool& bHarvestingForRetry, const bool& bReplyWasSuccess,
7555  const bool& bReplyWasFailure, const bool& bTransactionWasSuccess,
7556  const bool& bTransactionWasFailure) const
7557 {
7558  bool bIsInitialized = OTAPI()->IsInitialized();
7559  if (!bIsInitialized) {
7560  otErr << __FUNCTION__
7561  << ": Not initialized; call OT_API::Init first.\n";
7562  OT_FAIL;
7563  }
7564  if (THE_MESSAGE.empty()) {
7565  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
7566  OT_FAIL;
7567  }
7568  if (USER_ID.empty()) {
7569  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
7570  OT_FAIL;
7571  }
7572  const OTIdentifier theUserID(USER_ID);
7573  OTMessage theMessage;
7574  const OTString strMsg(THE_MESSAGE);
7575  if (!strMsg.Exists()) {
7576  otErr << __FUNCTION__
7577  << ": Failed trying to load message from empty string.\n";
7578  return false;
7579  }
7580  // Maybe it's not a message at all. Maybe it's a cron item
7581  // (smart contract... payment plan...)
7582  //
7583  if (strMsg.Contains("PAYMENT PLAN") || strMsg.Contains("SMARTCONTRACT")) {
7584  const OTString& strCronItem = strMsg;
7585 
7586  otOut << __FUNCTION__ << ": Attempting to harvest transaction numbers "
7587  "from cron item...\n";
7588  // Unfortunately the ONLY reason we are loading up this cron item here,
7589  // is so we can get the server ID off of it.
7590  //
7591  std::unique_ptr<OTCronItem> pCronItem(
7592  OTCronItem::NewCronItem(strCronItem));
7593  if (nullptr == pCronItem) {
7594  otErr << __FUNCTION__
7595  << ": Failed trying to load message from string.";
7596 
7597  otOut << __FUNCTION__
7598  << ": Error trying to load the cron item from string (a cron "
7599  "item is a smart contract, or some other recurring "
7600  "transaction such as a market offer, or a payment plan.) "
7601  "Contents:\n\n" << strCronItem << "\n\n";
7602  return false;
7603  }
7604 
7605  // NOTE:
7606  // If a CronItem is passed in here instead of a Message, that means the
7607  // client
7608  // didn't even TRY to send the message. He failed before reaching that
7609  // point.
7610  // Therefore in this one, strange case, we don't really care about all
7611  // the bools
7612  // that were passed in here. We're just going to harvest ALL the
7613  // numbers, and
7614  // ASSUME all the bools were false.
7615  // Here goes...
7616  //
7617  return OTAPI()->HarvestAllNumbers(pCronItem->GetServerID(), theUserID,
7618  strCronItem);
7619  }
7620  // Maybe it's not a message at all. Maybe it's a basket exchange request
7621  // that never
7622  // even got sent as a message...
7623  //
7624  if (strMsg.Contains("currencyBasket")) {
7625  const OTString& strBasket = strMsg;
7626 
7627  otOut << __FUNCTION__ << ": Attempting to harvest transaction numbers "
7628  "from a basket currency exchange request...\n";
7629  OTPseudonym* pNym =
7630  OTAPI()->GetOrLoadPrivateNym(theUserID, false, __FUNCTION__);
7631  if (nullptr == pNym) return false;
7632  Basket theRequestBasket;
7633 
7634  if (theRequestBasket.LoadContractFromString(strBasket)) {
7635  if (!theRequestBasket.IsExchanging()) {
7636  otErr << __FUNCTION__ << ": Error: This is apparently NOT a "
7637  "basket exchange request!\nContents:\n"
7638  << strBasket << "\n";
7639  return false;
7640  }
7641  // Now we need to find the account ID (so we can find the server
7642  // ID...)
7643  //
7644  OTAccount* pAccount = OTAPI()->GetAccount(
7645  theRequestBasket.GetRequestAccountID(), __FUNCTION__);
7646  if (nullptr == pAccount) {
7647  const OTString strAcctID(
7648  theRequestBasket.GetRequestAccountID());
7649  otErr << __FUNCTION__
7650  << ": Error: Unable to find the main account based on "
7651  "the ID from the exchange request: " << strAcctID
7652  << "\n";
7653  return false;
7654  }
7655  // Now let's get the server ID...
7656  //
7657  OTServerContract* pServer = OTAPI()->GetServer(
7658  pAccount->GetPurportedServerID(), __FUNCTION__);
7659 
7660  if (nullptr == pServer) {
7661  const OTString strServerID(pAccount->GetPurportedServerID());
7662  otErr << __FUNCTION__
7663  << ": Error: Unable to find the server based on the "
7664  "exchange request: " << strServerID << "\n";
7665  return false;
7666  }
7667  theRequestBasket.HarvestClosingNumbers(
7668  *pNym, pAccount->GetPurportedServerID(), true); // bSave=true
7669  return true;
7670  }
7671  else
7672  otErr << __FUNCTION__
7673  << ": Error loading original basket request.\n";
7674 
7675  return false;
7676  }
7677  else if (!theMessage.LoadContractFromString(strMsg)) {
7678  otErr << __FUNCTION__
7679  << ": Failed trying to load message from string.\n";
7680  return false;
7681  }
7682  // By this point, we have the actual message loaded up.
7683  //
7684  const bool& bSuccess = OTAPI()->Msg_HarvestTransactionNumbers(
7685  theMessage, theUserID, bHarvestingForRetry, bReplyWasSuccess,
7686  bReplyWasFailure, bTransactionWasSuccess, bTransactionWasFailure);
7687  return bSuccess ? true : false;
7688 }
7689 
7690 // bool OTAPI_Exec::HarvestClosingNumbers(const std::string& SERVER_ID,
7691 // const std::string& NYM_ID,
7692 // const std::string& THE_CRON_ITEM)
7693 //{
7694 // OT_ASSERT_MSG("" != SERVER_ID, "OTAPI_Exec::HarvestClosingNumbers: Null
7695 // SERVER_ID passed in.");
7696 // OT_ASSERT_MSG("" != NYM_ID, "OTAPI_Exec::HarvestClosingNumbers: Null
7697 // NYM_ID passed in.");
7698 // OT_ASSERT_MSG("" != THE_CRON_ITEM, "OTAPI_Exec::HarvestClosingNumbers:
7699 // Null THE_CRON_ITEM passed in.");
7700 //
7701 // const OTIdentifier theNymID(NYM_ID), theServerID(SERVER_ID);
7702 // const OTString strContract(THE_CRON_ITEM);
7703 //
7704 // const bool& bHarvested = OTAPI()->HarvestClosingNumbers(theServerID,
7705 // theNymID, strContract);
7706 //
7707 // return bHarvested ? true : false;
7708 //}
7709 //
7710 //
7711 // NOTE: usually you will want to call OTAPI_Exec::HarvestClosingNumbers, since
7712 // the Opening number is usually
7713 // burned up from some failed transaction or whatever. You don't want to harvest
7714 // the opening number usually,
7715 // just the closing numbers. (If the opening number is burned up, yet you still
7716 // harvest it, then your OT wallet
7717 // will end up using that number again on some other transaction, which will
7718 // obviously then fail since the number
7719 // isn't good anymore.)
7720 // This function is only for those cases where you are sure that the opening
7721 // transaction # hasn't been burned yet,
7722 // such as when the message failed and the transaction wasn't attempted (because
7723 // it never got that far) or such as
7724 // when the contract simply never got signed or activated by one of the other
7725 // parties, and so you want to claw your
7726 // #'s back, and since in that case your opening number is still good, you would
7727 // use the below function to get it back.
7728 //
7729 // bool OTAPI_Exec::HarvestAllNumbers(const std::string& SERVER_ID,
7730 // const std::string& NYM_ID,
7731 // const std::string& THE_CRON_ITEM)
7732 //{
7733 // OT_ASSERT_MSG("" != SERVER_ID, "OTAPI_Exec::HarvestAllNumbers: Null
7734 // SERVER_ID passed in.");
7735 // OT_ASSERT_MSG("" != NYM_ID, "OTAPI_Exec::HarvestAllNumbers: Null NYM_ID
7736 // passed in.");
7737 // OT_ASSERT_MSG("" != THE_CRON_ITEM, "OTAPI_Exec::HarvestAllNumbers: Null
7738 // THE_CRON_ITEM passed in.");
7739 //
7740 // const OTIdentifier theNymID(NYM_ID), theServerID(SERVER_ID);
7741 // const OTString strContract(THE_CRON_ITEM);
7742 //
7743 // const bool& bHarvested = OTAPI()->HarvestAllNumbers(theServerID,
7744 // theNymID, strContract);
7745 //
7746 // return bHarvested ? true : false;
7747 //}
7748 
7749 // LOAD PUBLIC KEY (of other users, where no private key is available)
7750 // This is the "address book" versus the private Nym.
7751 // If nothing found in the address book, it still tries to load
7752 // a Private Nym (just to get the pubkey from it.)
7753 // -- from local storage
7754 //
7755 // Return as STRING (NOT escaped.)
7756 //
7757 // Users will most likely store public keys of OTHER users, and they will need
7758 // to load those from time to time, especially to verify signatures, etc.
7759 //
7761  const std::string& USER_ID) const // returns "", or a public key.
7762 {
7763  if (USER_ID.empty()) {
7764  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
7765  OT_FAIL;
7766  }
7767  OTString strPubkey; // For the output
7768  OTPasswordData thePWData(OT_PW_DISPLAY);
7769  OTIdentifier NYM_ID(USER_ID);
7770  OTPseudonym* pNym =
7771  OTAPI()->GetOrLoadNym(NYM_ID, false, __FUNCTION__,
7772  &thePWData); // This tries to get, then tries to
7773  // load as public, then tries to load
7774  // as private.
7775  if (nullptr == pNym) return "";
7776  if (false ==
7778  strPubkey, false)) // bEscaped defaults to true. 6/13/12
7779  {
7780  OTString strNymID(NYM_ID);
7781  otOut << __FUNCTION__
7782  << ": Failure retrieving encryption pubkey from Nym: " << strNymID
7783  << "\n";
7784  }
7785  else // success
7786  {
7787  std::string pBuf = strPubkey.Get();
7788  return pBuf;
7789  }
7790  return "";
7791 }
7792 
7794  const std::string& USER_ID) const // returns "", or a public key.
7795 {
7796  if (USER_ID.empty()) {
7797  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
7798  OT_FAIL;
7799  }
7800  OTString strPubkey; // For the output
7801  OTPasswordData thePWData(OT_PW_DISPLAY);
7802  OTIdentifier NYM_ID(USER_ID);
7803  OTPseudonym* pNym =
7804  OTAPI()->GetOrLoadNym(NYM_ID, false, __FUNCTION__,
7805  &thePWData); // This tries to get, then tries to
7806  // load as public, then tries to load
7807  // as private.
7808  if (nullptr == pNym) return "";
7809  if (false ==
7811  strPubkey, false)) // bEscaped defaults to true. 6/13/12
7812  {
7813  OTString strNymID(NYM_ID);
7814  otOut << __FUNCTION__
7815  << ": Failure retrieving signing pubkey from Nym: " << strNymID
7816  << "\n";
7817  }
7818  else // success
7819  {
7820  std::string pBuf = strPubkey.Get();
7821  return pBuf;
7822  }
7823  return "";
7824 }
7825 
7826 // LOAD USER PUBLIC KEY -- from local storage
7827 //
7828 // (return as STRING)
7829 //
7831  const std::string& USER_ID) const // returns "", or a public key.
7832 {
7833  if (USER_ID.empty()) {
7834  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
7835  OT_FAIL;
7836  }
7837  OTString strPubkey; // For the output
7838  OTIdentifier NYM_ID(USER_ID);
7839  OTPseudonym* pNym =
7840  OTAPI()->GetOrLoadPrivateNym(NYM_ID); // No need to cleanup.
7841  if (nullptr == pNym) return "";
7842  if (!pNym->GetPublicEncrKey().GetPublicKey(strPubkey)) {
7843  OTString strNymID(NYM_ID);
7844  otOut << __FUNCTION__
7845  << ": Failure retrieving encryption pubkey from Nym: " << strNymID
7846  << "\n";
7847  }
7848  else // success
7849  {
7850  std::string pBuf = strPubkey.Get();
7851  return pBuf;
7852  }
7853  return "";
7854 }
7855 
7857  const std::string& USER_ID) const // returns "", or a public key.
7858 {
7859  if (USER_ID.empty()) {
7860  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
7861  OT_FAIL;
7862  }
7863  OTString strPubkey; // For the output
7864  OTIdentifier NYM_ID(USER_ID);
7865  OTPseudonym* pNym =
7866  OTAPI()->GetOrLoadPrivateNym(NYM_ID); // No need to cleanup.
7867  if (nullptr == pNym) return "";
7868  if (!pNym->GetPublicSignKey().GetPublicKey(strPubkey)) {
7869  OTString strNymID(NYM_ID);
7870  otOut << __FUNCTION__
7871  << ": Failure retrieving signing pubkey from Nym: " << strNymID
7872  << "\n";
7873  }
7874  else // success
7875  {
7876  std::string pBuf = strPubkey.Get();
7877  return pBuf;
7878  }
7879  return "";
7880 }
7881 
7882 //
7883 // Verify that USER_ID (including its Private Key) is an
7884 // available and verified user in local storage.
7885 //
7886 // Loads the user's private key, verifies, then returns true or false.
7887 //
7889  const std::string& USER_ID) const // returns
7890  // bool
7891 {
7892  if (USER_ID.empty()) {
7893  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
7894  OT_FAIL;
7895  }
7896  OTIdentifier NYM_ID(USER_ID);
7897  OTPseudonym* pNym =
7898  OTAPI()->GetOrLoadPrivateNym(NYM_ID); // No need to cleanup.
7899  if (nullptr == pNym) return false;
7900  return true;
7901 }
7902 
7903 //
7904 // Is Mint32_t Still Good ? true (1) == Yes, this mint32_t is still good.
7905 // false (0) == No: expired or other error.
7906 //
7907 bool OTAPI_Exec::Mint_IsStillGood(const std::string& SERVER_ID,
7908  const std::string& ASSET_TYPE_ID) const
7909 {
7910  if (SERVER_ID.empty()) {
7911  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
7912  OT_FAIL;
7913  }
7914  if (ASSET_TYPE_ID.empty()) {
7915  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
7916  OT_FAIL;
7917  }
7918 
7919  const OTIdentifier theServerID(SERVER_ID), theAssetID(ASSET_TYPE_ID);
7920  // There is an OT_ASSERT in here for memory failure,
7921  // but it still might return "" if various verification fails.
7922  std::unique_ptr<Mint> pMint(OTAPI()->LoadMint(theServerID, theAssetID));
7923 
7924  if (nullptr == pMint)
7925  otOut << __FUNCTION__
7926  << ": Failure calling OT_API::LoadMint.\nServer: " << SERVER_ID
7927  << "\n Asset Type: " << ASSET_TYPE_ID << "\n";
7928  else // success
7929  {
7930  bool bExpired = pMint->Expired();
7931 
7932  if (!bExpired) return true;
7933  }
7934  return false;
7935 }
7936 
7938  const std::string& SERVER_ID,
7939  const std::string& ASSET_TYPE_ID) const // returns
7940  // "", or a
7941  // mint
7942 {
7943  if (SERVER_ID.empty()) {
7944  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
7945  OT_FAIL;
7946  }
7947  if (ASSET_TYPE_ID.empty()) {
7948  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
7949  OT_FAIL;
7950  }
7951 
7952  const OTIdentifier theServerID(SERVER_ID);
7953  const OTIdentifier theAssetID(ASSET_TYPE_ID);
7954 
7955  // There is an OT_ASSERT in here for memory failure,
7956  // but it still might return "" if various verification fails.
7957  std::unique_ptr<Mint> pMint(OTAPI()->LoadMint(theServerID, theAssetID));
7958 
7959  if (nullptr == pMint)
7960  otOut << __FUNCTION__ << "OTAPI_Exec::LoadMint: Failure calling "
7961  "OT_API::LoadMint.\nServer: " << SERVER_ID
7962  << "\n Asset Type: " << ASSET_TYPE_ID << "\n";
7963  else // success
7964  {
7965  OTString strOutput(*pMint); // For the output
7966  std::string pBuf = strOutput.Get();
7967  return pBuf;
7968  }
7969  return "";
7970 }
7971 
7973  const std::string& ASSET_TYPE_ID) const // returns "", or an asset contract
7974 {
7975  if (ASSET_TYPE_ID.empty()) {
7976  otErr << __FUNCTION__ << ": Null ASSET_TYPE_ID passed in!\n";
7977  OT_FAIL;
7978  }
7979 
7980  const OTIdentifier theAssetID(ASSET_TYPE_ID);
7981 
7982  // There is an OT_ASSERT in here for memory failure,
7983  // but it still might return "" if various verification fails.
7984  std::unique_ptr<OTAssetContract> pContract(
7985  OTAPI()->LoadAssetContract(theAssetID));
7986 
7987  if (nullptr == pContract) {
7988  otOut << __FUNCTION__
7989  << ": Failure calling OT_API::LoadAssetContract.\n Asset Type: "
7990  << ASSET_TYPE_ID << "\n";
7991  }
7992  else // success
7993  {
7994  OTString strOutput(*pContract); // For the output
7995  std::string pBuf = strOutput.Get();
7996  return pBuf;
7997  }
7998  return "";
7999 }
8000 
8002  const std::string& SERVER_ID) const // returns "", or an asset contract
8003 {
8004  if (SERVER_ID.empty()) {
8005  otErr << __FUNCTION__ << ": Null SERVER_ID passed in!\n";
8006  OT_FAIL;
8007  }
8008 
8009  const OTIdentifier theServerID(SERVER_ID);
8010 
8011  // There is an OT_ASSERT in here for memory failure,
8012  // but it still might return "" if various verification fails.
8013  std::unique_ptr<OTServerContract> pContract(
8014  OTAPI()->LoadServerContract(theServerID));
8015 
8016  if (nullptr == pContract) {
8017  otOut << __FUNCTION__
8018  << ": Failure calling OT_API::LoadServerContract.\nServer ID: "
8019  << SERVER_ID << "\n";
8020  }
8021  else // success
8022  {
8023  OTString strOutput(*pContract); // For the output
8024  std::string pBuf = strOutput.Get();
8025  return pBuf;
8026  }
8027  return "";
8028 }
8029 
8030 // LOAD ACCOUNT / INBOX / OUTBOX -- (from local storage)
8031 //
8032 // Loads an acct, or inbox or outbox, based on account ID, (from local storage)
8033 // and returns it as string (or returns "" if it couldn't load it.)
8034 //
8036  const std::string& SERVER_ID, const std::string& USER_ID,
8037  const std::string& ACCOUNT_ID) const // Returns "", or an account.
8038 {
8039  if (SERVER_ID.empty()) {
8040  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8041  OT_FAIL;
8042  }
8043  if (USER_ID.empty()) {
8044  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8045  OT_FAIL;
8046  }
8047  if (ACCOUNT_ID.empty()) {
8048  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8049  OT_FAIL;
8050  }
8051 
8052  const OTIdentifier theServerID(SERVER_ID);
8053  const OTIdentifier theUserID(USER_ID);
8054  const OTIdentifier theAccountID(ACCOUNT_ID);
8055 
8056  // There is an OT_ASSERT in here for memory failure,
8057  // but it still might return "" if various verification fails.
8058  std::unique_ptr<OTAccount> pAccount(
8059  OTAPI()->LoadAssetAccount(theServerID, theUserID, theAccountID));
8060 
8061  if (nullptr == pAccount) {
8062  otOut << __FUNCTION__
8063  << ": Failure calling OT_API::LoadAssetAccount.\nAccount ID: "
8064  << ACCOUNT_ID << "\n";
8065  }
8066  else // success
8067  {
8068  OTString strOutput(*pAccount); // For the output
8069  std::string pBuf = strOutput.Get();
8070  return pBuf;
8071  }
8072  return "";
8073 }
8074 
8075 // Some server replies (to your messages) are so important that a notice is
8076 // dropped
8077 // into your Nymbox with a copy of the server's reply. It's called a
8078 // replyNotice.
8079 // Since the server is usually replying to a message, I've added this function
8080 // for
8081 // quickly looking up the message reply, if it's there, based on the
8082 // requestNumber.
8083 // This is the only example in the entire OT API where a Transaction is
8084 // looked-up from
8085 // a ledger, based on a REQUEST NUMBER. (Normally transactions use transaction
8086 // numbers,
8087 // and messages use request numbers. But in this case, it's a transaction that
8088 // carries
8089 // a copy of a message.)
8090 // Note: Make sure you call this AFTER you download the box receipts, but BEFORE
8091 // you process the Nymbox (because the reply notice will have disappeared.)
8092 // Basically this
8093 // function will be used for cases where you missed a server reply, and you need
8094 // to
8095 // search your Nymbox and see if a copy of the missed reply is still there.
8096 // (Which it
8097 // won't be, once you process the box.)
8098 //
8100  const std::string& SERVER_ID, const std::string& USER_ID,
8101  const int64_t& REQUEST_NUMBER) const // returns replyNotice transaction by
8102  // requestNumber.
8103 {
8104  if (SERVER_ID.empty()) {
8105  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8106  OT_FAIL;
8107  }
8108  if (USER_ID.empty()) {
8109  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8110  OT_FAIL;
8111  }
8112  if (0 > REQUEST_NUMBER) {
8113  otErr << __FUNCTION__ << ": Negative: REQUEST_NUMBER passed in!\n";
8114  OT_FAIL;
8115  }
8116 
8117  const OTIdentifier theServerID(SERVER_ID);
8118  const OTIdentifier theUserID(USER_ID);
8119 
8120  const int64_t lRequestNumber = REQUEST_NUMBER;
8121  // There is an OT_ASSERT in here for memory failure,
8122  // but it still might return "" if various verification fails.
8123 
8124  std::unique_ptr<OTLedger> pLedger(
8125  OTAPI()->LoadNymboxNoVerify(theServerID, theUserID));
8126 
8127  if (nullptr == pLedger) {
8128  otOut << __FUNCTION__
8129  << ": Failure calling OT_API::LoadNymboxNoVerify.\n";
8130  return "";
8131  }
8132  OTTransaction* pTransaction =
8133  pLedger->GetReplyNotice(static_cast<int64_t>(lRequestNumber));
8134  // No need to cleanup this transaction, the ledger owns it already.
8135 
8136  if (nullptr == pTransaction) {
8137  otLog4 << __FUNCTION__
8138  << ": No replyNotice transactions found in ledger with request "
8139  "number: " << lRequestNumber << "\n";
8140  return ""; // Maybe he was just looking; this isn't necessarily an
8141  // error.
8142  }
8143  // At this point, I actually have the transaction pointer to the
8144  // replyNotice,
8145  // so let's return it in string form...
8146  //
8147  const int64_t lTransactionNum = pTransaction->GetTransactionNum();
8148 
8149  // Update: for transactions in ABBREVIATED form, the string is empty, since
8150  // it has never actually
8151  // been signed (in fact the whole point32_t with abbreviated transactions in
8152  // a ledger is that they
8153  // take up very little room, and have no signature of their own, but exist
8154  // merely as XML tags on
8155  // their parent ledger.)
8156  //
8157  // THEREFORE I must check to see if this transaction is abbreviated and if
8158  // so, sign it in order to
8159  // force the UpdateContents() call, so the programmatic user of this API
8160  // will be able to load it up.
8161  //
8162 
8163  OTString strOutput(*pTransaction); // we only have the Abbreviated, so we
8164  // have to use this one.
8165 
8166  if (pTransaction->IsAbbreviated()) {
8167  pLedger->LoadBoxReceipt(static_cast<int64_t>(lTransactionNum));
8168  OTTransaction* pFullTransaction =
8169  pLedger->GetTransaction(static_cast<int64_t>(lTransactionNum));
8170 
8171  if (nullptr != pFullTransaction) {
8172  strOutput.Release();
8173  strOutput.zeroMemory();
8174  strOutput.Set(*pFullTransaction); // we have the FullTransaction,
8175  // lets use that one.
8176  }
8177  else // nullptr == pFullTransaction
8178  {
8179  otErr << __FUNCTION__ << ": good index but uncovered \"\" pointer "
8180  "after trying to load full version of "
8181  "receipt (from abbreviated.) Thus, saving "
8182  "abbreviated version instead, so I can "
8183  "still return SOMETHING.\n";
8184  OTPseudonym* pNym = OTAPI()->GetNym(theUserID, __FUNCTION__);
8185  if (nullptr == pNym) return "";
8186  pTransaction->ReleaseSignatures();
8187  pTransaction->SignContract(*pNym);
8188  pTransaction->SaveContract();
8189  }
8190  strOutput.Release();
8191  pTransaction->SaveContractRaw(strOutput); // if it was abbreviated
8192  // before, now it either IS
8193  // the box receipt, or it's
8194  // the abbreviated version.
8195  }
8196  // We return the abbreviated version because the developer using the OT API
8197  // needs to know if that receipt is there, whether it's abbreviated or not.
8198  // So rather than passing "" when it's abbreviated, and thus leading him
8199  // astray, we give him the next-best thing: the abbreviated version. That
8200  // way at least he knows for sure that the receipt is there, the one he is
8201  // asking about.
8202 
8203  std::string pBuf = strOutput.Get();
8204 
8205  return pBuf;
8206 }
8207 
8208 // If the client-side has ALREADY seen the server's reply to a specific
8209 // request number, he stores that number in a list which can be queried
8210 // using this function. A copy of that list is sent with nearly every request
8211 // message sent to the server. This way the server can see which replies you
8212 // have already received. The server will mirror every number it sees (it sends
8213 // its own list in all its replies.) Whenever you see a number mirrored in the
8214 // server's reply, that means the server now knows you got its original reply
8215 // (the one referenced by the number) and the server removed any replyNotice
8216 // of that from your Nymbox (so you don't have to download it.) Basically that
8217 // means you can go ahead and remove it from your list, and once you do, the
8218 // server
8219 // will remove its matching copy as well.
8220 //
8221 // *** When you are downloading your box receipts, you can skip any receipts
8222 // where
8223 // you have ALREADY seen the reply. So you can use this function to see if you
8224 // already
8225 // saw it, and if you did, then you can skip downloading that box receipt.
8226 // Warning: this function isn't "perfect", in the sense that it cannot tell you
8227 // definitively
8228 // whether you have actually seen a server reply, but it CAN tell you if you
8229 // have seen
8230 // one until it finishes the above-described protocol (it will work in that way,
8231 // which is
8232 // how it was intended.) But after that, it will no int64_ter know if you got
8233 // the reply since
8234 // it has removed it from its list.
8235 //
8237  const std::string& SERVER_ID, const std::string& USER_ID,
8238  const int64_t& REQUEST_NUMBER) const // returns
8239  // bool
8240 {
8241  if (SERVER_ID.empty()) {
8242  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8243  OT_FAIL;
8244  }
8245  if (USER_ID.empty()) {
8246  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8247  OT_FAIL;
8248  }
8249  if (0 > REQUEST_NUMBER) {
8250  otErr << __FUNCTION__ << ": Negative: REQUEST_NUMBER passed in!\n";
8251  OT_FAIL;
8252  }
8253 
8254  OTIdentifier theServerID(SERVER_ID);
8255  OTIdentifier theUserID(USER_ID);
8256 
8257  const int64_t lRequestNumber = REQUEST_NUMBER;
8258 
8259  // const std::string& strFunc = "OTAPI_Exec::HaveAlreadySeenReply";
8260  // There is an OT_ASSERT in here for memory failure,
8261  // but it still might return "" if various verification fails.
8262 
8263  const bool& bTemp = OTAPI()->HaveAlreadySeenReply(
8264  theServerID, theUserID, static_cast<int64_t>(lRequestNumber));
8265  return bTemp;
8266 }
8267 
8268 std::string OTAPI_Exec::LoadNymbox(const std::string& SERVER_ID,
8269  const std::string& USER_ID) const // Returns
8270  // "", or
8271 // an inbox.
8272 {
8273  if (SERVER_ID.empty()) {
8274  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8275  OT_FAIL;
8276  }
8277  if (USER_ID.empty()) {
8278  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8279  OT_FAIL;
8280  }
8281 
8282  const OTIdentifier theServerID(SERVER_ID);
8283  const OTIdentifier theUserID(USER_ID);
8284 
8285  // There is an OT_ASSERT in here for memory failure,
8286  // but it still might return "" if various verification fails.
8287  std::unique_ptr<OTLedger> pLedger(
8288  OTAPI()->LoadNymbox(theServerID, theUserID));
8289 
8290  if (nullptr == pLedger) {
8291  otOut << __FUNCTION__ << ": Failure calling OT_API::LoadNymbox.\n";
8292  }
8293  else // success
8294  {
8295  OTString strOutput(*pLedger); // For the output
8296  std::string pBuf = strOutput.Get();
8297  return pBuf;
8298  }
8299 
8300  return "";
8301 }
8302 
8304  const std::string& SERVER_ID,
8305  const std::string& USER_ID) const // Returns "", or an inbox.
8306 {
8307  if (SERVER_ID.empty()) {
8308  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8309  OT_FAIL;
8310  }
8311  if (USER_ID.empty()) {
8312  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8313  OT_FAIL;
8314  }
8315 
8316  const OTIdentifier theServerID(SERVER_ID);
8317  const OTIdentifier theUserID(USER_ID);
8318 
8319  // There is an OT_ASSERT in here for memory failure,
8320  // but it still might return "" if various verification fails.
8321  std::unique_ptr<OTLedger> pLedger(
8322  OTAPI()->LoadNymboxNoVerify(theServerID, theUserID));
8323 
8324  if (nullptr == pLedger) {
8325  otOut << __FUNCTION__
8326  << ": Failure calling OT_API::LoadNymboxNoVerify.\n";
8327  }
8328  else // success
8329  {
8330  OTString strOutput(*pLedger); // For the output
8331  std::string pBuf = strOutput.Get();
8332  return pBuf;
8333  }
8334 
8335  return "";
8336 }
8337 
8339  const std::string& SERVER_ID, const std::string& USER_ID,
8340  const std::string& ACCOUNT_ID) const // Returns "",
8341  // or an inbox.
8342 {
8343  if (SERVER_ID.empty()) {
8344  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8345  OT_FAIL;
8346  }
8347  if (USER_ID.empty()) {
8348  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8349  OT_FAIL;
8350  }
8351  if (ACCOUNT_ID.empty()) {
8352  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8353  OT_FAIL;
8354  }
8355 
8356  const OTIdentifier theServerID(SERVER_ID);
8357  const OTIdentifier theUserID(USER_ID);
8358  const OTIdentifier theAccountID(ACCOUNT_ID);
8359 
8360  // There is an OT_ASSERT in here for memory failure,
8361  // but it still might return "" if various verification fails.
8362  std::unique_ptr<OTLedger> pLedger(
8363  OTAPI()->LoadInbox(theServerID, theUserID, theAccountID));
8364 
8365  if (nullptr == pLedger) {
8366  otWarn << __FUNCTION__
8367  << ": Failure calling OT_API::LoadInbox.\nAccount ID : "
8368  << ACCOUNT_ID << "\n";
8369  }
8370  else // success
8371  {
8372  OTString strOutput(*pLedger); // For the output
8373  std::string pBuf = strOutput.Get();
8374  return pBuf;
8375  }
8376 
8377  return "";
8378 }
8379 
8381  const std::string& SERVER_ID, const std::string& USER_ID,
8382  const std::string& ACCOUNT_ID) const // Returns "", or an inbox.
8383 {
8384  if (SERVER_ID.empty()) {
8385  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8386  OT_FAIL;
8387  }
8388  if (USER_ID.empty()) {
8389  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8390  OT_FAIL;
8391  }
8392  if (ACCOUNT_ID.empty()) {
8393  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8394  OT_FAIL;
8395  }
8396 
8397  const OTIdentifier theServerID(SERVER_ID);
8398  const OTIdentifier theUserID(USER_ID);
8399  const OTIdentifier theAccountID(ACCOUNT_ID);
8400 
8401  // There is an OT_ASSERT in here for memory failure,
8402  // but it still might return "" if various verification fails.
8403  std::unique_ptr<OTLedger> pLedger(
8404  OTAPI()->LoadInboxNoVerify(theServerID, theUserID, theAccountID));
8405 
8406  if (nullptr == pLedger) {
8407  otWarn << __FUNCTION__
8408  << ": Failure calling OT_API::LoadInboxNoVerify.\nAccount ID : "
8409  << ACCOUNT_ID << "\n";
8410  }
8411  else // success
8412  {
8413  OTString strOutput(*pLedger); // For the output
8414  std::string pBuf = strOutput.Get();
8415  return pBuf;
8416  }
8417 
8418  return "";
8419 }
8420 
8421 std::string OTAPI_Exec::LoadOutbox(const std::string& SERVER_ID,
8422  const std::string& USER_ID,
8423  const std::string& ACCOUNT_ID) const
8424 {
8425  if (SERVER_ID.empty()) {
8426  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8427  OT_FAIL;
8428  }
8429  if (USER_ID.empty()) {
8430  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8431  OT_FAIL;
8432  }
8433  if (ACCOUNT_ID.empty()) {
8434  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8435  OT_FAIL;
8436  }
8437 
8438  const OTIdentifier theServerID(SERVER_ID);
8439  const OTIdentifier theUserID(USER_ID);
8440  const OTIdentifier theAccountID(ACCOUNT_ID);
8441 
8442  // There is an OT_ASSERT in here for memory failure,
8443  // but it still might return "" if various verification fails.
8444  std::unique_ptr<OTLedger> pLedger(
8445  OTAPI()->LoadOutbox(theServerID, theUserID, theAccountID));
8446 
8447  if (nullptr == pLedger) {
8448  otWarn << __FUNCTION__
8449  << ": Failure calling OT_API::LoadOutbox().\nAccount ID : "
8450  << ACCOUNT_ID << "\n";
8451  }
8452  else // success
8453  {
8454  OTString strOutput(*pLedger); // For the output
8455  std::string pBuf = strOutput.Get();
8456  return pBuf;
8457  }
8458 
8459  return "";
8460 }
8461 
8462 std::string OTAPI_Exec::LoadOutboxNoVerify(const std::string& SERVER_ID,
8463  const std::string& USER_ID,
8464  const std::string& ACCOUNT_ID) const
8465 {
8466  if (SERVER_ID.empty()) {
8467  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8468  OT_FAIL;
8469  }
8470  if (USER_ID.empty()) {
8471  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8472  OT_FAIL;
8473  }
8474  if (ACCOUNT_ID.empty()) {
8475  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8476  OT_FAIL;
8477  }
8478 
8479  const OTIdentifier theServerID(SERVER_ID);
8480  const OTIdentifier theUserID(USER_ID);
8481  const OTIdentifier theAccountID(ACCOUNT_ID);
8482 
8483  // There is an OT_ASSERT in here for memory failure,
8484  // but it still might return "" if various verification fails.
8485  std::unique_ptr<OTLedger> pLedger(
8486  OTAPI()->LoadOutboxNoVerify(theServerID, theUserID, theAccountID));
8487 
8488  if (nullptr == pLedger) {
8489  otWarn << __FUNCTION__
8490  << ": Failure calling OT_API::LoadOutboxNoVerify.\nAccount ID : "
8491  << ACCOUNT_ID << "\n";
8492  }
8493  else // success
8494  {
8495  OTString strOutput(*pLedger); // For the output
8496  std::string pBuf = strOutput.Get();
8497  return pBuf;
8498  }
8499 
8500  return "";
8501 }
8502 
8504  const std::string& SERVER_ID, const std::string& USER_ID) const // Returns
8505  // "", or
8506  // an
8507  // inbox.
8508 {
8509  if (SERVER_ID.empty()) {
8510  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8511  OT_FAIL;
8512  }
8513  if (USER_ID.empty()) {
8514  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8515  OT_FAIL;
8516  }
8517 
8518  const OTIdentifier theServerID(SERVER_ID);
8519  const OTIdentifier theUserID(USER_ID);
8520 
8521  // There is an OT_ASSERT in here for memory failure,
8522  // but it still might return "" if various verification fails.
8523  std::unique_ptr<OTLedger> pLedger(
8524  OTAPI()->LoadPaymentInbox(theServerID, theUserID));
8525 
8526  if (nullptr == pLedger) {
8527  otWarn << __FUNCTION__
8528  << ": Failure calling OT_API::LoadPaymentInbox.\n User ID : "
8529  << USER_ID << "\n";
8530  }
8531  else // success
8532  {
8533  OTString strOutput(*pLedger); // For the output
8534  std::string pBuf = strOutput.Get();
8535  return pBuf;
8536  }
8537 
8538  return "";
8539 }
8540 
8542  const std::string& SERVER_ID,
8543  const std::string& USER_ID) const // Returns "", or a paymentInbox.
8544 {
8545  if (SERVER_ID.empty()) {
8546  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8547  OT_FAIL;
8548  }
8549  if (USER_ID.empty()) {
8550  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8551  OT_FAIL;
8552  }
8553 
8554  const OTIdentifier theServerID(SERVER_ID);
8555  const OTIdentifier theUserID(USER_ID);
8556 
8557  // There is an OT_ASSERT in here for memory failure,
8558  // but it still might return "" if various verification fails.
8559  std::unique_ptr<OTLedger> pLedger(
8560  OTAPI()->LoadPaymentInboxNoVerify(theServerID, theUserID));
8561 
8562  if (nullptr == pLedger) {
8563  otWarn
8564  << __FUNCTION__
8565  << ": Failure calling OT_API::LoadPaymentInboxNoVerify.\nUser ID: "
8566  << USER_ID << "\n";
8567  }
8568  else // success
8569  {
8570  OTString strOutput(*pLedger); // For the output
8571  std::string pBuf = strOutput.Get();
8572  return pBuf;
8573  }
8574 
8575  return "";
8576 }
8577 
8578 std::string OTAPI_Exec::LoadRecordBox(const std::string& SERVER_ID,
8579  const std::string& USER_ID,
8580  const std::string& ACCOUNT_ID) const
8581 {
8582  if (SERVER_ID.empty()) {
8583  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8584  OT_FAIL;
8585  }
8586  if (USER_ID.empty()) {
8587  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8588  OT_FAIL;
8589  }
8590  if (ACCOUNT_ID.empty()) {
8591  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8592  OT_FAIL;
8593  }
8594 
8595  const OTIdentifier theServerID(SERVER_ID);
8596  const OTIdentifier theUserID(USER_ID);
8597  const OTIdentifier theAccountID(ACCOUNT_ID);
8598 
8599  // There is an OT_ASSERT in here for memory failure,
8600  // but it still might return "" if various verification fails.
8601  std::unique_ptr<OTLedger> pLedger(
8602  OTAPI()->LoadRecordBox(theServerID, theUserID, theAccountID));
8603 
8604  if (nullptr == pLedger) {
8605  otWarn << __FUNCTION__ << ": Failure calling OT_API::LoadRecordBox.\n";
8606  }
8607  else // success
8608  {
8609  OTString strOutput(*pLedger); // For the output
8610  std::string pBuf = strOutput.Get();
8611  return pBuf;
8612  }
8613  return "";
8614 }
8615 
8617  const std::string& SERVER_ID, const std::string& USER_ID,
8618  const std::string& ACCOUNT_ID) const
8619 {
8620  if (SERVER_ID.empty()) {
8621  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8622  OT_FAIL;
8623  }
8624  if (USER_ID.empty()) {
8625  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8626  OT_FAIL;
8627  }
8628  if (ACCOUNT_ID.empty()) {
8629  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8630  OT_FAIL;
8631  }
8632 
8633  const OTIdentifier theServerID(SERVER_ID);
8634  const OTIdentifier theUserID(USER_ID);
8635  const OTIdentifier theAccountID(ACCOUNT_ID);
8636 
8637  // There is an OT_ASSERT in here for memory failure,
8638  // but it still might return "" if various verification fails.
8639  std::unique_ptr<OTLedger> pLedger(
8640  OTAPI()->LoadRecordBoxNoVerify(theServerID, theUserID, theAccountID));
8641 
8642  if (nullptr == pLedger) {
8643  otWarn << __FUNCTION__
8644  << ": Failure calling OT_API::LoadRecordBoxNoVerify.\n";
8645  }
8646  else // success
8647  {
8648  const OTString strOutput(*pLedger); // For the output
8649  std::string pBuf = strOutput.Get();
8650  return pBuf;
8651  }
8652  return "";
8653 }
8654 
8655 std::string OTAPI_Exec::LoadExpiredBox(const std::string& SERVER_ID,
8656  const std::string& USER_ID) const
8657 {
8658  if (SERVER_ID.empty()) {
8659  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8660  OT_FAIL;
8661  }
8662  if (USER_ID.empty()) {
8663  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8664  OT_FAIL;
8665  }
8666 
8667  const OTIdentifier theServerID(SERVER_ID);
8668  const OTIdentifier theUserID(USER_ID);
8669 
8670  // There is an OT_ASSERT in here for memory failure,
8671  // but it still might return "" if various verification fails.
8672  std::unique_ptr<OTLedger> pLedger(
8673  OTAPI()->LoadExpiredBox(theServerID, theUserID));
8674 
8675  if (nullptr == pLedger) {
8676  otWarn << __FUNCTION__ << ": Failure calling OT_API::LoadExpiredBox.\n";
8677  }
8678  else // success
8679  {
8680  OTString strOutput(*pLedger); // For the output
8681  std::string pBuf = strOutput.Get();
8682  return pBuf;
8683  }
8684  return "";
8685 }
8686 
8688  const std::string& SERVER_ID,
8689  const std::string& USER_ID) const // Returns nullptr, or a ExpiredBox.
8690 {
8691  if (SERVER_ID.empty()) {
8692  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8693  OT_FAIL;
8694  }
8695  if (USER_ID.empty()) {
8696  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8697  OT_FAIL;
8698  }
8699 
8700  const OTIdentifier theServerID(SERVER_ID);
8701  const OTIdentifier theUserID(USER_ID);
8702 
8703  // There is an OT_ASSERT in here for memory failure,
8704  // but it still might return "" if various verification fails.
8705  std::unique_ptr<OTLedger> pLedger(
8706  OTAPI()->LoadExpiredBoxNoVerify(theServerID, theUserID));
8707 
8708  if (nullptr == pLedger) {
8709  otWarn << __FUNCTION__
8710  << ": Failure calling OT_API::LoadExpiredBoxNoVerify.\n";
8711  }
8712  else // success
8713  {
8714  const OTString strOutput(*pLedger); // For the output
8715  std::string pBuf = strOutput.Get();
8716  return pBuf;
8717  }
8718  return "";
8719 }
8720 
8722  const std::string& SERVER_ID, const std::string& USER_ID,
8723  const bool& bIsInbox, // true == payments inbox. false == payments outbox.
8724  const int32_t& nIndex, // removes payment instrument (from payments in or
8725  // out box) and moves to record box.
8726  const bool& bSaveCopy) const // If false, then will NOT save a copy to
8727  // record box.
8728 {
8729  OT_ASSERT(nIndex >= 0);
8730  if (SERVER_ID.empty()) {
8731  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8732  OT_FAIL;
8733  }
8734  if (USER_ID.empty()) {
8735  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8736  OT_FAIL;
8737  }
8738 
8739  const OTIdentifier theServerID(SERVER_ID);
8740  const OTIdentifier theUserID(USER_ID);
8741 
8742  return OTAPI()->RecordPayment(theServerID, theUserID, bIsInbox, nIndex,
8743  bSaveCopy);
8744 }
8745 
8747  const std::string& SERVER_ID, const std::string& USER_ID,
8748  const std::string& ACCOUNT_ID, // USER_ID can be passed here as well.
8749  const int32_t& nIndex,
8750  const bool& bClearAll) const // if true, nIndex is ignored.
8751 {
8752  OT_ASSERT(nIndex >= 0);
8753  if (SERVER_ID.empty()) {
8754  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8755  OT_FAIL;
8756  }
8757  if (USER_ID.empty()) {
8758  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8759  OT_FAIL;
8760  }
8761  if (ACCOUNT_ID.empty()) {
8762  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8763  OT_FAIL;
8764  }
8765 
8766  const OTIdentifier theServerID(SERVER_ID);
8767  const OTIdentifier theUserID(USER_ID);
8768  const OTIdentifier theAcctID(ACCOUNT_ID);
8769 
8770  return OTAPI()->ClearRecord(theServerID, theUserID, theAcctID, nIndex,
8771  bClearAll);
8772 }
8773 
8774 bool OTAPI_Exec::ClearExpired(const std::string& SERVER_ID,
8775  const std::string& USER_ID, const int32_t& nIndex,
8776  const bool& bClearAll) const // if true, nIndex is
8777  // ignored.
8778 {
8779  OT_ASSERT(nIndex >= 0);
8780  if (SERVER_ID.empty()) {
8781  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8782  OT_FAIL;
8783  }
8784  if (USER_ID.empty()) {
8785  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8786  OT_FAIL;
8787  }
8788 
8789  const OTIdentifier theServerID(SERVER_ID);
8790  const OTIdentifier theUserID(USER_ID);
8791 
8792  return OTAPI()->ClearExpired(theServerID, theUserID, nIndex, bClearAll);
8793 }
8794 
8839 // Returns number of transactions within, or -1 for error.
8840 int32_t OTAPI_Exec::Ledger_GetCount(const std::string& SERVER_ID,
8841  const std::string& USER_ID,
8842  const std::string& ACCOUNT_ID,
8843  const std::string& THE_LEDGER) const
8844 {
8845  if (SERVER_ID.empty()) {
8846  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8847  OT_FAIL;
8848  }
8849  if (USER_ID.empty()) {
8850  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8851  OT_FAIL;
8852  }
8853  if (ACCOUNT_ID.empty()) {
8854  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8855  OT_FAIL;
8856  }
8857  if (THE_LEDGER.empty()) {
8858  otErr << __FUNCTION__ << ": Null: THE_LEDGER passed in!\n";
8859  OT_FAIL;
8860  }
8861 
8862  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
8863  theAccountID(ACCOUNT_ID);
8864 
8865  OTString strLedger(THE_LEDGER);
8866  OTLedger theLedger(theUserID, theAccountID, theServerID);
8867 
8868  if (!theLedger.LoadLedgerFromString(strLedger)) {
8869  OTString strAcctID(theAccountID);
8870  otErr << __FUNCTION__
8871  << ": Error loading ledger from string. Acct ID: " << strAcctID
8872  << "\n";
8873  return -1;
8874  }
8875 
8876  return theLedger.GetTransactionCount();
8877 }
8878 
8879 // Creates a new 'response' ledger, set up with the right Server ID, etc, so you
8880 // can add the 'response' items to it, one by one. (Pass in the original ledger
8881 // that you are responding to, as it uses the data from it to set up the
8882 // response.)
8883 // The original ledger is your inbox. Inbox receipts are the only things you
8884 // would
8885 // ever create a "response" to, as part of your "process inbox" process.
8886 //
8888  const std::string& SERVER_ID, const std::string& USER_ID,
8889  const std::string& ACCOUNT_ID, const std::string& ORIGINAL_LEDGER) const
8890 {
8891  if (SERVER_ID.empty()) {
8892  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8893  OT_FAIL;
8894  }
8895  if (USER_ID.empty()) {
8896  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8897  OT_FAIL;
8898  }
8899  if (ACCOUNT_ID.empty()) {
8900  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8901  OT_FAIL;
8902  }
8903  if (ORIGINAL_LEDGER.empty()) {
8904  otErr << __FUNCTION__ << ": Null: ORIGINAL_LEDGER passed in!\n";
8905  OT_FAIL;
8906  }
8907 
8908  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
8909  theAccountID(ACCOUNT_ID);
8911  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
8912  if (nullptr == pNym) return "";
8913  // Let's load up the ledger (an inbox) that was passed in...
8914  OTString strOriginalLedger(ORIGINAL_LEDGER);
8915  OTLedger theOriginalLedger(theUserID, theAccountID, theServerID);
8916 
8917  if (!theOriginalLedger.LoadLedgerFromString(strOriginalLedger)) {
8918  OTString strAcctID(theAccountID);
8919  otErr << __FUNCTION__
8920  << ": Error loading ledger from string. Acct ID: " << strAcctID
8921  << "\n";
8922  return "";
8923  }
8924 
8925  if (!theOriginalLedger.VerifyAccount(*pNym)) {
8926  OTString strAcctID(theAccountID);
8927  otErr << __FUNCTION__
8928  << ": Error verifying original ledger. Acct ID: " << strAcctID
8929  << "\n";
8930  return "";
8931  }
8932  // By this point, the ledger is loaded properly from the string,
8933  // Let's create the response to it.
8934  std::unique_ptr<OTLedger> pResponseLedger(OTLedger::GenerateLedger(
8935  theUserID, theAccountID, theServerID, OTLedger::message));
8936  if (nullptr == pResponseLedger) {
8937  OTString strAcctID(theAccountID);
8938  otErr << __FUNCTION__
8939  << ": Error generating response ledger. Acct ID: " << strAcctID
8940  << "\n";
8941  return "";
8942  }
8943  pResponseLedger->SignContract(*pNym);
8944  pResponseLedger->SaveContract();
8945 
8946  OTString strOutput(*pResponseLedger); // For the output
8947 
8948  std::string pBuf = strOutput.Get();
8949 
8950  return pBuf;
8951 }
8952 
8953 // Lookup a transaction or its ID (from within a ledger) based on index or
8954 // transaction number.
8955 //
8956 // The transaction number is returned as a string, because I return ALL int64_t
8957 // ints as a string (in the API.) In C, you can just call StringToLong to
8958 // convert it back.
8959 // This makes it easier for the guys who use scripting languages. (This file is
8960 // primarily for them. If you are lower-level, you should use
8961 // OpenTransactions.h/.cpp
8962 // and then use this one as a model for how to do it. Or use this one if you
8963 // insist
8964 // on straight C, since all these functions are extern "C".)
8965 //
8967  const std::string& SERVER_ID, const std::string& USER_ID,
8968  const std::string& ACCOUNT_ID, const std::string& THE_LEDGER,
8969  const int32_t& nIndex) const // returns transaction by index (from ledger)
8970 {
8971  if (SERVER_ID.empty()) {
8972  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
8973  OT_FAIL;
8974  }
8975  if (USER_ID.empty()) {
8976  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
8977  OT_FAIL;
8978  }
8979  if (ACCOUNT_ID.empty()) {
8980  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
8981  OT_FAIL;
8982  }
8983  if (THE_LEDGER.empty()) {
8984  otErr << __FUNCTION__ << ": Null: THE_LEDGER passed in!\n";
8985  OT_FAIL;
8986  }
8987 
8988  if (0 > nIndex) {
8989  otErr << __FUNCTION__
8990  << ": nIndex is out of bounds (it's in the negative!)\n";
8991  OT_FAIL;
8992  }
8993 
8994  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
8995  theAccountID(ACCOUNT_ID);
8996 
8997  OTString strLedger(THE_LEDGER);
8998  OTLedger theLedger(theUserID, theAccountID, theServerID);
8999  // std::set<int64_t> setUnloaded;
9000 
9001  if (!theLedger.LoadLedgerFromString(strLedger)
9002  // || !theLedger.LoadBoxReceipts(&setUnloaded) // This is
9003  // done below, for the individual transaction, for better optimization.
9004  ) {
9005  OTString strAcctID(theAccountID);
9006  otErr << __FUNCTION__
9007  << ": Error loading ledger from string, or loading box receipts "
9008  "subsequently. Acct ID: " << strAcctID << "\n";
9009  return "";
9010  }
9011 
9012  // At this point, I know theLedger loaded successfully.
9013 
9014  if (nIndex >= theLedger.GetTransactionCount()) {
9015  otErr << __FUNCTION__ << ": out of bounds: " << nIndex << "\n";
9016  return ""; // out of bounds. I'm saving from an OT_ASSERT_MSG()
9017  // happening here. (Maybe I shouldn't.)
9018  }
9019 
9020  OTTransaction* pTransaction = theLedger.GetTransactionByIndex(nIndex);
9021 
9022  if (nullptr == pTransaction) {
9023  otErr << __FUNCTION__
9024  << ": Failure: good index but uncovered \"\" pointer: " << nIndex
9025  << "\n";
9026  return ""; // Weird.
9027  }
9028 
9029  const int64_t lTransactionNum = pTransaction->GetTransactionNum();
9030  // At this point, I actually have the transaction pointer, so let's return
9031  // it in string form...
9032 
9033  // Update: for transactions in ABBREVIATED form, the string is empty, since
9034  // it has never actually
9035  // been signed (in fact the whole point32_t with abbreviated transactions in
9036  // a ledger is that they
9037  // take up very little room, and have no signature of their own, but exist
9038  // merely as XML tags on
9039  // their parent ledger.)
9040  //
9041  // THEREFORE I must check to see if this transaction is abbreviated and if
9042  // so, sign it in order to
9043  // force the UpdateContents() call, so the programmatic user of this API
9044  // will be able to load it up.
9045  //
9046  if (pTransaction->IsAbbreviated()) {
9047  theLedger.LoadBoxReceipt(static_cast<int64_t>(
9048  lTransactionNum)); // I don't check return val here because I still
9049  // want it to send the abbreviated form, if this
9050  // fails.
9051  pTransaction =
9052  theLedger.GetTransaction(static_cast<int64_t>(lTransactionNum));
9053  if (nullptr == pTransaction) {
9054  otErr << __FUNCTION__ << ": good index but uncovered \"\" pointer "
9055  "after trying to load full version of "
9056  "receipt (from abbreviated): " << nIndex
9057  << "\n";
9058  return ""; // Weird.
9059  }
9060  // I was doing this when it was abbreviated. But now (above) I just
9061  // load the box receipt itself. (This code is a hack that creates a
9062  // serialized abbreviated version.)
9063  // OTPseudonym * pNym = OTAPI()->GetNym(theUserID,
9064  // "OTAPI_Exec::Ledger_GetTransactionByIndex");
9065  // if (nullptr == pNym) return "";
9066  //
9067  // pTransaction->ReleaseSignatures();
9068  // pTransaction->SignContract(*pNym);
9069  // pTransaction->SaveContract();
9070  }
9071 
9072  const OTString strOutput(*pTransaction); // For the output
9073  std::string pBuf = strOutput.Get();
9074 
9075  return pBuf;
9076 }
9077 
9078 // Returns transaction by ID (transaction numbers are int64_t ints, and thus
9079 // they are passed as strings in this OT high-level API.)
9080 // Note: If this function returns "" for a transaction you KNOW is on
9081 // the ledger, then you probably just need to download it. (The box receipts
9082 // are stored in separate files and downloaded separately as well.)
9083 //
9085  const std::string& SERVER_ID, const std::string& USER_ID,
9086  const std::string& ACCOUNT_ID, const std::string& THE_LEDGER,
9087  const int64_t& TRANSACTION_NUMBER) const
9088 {
9089  if (SERVER_ID.empty()) {
9090  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
9091  OT_FAIL;
9092  }
9093  if (USER_ID.empty()) {
9094  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
9095  OT_FAIL;
9096  }
9097  if (ACCOUNT_ID.empty()) {
9098  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
9099  OT_FAIL;
9100  }
9101  if (THE_LEDGER.empty()) {
9102  otErr << __FUNCTION__ << ": Null: THE_LEDGER passed in!\n";
9103  OT_FAIL;
9104  }
9105  if (0 > TRANSACTION_NUMBER) {
9106  otErr << __FUNCTION__ << ": Negative: TRANSACTION_NUMBER passed in!\n";
9107  OT_FAIL;
9108  }
9109 
9110  const int64_t lTransactionNumber = TRANSACTION_NUMBER;
9111 
9112  if (0 > lTransactionNumber) {
9113  otErr << __FUNCTION__
9114  << ": Bad transaction number passed in (negative value)\n";
9115  OT_FAIL;
9116  }
9117 
9118  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
9119  theAccountID(ACCOUNT_ID);
9120 
9121  OTString strLedger(THE_LEDGER);
9122 
9123  OTLedger theLedger(theUserID, theAccountID, theServerID);
9124 
9125  if (!theLedger.LoadLedgerFromString(strLedger)) {
9126  OTString strAcctID(theAccountID);
9127  otErr << __FUNCTION__
9128  << ": Error loading ledger from string. Acct ID: " << strAcctID
9129  << "\n";
9130  return "";
9131  }
9132  // At this point, I know theLedger loaded successfully.
9133 
9134  OTTransaction* pTransaction =
9135  theLedger.GetTransaction(static_cast<int64_t>(lTransactionNumber));
9136  // No need to cleanup this transaction, the ledger owns it already.
9137 
9138  if (nullptr == pTransaction) {
9139  otOut << __FUNCTION__
9140  << ": No transaction found in ledger with that number : "
9141  << lTransactionNumber << ".\n";
9142  return ""; // Maybe he was just looking; this isn't necessarily an
9143  // error.
9144  }
9145 
9146  // At this point, I actually have the transaction pointer, so let's return
9147  // it in string form...
9148  //
9149  const int64_t lTransactionNum = pTransaction->GetTransactionNum();
9150  OT_ASSERT(lTransactionNum == lTransactionNumber);
9151 
9152  // Update: for transactions in ABBREVIATED form, the string is empty, since
9153  // it has never actually
9154  // been signed (in fact the whole point32_t with abbreviated transactions in
9155  // a ledger is that they
9156  // take up very little room, and have no signature of their own, but exist
9157  // merely as XML tags on
9158  // their parent ledger.)
9159  //
9160  // THEREFORE I must check to see if this transaction is abbreviated and if
9161  // so, sign it in order to
9162  // force the UpdateContents() call, so the programmatic user of this API
9163  // will be able to load it up.
9164  //
9165  if (pTransaction->IsAbbreviated()) {
9166  // First we see if we are able to load the full version of this box
9167  // receipt.
9168  // (Perhaps it has already been downloaded sometime in the past, and
9169  // simply
9170  // needs to be loaded up. Worth a shot.)
9171  //
9172  const bool& bLoadedBoxReceipt = theLedger.LoadBoxReceipt(
9173  static_cast<int64_t>(lTransactionNum)); // I still want it to send
9174  // the abbreviated form, if
9175  // this fails.
9176 
9177  // Grab this pointer again, since the object was re-instantiated
9178  // in the case of a successful LoadBoxReceipt.
9179  //
9180  if (bLoadedBoxReceipt)
9181  pTransaction =
9182  theLedger.GetTransaction(static_cast<int64_t>(lTransactionNum));
9183 
9184  // (else if false == bLoadedBoxReceipt, then pTransaction ALREADY points
9185  // to the abbreviated version.)
9186  if (nullptr == pTransaction) {
9187  otErr << __FUNCTION__ << ": good ID, but uncovered \"\" pointer "
9188  "after trying to load full version of "
9189  "receipt (from abbreviated.) Probably "
9190  "just need to download this one...\n";
9191  return ""; // Weird.
9192  }
9193  // If it's STILL abbreviated after the above efforts, then there's
9194  // nothing else I can do
9195  // except return the abbreviated version. The caller may still need the
9196  // info available on
9197  // the abbreviated version. (And the caller may yet download the full
9198  // version...)
9199  //
9200  else if (pTransaction->IsAbbreviated()) {
9201  OTPseudonym* pNym = OTAPI()->GetNym(theUserID, __FUNCTION__);
9202  if (nullptr == pNym) return ""; // Weird.
9203  pTransaction->ReleaseSignatures();
9204  pTransaction->SignContract(*pNym);
9205  pTransaction->SaveContract();
9206  }
9207  }
9208  const OTString strOutput(*pTransaction); // For the output
9209  std::string pBuf = strOutput.Get();
9210 
9211  return pBuf;
9212 }
9213 
9214 // OTAPI_Exec::Ledger_GetInstrument (by index)
9215 //
9216 // Lookup a financial instrument (from within a transaction that is inside
9217 // a paymentInbox ledger) based on index.
9218 /*
9219 sendUserInstrument does this:
9220 -- Puts instrument (a contract string) as encrypted Payload on an OTMessage(1).
9221 -- Also puts instrument (same contract string) as CLEAR payload on an
9222 OTMessage(2).
9223 -- (1) is sent to server, and (2) is added to Outpayments messages.
9224 -- (1) gets added to recipient's Nymbox as "in ref to" string on a
9225 "instrumentNotice" transaction.
9226 -- When recipient processes Nymbox, the "instrumentNotice" transaction
9227 (containing (1) in its "in ref to"
9228 field) is copied and added to the recipient's paymentInbox.
9229 -- When recipient iterates through paymentInbox transactions, they are ALL
9230 "instrumentNotice" OTMessages.
9231 Each transaction contains an OTMessage in its "in ref to" field, and that
9232 OTMessage object contains an
9233 encrypted payload of the instrument itself (a contract string.)
9234 -- When sender gets Outpayments contents, the original instrument (contract
9235 string) is stored IN THE
9236 CLEAR as payload on an OTMessage.
9237 
9238 THEREFORE:
9239 TO EXTRACT INSTRUMENT FROM PAYMENTS INBOX:
9240 -- Iterate through the transactions in the payments inbox.
9241 -- (They should all be "instrumentNotice" transactions.)
9242 -- Each transaction contains (1) OTMessage in the "in ref to" field, which in
9243 turn contains an encrypted
9244 instrument in the messagePayload field.
9245 -- *** Therefore, this function, based purely on ledger index (as we iterate)
9246 extracts the
9247 OTMessage from the Transaction "in ref to" field (for the transaction at that
9248 index), then decrypts
9249 the payload on that message and returns the decrypted cleartext.
9250 */
9251 
9252 // DONE: Move most of the code in the below function into
9253 // OTLedger::GetInstrument.
9254 //
9255 // DONE: Finish writing OTClient::ProcessDepositResponse
9256 
9258  const std::string& SERVER_ID, const std::string& USER_ID,
9259  const std::string& ACCOUNT_ID, const std::string& THE_LEDGER,
9260  const int32_t& nIndex) const // returns financial instrument by index.
9261 {
9262  if (SERVER_ID.empty()) {
9263  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
9264  OT_FAIL;
9265  }
9266  if (USER_ID.empty()) {
9267  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
9268  OT_FAIL;
9269  }
9270  if (ACCOUNT_ID.empty()) {
9271  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
9272  OT_FAIL;
9273  }
9274  if (THE_LEDGER.empty()) {
9275  otErr << __FUNCTION__ << ": Null: THE_LEDGER passed in!\n";
9276  OT_FAIL;
9277  }
9278 
9279  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
9280  theAccountID(ACCOUNT_ID);
9281  OTPseudonym* pNym = OTAPI()->GetNym(theUserID, __FUNCTION__);
9282  if (nullptr == pNym) return "";
9283  OTString strLedger(THE_LEDGER);
9284  OTLedger theLedger(theUserID, theAccountID, theServerID);
9285  // std::set<int64_t> setUnloaded;
9286 
9287  if (!theLedger.LoadLedgerFromString(strLedger)
9288  // || !theLedger.LoadBoxReceipts(&setUnloaded) // This is
9289  // now done below, for the individual transaction, for better
9290  // optimization.
9291  ) // Update: now in the theLedger.GetInstrument call.
9292  {
9293  OTString strUserID(theUserID);
9294  OTString strAcctID(theAccountID);
9295  otErr << __FUNCTION__
9296  << ": Error loading ledger from string. UserID / Acct ID: "
9297  << strUserID << " / " << strAcctID << "\n";
9298  return "";
9299  }
9300  // At this point, I know theLedger loaded successfully.
9301  //
9302  std::unique_ptr<OTPayment> pPayment(
9303  GetInstrument(*pNym, nIndex, theLedger));
9304 
9305  if ((nullptr == pPayment) || !pPayment->IsValid()) {
9306  otOut << __FUNCTION__ << ": theLedger.GetInstrument either returned "
9307  "nullptr, or an invalid instrument.\n";
9308  }
9309  else {
9310  // NOTE: instead of loading up an OTPayment, and then loading a
9311  // cheque/purse/etc from it,
9312  // we just send the cheque/purse/etc directly and use it to construct
9313  // the OTPayment.
9314  // (Saves a step.)
9315  //
9316  OTString strPaymentContents;
9317 
9318  if (!pPayment->GetPaymentContents(strPaymentContents)) {
9319  otOut << __FUNCTION__ << ": Failed retrieving payment instrument "
9320  "from OTPayment object.\n";
9321  return "";
9322  }
9323  std::string gBuf = strPaymentContents.Get();
9324  return gBuf;
9325  }
9326 
9327  return "";
9328 }
9329 
9330 /*
9331 
9332 // returns the message, optionally with Subject: as first line.
9333 
9334  std::string OTAPI_Exec::GetNym_MailContentsByIndex(const std::string& NYM_ID,
9335 const int32_t& nIndex)
9336 {
9337  OT_ASSERT_MSG("" != NYM_ID, "Null NYM_ID passed to
9338 OTAPI_Exec::GetNym_MailContentsByIndex");
9339 
9340  std::string strFunc = "OTAPI_Exec::GetNym_MailContentsByIndex";
9341  OTIdentifier theNymID(NYM_ID);
9342  OTPseudonym * pNym = OTAPI()->GetNym(theNymID, strFunc);
9343  if (nullptr == pNym) return "";
9344  OTMessage * pMessage = pNym->GetMailByIndex(nIndex);
9345 
9346  if (nullptr != pMessage)
9347  {
9348  // SENDER: pMessage->m_strNymID
9349  // RECIPIENT: pMessage->m_strNymID2
9350  // MESSAGE: pMessage->m_ascPayload (in an OTEnvelope)
9351  //
9352  OTEnvelope theEnvelope;
9353  OTString strEnvelopeContents;
9354 
9355  // Decrypt the Envelope.
9356  if (theEnvelope.SetAsciiArmoredData(pMessage->m_ascPayload) &&
9357  theEnvelope.Open(*pNym, strEnvelopeContents))
9358  {
9359  std::string pBuf = strEnvelopeContents.Get();
9360 
9361  return pBuf;
9362  }
9363  }
9364  return "";
9365 }
9366 
9367 */
9368 
9369 // Returns a transaction number, or -1 for error.
9371  const std::string& SERVER_ID, const std::string& USER_ID,
9372  const std::string& ACCOUNT_ID, const std::string& THE_LEDGER,
9373  const int32_t& nIndex) const // returns transaction number by index.
9374 {
9375  if (SERVER_ID.empty()) {
9376  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
9377  OT_FAIL;
9378  }
9379  if (USER_ID.empty()) {
9380  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
9381  OT_FAIL;
9382  }
9383  if (ACCOUNT_ID.empty()) {
9384  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
9385  OT_FAIL;
9386  }
9387  if (THE_LEDGER.empty()) {
9388  otErr << __FUNCTION__ << ": Null: THE_LEDGER passed in!\n";
9389  OT_FAIL;
9390  }
9391 
9392  if (0 > nIndex) {
9393  otErr << __FUNCTION__
9394  << ": nIndex is out of bounds (it's in the negative!)\n";
9395  OT_FAIL;
9396  }
9397 
9398  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
9399  theAccountID(ACCOUNT_ID);
9400 
9401  OTString strLedger(THE_LEDGER);
9402  OTString strOutput("-1"); // For the output
9403 
9404  int64_t lTransactionNumber = 0;
9405  OTTransaction* pTransaction = nullptr;
9406 
9407  OTLedger theLedger(theUserID, theAccountID, theServerID);
9408 
9409  if (!theLedger.LoadLedgerFromString(strLedger)) {
9410  OTString strAcctID(theAccountID);
9411  otErr << __FUNCTION__
9412  << ": Error loading ledger from string. Acct ID: " << strAcctID
9413  << "\n";
9414  }
9415 
9416  // At this point, I know theLedger loaded successfully.
9417  else if (nIndex >= theLedger.GetTransactionCount()) {
9418  otErr << __FUNCTION__ << ": out of bounds: " << nIndex << "\n";
9419  // out of bounds. I'm saving from an OT_ASSERT_MSG() happening here.
9420  // (Maybe I shouldn't.)
9421  }
9422  else if (nullptr ==
9423  (pTransaction = theLedger.GetTransactionByIndex(nIndex))) {
9424  otErr << __FUNCTION__
9425  << ": good index but uncovered \"\" pointer: " << nIndex << "\n";
9426  } // NO NEED TO CLEANUP the transaction, since it is already "owned" by
9427  // theLedger.
9428 
9429  // At this point, I actually have the transaction pointer, so let's get the
9430  // ID...
9431  else if (0 >= (lTransactionNumber = pTransaction->GetTransactionNum())) {
9432  otErr << __FUNCTION__
9433  << ": negative or zero transaction num: " << lTransactionNumber
9434  << "\n";
9435  return -1;
9436  }
9437  else // success
9438  {
9439  return lTransactionNumber;
9440  }
9441 
9442  return -1;
9443 }
9444 
9445 // Add a transaction to a ledger.
9446 // (Returns the updated ledger.)
9447 //
9449  const std::string& SERVER_ID, const std::string& USER_ID,
9450  const std::string& ACCOUNT_ID, const std::string& THE_LEDGER,
9451  const std::string& THE_TRANSACTION) const
9452 {
9453  if (SERVER_ID.empty()) {
9454  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
9455  OT_FAIL;
9456  }
9457  if (USER_ID.empty()) {
9458  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
9459  OT_FAIL;
9460  }
9461  if (ACCOUNT_ID.empty()) {
9462  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
9463  OT_FAIL;
9464  }
9465  if (THE_LEDGER.empty()) {
9466  otErr << __FUNCTION__ << ": Null: THE_LEDGER passed in!\n";
9467  OT_FAIL;
9468  }
9469  if (THE_TRANSACTION.empty()) {
9470  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
9471  OT_FAIL;
9472  }
9473 
9474  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
9475  theAccountID(ACCOUNT_ID);
9476 
9477  OTString strLedger(THE_LEDGER);
9478  OTString strTransaction(THE_TRANSACTION);
9479 
9481  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
9482  if (nullptr == pNym) return "";
9483 
9484  OTLedger theLedger(theUserID, theAccountID, theServerID);
9485 
9486  if (!theLedger.LoadLedgerFromString(strLedger)) {
9487  OTString strAcctID(theAccountID);
9488  otErr << __FUNCTION__
9489  << ": Error loading ledger from string. Acct ID: " << strAcctID
9490  << "\n";
9491  return "";
9492  }
9493  else if (!theLedger.VerifyAccount(*pNym)) {
9494  OTString strAcctID(theAccountID);
9495  otErr << __FUNCTION__
9496  << ": Error verifying ledger in "
9497  "OTAPI_Exec::Ledger_AddTransaction. Acct ID: " << strAcctID
9498  << "\n";
9499  return "";
9500  }
9501 
9502  // At this point, I know theLedger loaded and verified successfully.
9503 
9504  OTTransaction* pTransaction =
9505  new OTTransaction(theUserID, theAccountID, theServerID);
9506  if (nullptr == pTransaction) {
9507  otErr << __FUNCTION__ << ": Error allocating memory in the OTAPI: "
9508  << "pTransaction"
9509  << " !\n";
9510  OT_FAIL;
9511  }
9512 
9513  if (!pTransaction->LoadContractFromString(strTransaction)) {
9514  OTString strAcctID(theAccountID);
9515  otErr << __FUNCTION__
9516  << ": Error loading transaction from string. Acct ID: "
9517  << strAcctID << "\n";
9518  delete pTransaction;
9519  pTransaction = nullptr;
9520  return "";
9521  }
9522  else if (!pTransaction->VerifyAccount(*pNym)) {
9523  OTString strAcctID(theAccountID);
9524  otErr << __FUNCTION__
9525  << ": Error verifying transaction. Acct ID: " << strAcctID
9526  << "\n";
9527  delete pTransaction;
9528  pTransaction = nullptr;
9529  return "";
9530  }
9531  // At this point, I know pTransaction loaded and verified successfully.
9532  // So let's add it to the ledger, save, and return updated ledger in string
9533  // form.
9534 
9535  theLedger.AddTransaction(
9536  *pTransaction); // Ledger now "owns" it and will handle cleanup.
9537 
9538  theLedger.ReleaseSignatures();
9539  theLedger.SignContract(*pNym);
9540  theLedger.SaveContract();
9541 
9542  OTString strOutput(theLedger); // For the output
9543 
9544  std::string pBuf = strOutput.Get();
9545 
9546  return pBuf;
9547 }
9548 
9549 // Create a 'response' transaction, that will be used to indicate my
9550 // acceptance or rejection of another transaction. Usually an entire
9551 // ledger full of these is sent to the server as I process the various
9552 // transactions in my inbox.
9553 //
9554 // The original transaction is passed in, and I generate a response transaction
9555 // based on it.
9556 // Also, the response ledger is passed in, so I load it, add the response
9557 // transaction, save
9558 // it back to string, and return the string.
9559 //
9560 // This way, users can call this function multiple times, adding transactions
9561 // until done.
9562 //
9564  const std::string& SERVER_ID, const std::string& USER_ID,
9565  const std::string& ACCOUNT_ID,
9566  const std::string& THE_LEDGER, // 'Response' ledger be sent to the server...
9567  const std::string& THE_TRANSACTION, // Responding to...?
9568  const bool& BOOL_DO_I_ACCEPT) const // 0 or 1 (true or false.)
9569 {
9570  if (SERVER_ID.empty()) {
9571  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
9572  OT_FAIL;
9573  }
9574  if (USER_ID.empty()) {
9575  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
9576  OT_FAIL;
9577  }
9578  if (ACCOUNT_ID.empty()) {
9579  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
9580  OT_FAIL;
9581  }
9582  if (THE_LEDGER.empty()) {
9583  otErr << __FUNCTION__ << ": Null: THE_LEDGER passed in!\n";
9584  OT_FAIL;
9585  }
9586  if (THE_TRANSACTION.empty()) {
9587  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
9588  OT_FAIL;
9589  }
9590 
9591  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
9592  theAcctID(ACCOUNT_ID);
9593 
9594  OTString strLedger(THE_LEDGER);
9595  OTString strTransaction(THE_TRANSACTION);
9596  OTServerContract* pServer = OTAPI()->GetServer(theServerID, __FUNCTION__);
9597  if (nullptr == pServer) return "";
9598  // By this point, pServer is a good pointer. (No need to cleanup.)
9599  const OTPseudonym* pServerNym = pServer->GetContractPublicNym();
9600 
9601  if (nullptr == pServerNym) {
9602  otOut << __FUNCTION__
9603  << ": No Contract Nym found in that Server Contract.\n";
9604  return "";
9605  }
9606  // By this point, pServerNym is a good pointer. (No need to cleanup.)
9607  OTPseudonym* pNym = OTAPI()->GetOrLoadPrivateNym(
9608  theUserID, false, __FUNCTION__); // This logs, ASSERTs, etc.
9609  if (nullptr == pNym) return "";
9610  // By this point, pNym is a good pointer, and is on the wallet. (No need to
9611  // cleanup.)
9612  OTLedger theLedger(theUserID, theAcctID, theServerID);
9613 
9614  if (!theLedger.LoadLedgerFromString(strLedger)) {
9615  OTString strAcctID(theAcctID);
9616  otErr << __FUNCTION__
9617  << ": Error loading ledger from string. Acct ID: " << strAcctID
9618  << "\n";
9619  return "";
9620  }
9621  else if (!theLedger.VerifyAccount(*pNym)) {
9622  OTString strAcctID(theAcctID);
9623  otErr << __FUNCTION__
9624  << ": Error verifying ledger. Acct ID: " << strAcctID << "\n";
9625  return "";
9626  }
9627 
9628  // At this point, I know theLedger loaded and verified successfully.
9629  // (This is the 'response' ledger that the user previously generated,
9630  // and now he is loading it up with responses that this function will
9631  // generate on his behalf.)
9632  OTTransaction theTransaction(theUserID, theAcctID, theServerID);
9633 
9634  if (!theTransaction.LoadContractFromString(strTransaction)) {
9635  OTString strAcctID(theAcctID);
9636  otErr << __FUNCTION__
9637  << ": Error loading transaction from string. Acct ID: "
9638  << strAcctID << "\n";
9639  return "";
9640  }
9641  OTTransaction* pTransaction = nullptr;
9642  std::unique_ptr<OTTransaction> theTransAngel;
9643 
9644  if (theTransaction.IsAbbreviated()) {
9645  pTransaction = LoadBoxReceipt(theTransaction,
9646  static_cast<int64_t>(OTLedger::inbox));
9647 
9648  if (nullptr == pTransaction) {
9649  OTString strAcctID(theAcctID);
9650  otErr << __FUNCTION__ << ": Error loading full transaction from "
9651  "abbreviated version of inbox receipt. "
9652  "Acct ID: " << strAcctID << "\n";
9653  return "";
9654  }
9655  theTransAngel.reset(pTransaction);
9656  }
9657  else
9658  pTransaction = &theTransaction;
9659  // BELOW THIS POINT, only use pTransaction, not theTransaction.
9660 
9661  // This transaction is presumably from the server, since we are in this
9662  // function in order to generate a response back to the server. So therefore
9663  // I want to verify that the server has actually signed the thing, before
9664  // I go off responding to it like a damned fool.
9665  //
9666  if (false ==
9667  pTransaction->VerifyAccount(*(const_cast<OTPseudonym*>(pServerNym)))) {
9668  OTString strAcctID(theAcctID);
9669  otErr << __FUNCTION__
9670  << ": Error verifying transaction. Acct ID: " << strAcctID
9671  << "\n";
9672  return "";
9673  }
9674 
9675  if ((OTTransaction::pending != pTransaction->GetType()) &&
9676  (OTTransaction::chequeReceipt != pTransaction->GetType()) &&
9677  (OTTransaction::voucherReceipt != pTransaction->GetType()) &&
9678  (OTTransaction::transferReceipt != pTransaction->GetType()) &&
9679  (OTTransaction::marketReceipt != pTransaction->GetType()) &&
9680  (OTTransaction::paymentReceipt != pTransaction->GetType()) &&
9681  (OTTransaction::finalReceipt != pTransaction->GetType()) &&
9682  (OTTransaction::basketReceipt != pTransaction->GetType())) {
9683  otErr << __FUNCTION__
9684  << ": wrong transaction type: " << pTransaction->GetTypeString()
9685  << ".\n";
9686  return "";
9687  }
9688  // At this point, I know pTransaction loaded and verified successfully.
9689  // So let's generate a response item based on it, and add it to a
9690  // processInbox
9691  // transaction to be added to that ledger (if one's not already there...)
9692 
9693  // First, check to see if there is a processInbox transaction already on
9694  // the ledger...
9695  OTTransaction* pResponse =
9697 
9698  // If it's not already there, create it and add it.
9699  if (nullptr == pResponse) {
9700  OTString strServerID(theServerID);
9701  int64_t lTransactionNumber = 0;
9702  bool bGotTransNum =
9703  pNym->GetNextTransactionNum(*pNym, strServerID, lTransactionNumber);
9704 
9705  if (!bGotTransNum) {
9706  OTString strNymID(theUserID);
9707  otOut << __FUNCTION__
9708  << ": User is all out of transaction numbers:\n" << strNymID
9709  << "\n";
9710  return "";
9711  }
9712 
9714  theUserID, theAcctID, theServerID, OTTransaction::processInbox,
9715  lTransactionNumber);
9716 
9717  if (nullptr == pResponse) {
9718  OTString strAcctID(theAcctID);
9719  otErr << __FUNCTION__
9720  << ": Error generating processInbox transaction for AcctID: "
9721  << strAcctID << "\n";
9722 
9723  pNym->AddTransactionNum(*pNym, strServerID, lTransactionNumber,
9724  true); // bSave=true. Have to add this back
9725  // since we failed to use it.
9726 
9727  return "";
9728  }
9729 
9730  theLedger.AddTransaction(
9731  *pResponse); // Ledger now "owns" it and will handle cleanup.
9732  }
9733 
9734  // At this point32_t I know pResponse is a processInbox transaction, ready
9735  // to go,
9736  // and that theLedger will handle any cleanup issues related to it.
9737 
9738  // Next let's create a new item that responds to pTransaction, and add that
9739  // item to pResponse. Then we'll return the updated ledger.
9740 
9741  OTItem::itemType theAcceptItemType = OTItem::error_state;
9742  OTItem::itemType theRejectItemType = OTItem::error_state;
9743 
9744  switch (pTransaction->GetType()) {
9746  theAcceptItemType = OTItem::acceptPending;
9747  theRejectItemType = OTItem::rejectPending;
9748  break;
9749 
9752  theAcceptItemType = OTItem::acceptCronReceipt;
9753  theRejectItemType = OTItem::disputeCronReceipt;
9754  break;
9755 
9759  theAcceptItemType = OTItem::acceptItemReceipt;
9760  theRejectItemType = OTItem::disputeItemReceipt;
9761  break;
9762 
9764  theAcceptItemType = OTItem::acceptFinalReceipt;
9765  theRejectItemType = OTItem::disputeFinalReceipt;
9766  break;
9767 
9769  theAcceptItemType = OTItem::acceptBasketReceipt;
9770  theRejectItemType = OTItem::disputeBasketReceipt;
9771  break;
9772 
9773  default:
9774  theAcceptItemType = OTItem::error_state;
9775  theRejectItemType = OTItem::error_state;
9776  otErr << __FUNCTION__ << ": Unexpected transaction type in: "
9777  << pTransaction->GetTypeString() << "\n";
9778  return "";
9779  }
9780  int64_t lReferenceTransactionNum = 0;
9781  int64_t lNumberOfOrigin = 0;
9782  OTString strNote;
9783  switch (pTransaction->GetType()) {
9788  lNumberOfOrigin = pTransaction->GetReferenceToNum();
9789  lReferenceTransactionNum =
9790  pTransaction->GetTransactionNum(); // <=== References the receipt in
9791  // my inbox.
9792  break;
9793 
9794  case OTTransaction::transferReceipt: // Contains "in ref to" acceptPending
9795  // item from someone who processed
9796  // their inbox to accept my transfer.
9797  case OTTransaction::pending: // Contains "in ref to" transfer item from
9798  // someone who sent me a transfer.
9799  case OTTransaction::chequeReceipt: // Contains "in ref to" depositCheque
9800  // item from someone who deposited my
9801  // cheque.
9802  case OTTransaction::voucherReceipt: // Contains "in ref to" depositCheque
9803  // item from someone who deposited my
9804  // voucher.
9805  {
9806  // Here's some code in case you need to load up the item.
9807  OTString strReference;
9808  pTransaction->GetReferenceString(strReference);
9809 
9810  if (!strReference.Exists()) {
9811  otErr << __FUNCTION__
9812  << ": No reference string found on transaction.\n";
9813  return "";
9814  }
9815  std::unique_ptr<OTItem> pOriginalItem(OTItem::CreateItemFromString(
9816  strReference, theServerID, pTransaction->GetReferenceToNum()));
9817 
9818  if (nullptr == pOriginalItem) {
9819  otErr << __FUNCTION__
9820  << ": Failed loading transaction item from string.\n";
9821  return "";
9822  }
9823  // pItem will be automatically cleaned up when it goes out of scope.
9824  if ((OTItem::request != pOriginalItem->GetStatus()) ||
9826  pOriginalItem->GetType()) && // I'm accepting a transfer
9827  // receipt
9828  // that was created by someone's
9829  // acceptPending (from a transfer I
9830  // sent.)
9831  (OTItem::transfer !=
9832  pOriginalItem->GetType()) && // I'm accepting a pending
9833  // transfer
9834  // that was created by someone's
9835  // transfer to me.
9837  pOriginalItem->GetType()) // I'm accepting a cheque or voucher
9838  // receipt that was created by someone's
9839  // depositCheque (of a cheque I wrote or
9840  // a voucher I remitted.)
9841  )) {
9842  otErr << __FUNCTION__ << ": Wrong item type or status attached "
9843  "as reference on transaction.\n";
9844  return "";
9845  }
9846  if (OTItem::transfer == pOriginalItem->GetType())
9847  pOriginalItem->GetNote(strNote);
9848  lNumberOfOrigin = pOriginalItem->GetNumberOfOrigin();
9849  lReferenceTransactionNum =
9850  pTransaction->GetTransactionNum(); // <=== References the
9851  // receipt in
9852  // my inbox.
9853  // lReferenceTransactionNum =
9854  // pOriginalItem->GetReferenceToNum(); // <=== References the
9855  // original
9856  // transfer I sent, or N/A (for pending), or cheque I wrote.
9857  // lReferenceTransactionNum =
9858  // pOriginalItem->GetTransactionNum(); // <=== References someone
9859  // else's transaction that put the receipt into my inbox.
9860  }
9861  break;
9862 
9863  default:
9864  otErr << __FUNCTION__ << ": Unexpected transaction type in: "
9865  << pTransaction->GetTypeString() << "\n";
9866  return "";
9867  }
9869  *pResponse, (true == BOOL_DO_I_ACCEPT)
9870  ? theAcceptItemType
9871  : theRejectItemType); // set above.
9872  pAcceptItem->SetNumberOfOrigin(lNumberOfOrigin);
9873  // Set up the "accept" transaction item to be sent to the server
9874  // (this item references and accepts another item by its transaction
9875  // number--
9876  // one that is already there in my inbox)
9877  pAcceptItem->SetReferenceToNum(static_cast<int64_t>(
9878  lReferenceTransactionNum)); // This is critical. Server needs this to
9879  // look up the original.
9880  // Don't need to set transaction num on item since the constructor already
9881  // got it off the owner transaction.
9882  pAcceptItem->SetAmount(pTransaction->GetReceiptAmount()); // Server
9883  // validates this,
9884  // so make sure
9885  // it's right.
9886  if (strNote.Exists()) pAcceptItem->SetNote(strNote);
9887  // sign the item
9888  pAcceptItem->SignContract(*pNym);
9889  pAcceptItem->SaveContract();
9890  // Make sure there's not already a response item in reference to the same
9891  // receipt.
9892  //
9893  // UPDATE, NOTE: Turns out, it's normal to have multiple receipts in
9894  // reference to the same thing.
9895  // For example, I might have two transfer receipts that are both in
9896  // reference to the same notarizeInbox.
9897  //
9898  // OTItem * pExistingItem =
9899  // pResponse->GetItemInRefTo(lReferenceTransactionNum);
9900  // if (nullptr != pExistingItem)
9901  // {
9902  // otErr << __FUNCTION__ << ": Error: There's already a response item
9903  // in
9904  // reference to the same receipt! (In Ref: " <<
9905  // static_cast<int64_t>(lReferenceTransactionNum) << " User: " << USER_ID <<
9906  // " Account: " << ACCOUNT_ID << ")
9907  // Failure.\n\n";
9908  //
9909  // const OTString strAccept(*pAcceptItem);
9910  // otErr << "===> Failed accept item:\n" << strAccept << "\n\n";
9911  //
9912  // const OTString strExisting(*pExistingItem);
9913  // otErr << "===> Pre-existing item:\n" << strExisting << "\n\n";
9914  //
9915  // return "";
9916  // }
9917  // the transaction will handle cleaning up the transaction item.
9918  pResponse->AddItem(*pAcceptItem);
9919 
9920  // I don't attach the original item here because I already reference it by
9921  // transaction num,
9922  // and because the server already has it and sent it to me. SO I just need
9923  // to give the server
9924  // enough info to look it up again.
9925 
9926  pResponse->ReleaseSignatures();
9927  pResponse->SignContract(*pNym);
9928  pResponse->SaveContract();
9929 
9930  theLedger.ReleaseSignatures();
9931  theLedger.SignContract(*pNym);
9932  theLedger.SaveContract();
9933 
9934  OTString strOutput(theLedger); // For the output
9935 
9936  std::string pBuf = strOutput.Get();
9937 
9938  return pBuf;
9939 }
9940 
9941 // (Response Ledger) LEDGER FINALIZE RESPONSE
9942 //
9943 // AFTER you have set up all the transaction responses, call THIS function
9944 // to finalize them by adding a BALANCE AGREEMENT.
9945 //
9946 // MAKE SURE you have the latest copy of the account file, inbox file, and
9947 // outbox file, since we will need those in here to create the balance statement
9948 // properly.
9949 //
9950 // (Client software may wish to check those things, when downloaded, against
9951 // the local copies and the local signed receipts. In this way, clients can
9952 // protect themselves against malicious servers.)
9953 //
9954 std::string OTAPI_Exec::Ledger_FinalizeResponse(const std::string& SERVER_ID,
9955  const std::string& USER_ID,
9956  const std::string& ACCOUNT_ID,
9957  const std::string& THE_LEDGER)
9958  const // 'Response' ledger be sent to the server...
9959 {
9960  if (SERVER_ID.empty()) {
9961  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
9962  OT_FAIL;
9963  }
9964  if (USER_ID.empty()) {
9965  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
9966  OT_FAIL;
9967  }
9968  if (ACCOUNT_ID.empty()) {
9969  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
9970  OT_FAIL;
9971  }
9972  if (THE_LEDGER.empty()) {
9973  otErr << __FUNCTION__ << ": Null: THE_LEDGER passed in!\n";
9974  OT_FAIL;
9975  }
9976 
9977  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
9978  theAcctID(ACCOUNT_ID);
9979 
9980  OTString strLedger(THE_LEDGER), strServerID(theServerID);
9981  OTServerContract* pServer = OTAPI()->GetServer(theServerID, __FUNCTION__);
9982  if (nullptr == pServer) return "";
9983  // By this point, pServer is a good pointer. (No need to cleanup.)
9984  const OTPseudonym* pServerNym = pServer->GetContractPublicNym();
9985 
9986  if (nullptr == pServerNym) {
9987  otOut << __FUNCTION__
9988  << ": No Contract Nym found in that Server Contract.\n";
9989  return "";
9990  }
9991  // By this point, pServerNym is a good pointer. (No need to cleanup.)
9992  OTPseudonym* pNym = OTAPI()->GetOrLoadPrivateNym(
9993  theUserID, false, __FUNCTION__); // This logs, ASSERTs, etc.
9994  if (nullptr == pNym) return "";
9995  // By this point, pNym is a good pointer, and is on the wallet. (No need to
9996  // cleanup.)
9997  OTLedger theLedger(theUserID, theAcctID, theServerID);
9998 
9999  if (!theLedger.LoadLedgerFromString(strLedger)) {
10000  OTString strAcctID(theAcctID);
10001  otErr << __FUNCTION__
10002  << ": Error loading ledger from string. Acct ID: " << strAcctID
10003  << "\n";
10004  return "";
10005  }
10006  else if (!theLedger.VerifyAccount(*pNym)) {
10007  OTString strAcctID(theAcctID);
10008  otErr << __FUNCTION__
10009  << ": Error verifying ledger. Acct ID: " << strAcctID << "\n";
10010  return "";
10011  }
10012 
10013  // At this point, I know theLedger loaded and verified successfully.
10014  // (This is the 'response' ledger that the user previously generated
10015  // in response to the various inbox receipts, and now he is loading
10016  // it up with responses that this function will finalize for sending.)
10017 
10018  // First, check to see if there is a processInbox transaction already on
10019  // the ledger...
10020  OTTransaction* pTransaction =
10022 
10023  // If it's not already there, create it and add it.
10024  if (nullptr == pTransaction) {
10025  OTString strAcctID(theAcctID);
10026  otErr << __FUNCTION__
10027  << ": Error finding processInbox transaction for AcctID: "
10028  << strAcctID << "\n";
10029  return "";
10030  }
10031  // At this point32_t I know pTransaction is a processInbox transaction,
10032  // ready to go,
10033  // and that theLedger will handle any cleanup issues related to it.
10034  // If balance statement is already there, return.
10035  if (nullptr != pTransaction->GetItem(OTItem::balanceStatement)) {
10036  otErr << __FUNCTION__
10037  << ": this response has already been finalized.\n";
10038  return "";
10039  }
10040  // Get the account.
10041  OTAccount* pAccount = OTAPI()->GetAccount(theAcctID, __FUNCTION__);
10042  if (nullptr == pAccount) return "";
10043  // Load the inbox and outbox.
10044 
10045  OTLedger theInbox(theUserID, theAcctID, theServerID);
10046  OTLedger theOutbox(theUserID, theAcctID, theServerID);
10047 
10048  if (!theInbox.LoadInbox() || !theInbox.VerifyAccount(*pNym)) {
10049  otOut << __FUNCTION__ << ": Unable to load or verify Inbox for acct "
10050  << ACCOUNT_ID << "\n";
10051  return "";
10052  }
10053 
10054  if (!theOutbox.LoadOutbox() || !theOutbox.VerifyAccount(*pNym)) {
10055  otOut << __FUNCTION__ << ": Unable to load or verify Outbox for acct "
10056  << ACCOUNT_ID << "\n";
10057  return "";
10058  }
10059 
10060  // Setup balance agreement item here!
10061  // Adapting code from OTServer... with comments:
10062  //
10063  // This transaction accepts various incoming pending transfers.
10064  // So when it's all done, my balance will be higher.
10065  // AND pending inbox items will be removed from my inbox.
10066  //
10067  // I would like to not even process the whole giant loop below,
10068  // if I can verify here now that the balance agreement is wrong.
10069  //
10070  // Thus I will actually loop through the acceptPending items in
10071  // pTransaction, and then for each one, I'll
10072  // lookup the ACTUAL transaction in the inbox, and get its ACTUAL value.
10073  // (And total them all up.)
10074  //
10075  // The total of those, (WITHOUT the user having to tell me what it will be,
10076  // since I'm looking them all up),
10077  // should equal the difference in the account balance! Meaning the current
10078  // balance plus that total will be
10079  // the expected NEW balance, according to this balance agreement -- if it
10080  // wants to be approved, that is.
10081  //
10082  //
10083 
10084  bool bSuccessFindingAllTransactions = true;
10085  int64_t lTotalBeingAccepted = 0;
10086 
10087  std::list<int64_t> theListOfInboxReceiptsBeingRemoved;
10088 
10089  OTPseudonym theTempNym;
10090 
10091  for (auto& it_bigloop : pTransaction->GetItemList()) {
10092  OTItem* pItem = it_bigloop;
10093  if (nullptr == pItem) {
10094  otErr << __FUNCTION__
10095  << ": Pointer: pItem should not have been \"\".\n";
10096  OT_FAIL;
10097  }
10098 
10099  if ((pItem->GetType() == OTItem::acceptPending) ||
10100  (pItem->GetType() == OTItem::acceptItemReceipt)) {
10101 
10102  // if
10103  // (theInbox.GetTransactionCountInRefTo(pItem->GetReferenceToNum())
10104  // > 1)
10105  // otErr << __FUNCTION__ << ": WARNING: There are
10106  // MULTIPLE
10107  // receipts 'in reference to' " << pItem->GetReferenceToNum() << ".
10108  // (It will return the first
10109  // one...)\n";
10110 
10111  OTTransaction* pServerTransaction =
10112  theInbox.GetTransaction(pItem->GetReferenceToNum());
10113 
10114  otWarn << __FUNCTION__
10115  << ": Checking inbox for expected pending or receipt ("
10116  << pItem->GetReferenceToNum() << ") Nym: " << USER_ID
10117  << "\n"; // temp remove
10118 
10119  if (nullptr == pServerTransaction) {
10120  bSuccessFindingAllTransactions = false;
10121  otOut << __FUNCTION__ << ": Expected receipt "
10122  << pItem->GetReferenceToNum()
10123  << " NOT found! (Do you have the latest inbox?)\n";
10124  break;
10125  }
10126  else {
10127  bSuccessFindingAllTransactions = true;
10128 
10129  // IF I'm accepting a pending transfer, then add the amount to
10130  // my counter of total amount being accepted.
10131  //
10132  // ELSE if I'm accepting an item receipt (which will remove my
10133  // responsibility for that item) then add it
10134  // to the temp Nym (which is a list of transaction numbers that
10135  // will be removed from my responsibility if
10136  // all is successful.) Also remove all the Temp Nym numbers
10137  // from pNym, so we can verify the Balance
10138  // Statement AS IF they were already removed. Add them
10139  //
10140  if (pItem->GetType() == OTItem::acceptPending) // acceptPending
10141  lTotalBeingAccepted +=
10142  pServerTransaction
10143  ->GetReceiptAmount(); // <============================
10144 
10145  else if (pItem->GetType() ==
10146  OTItem::acceptItemReceipt) // acceptItemReceipt
10147  {
10148  // What number do I remove here? the user is accepting a
10149  // transfer receipt, which
10150  // is in reference to the recipient's acceptPending. THAT
10151  // item is in reference to
10152  // my original transfer (or contains a cheque with my
10153  // original number.) (THAT's the # I need.)
10154  //
10155  OTString strOriginalItem;
10156  pServerTransaction->GetReferenceString(strOriginalItem);
10157 
10158  std::unique_ptr<OTItem> pOriginalItem(
10160  strOriginalItem, SERVER_ID.c_str(),
10161  pServerTransaction->GetReferenceToNum()));
10162 
10163  if (nullptr != pOriginalItem) {
10164  // If pOriginalItem is acceptPending, that means the
10165  // client is accepting the transfer receipt from the
10166  // server, (from his inbox),
10167  // which has the recipient's acceptance inside of the
10168  // client's transfer as the original item. This means
10169  // the transfer that
10170  // the client originally sent is now finally closed!
10171  //
10172  // If it's a depositCheque, that means the client is
10173  // accepting the cheque receipt from the server,
10174  // (from his inbox)
10175  // which has the recipient's deposit inside of it as the
10176  // original item. This means that the cheque that
10177  // the client originally wrote is now finally closed!
10178  //
10179  // In both cases, the "original item" itself is not from
10180  // the client, but from the recipient! Therefore,
10181  // the number on that item is useless for removing
10182  // numbers from the client's list of issued numbers.
10183  // Rather, I need to load that original cheque, or
10184  // pending transfer, from WITHIN the original item,
10185  // in order to get THAT number, to remove it from the
10186  // client's issued list. (Whether for real, or for
10187  // setting up dummy data in order to verify the balance
10188  // agreement.) *sigh*
10189  //
10190  if (OTItem::depositCheque ==
10191  pOriginalItem->GetType()) // client is accepting a
10192  // cheque receipt, which
10193  // has a depositCheque
10194  // (from the recipient) as
10195  // the original item
10196  // within.
10197  {
10198  // Get the cheque from the Item and load it up into
10199  // a Cheque object.
10200  OTString strCheque;
10201  pOriginalItem->GetAttachment(strCheque);
10202 
10203  OTCheque theCheque; // allocated on the stack :-)
10204 
10205  if (false ==
10206  ((strCheque.GetLength() > 2) &&
10207  theCheque.LoadContractFromString(strCheque))) {
10208  otErr << __FUNCTION__
10209  << ": ERROR loading cheque from string:\n"
10210  << strCheque << "\n";
10211  }
10212  else // Since the client wrote the cheque, and he
10213  // is now accepting the cheque receipt, he
10214  // can be cleared for that transaction
10215  // number...
10216  {
10217  if (pNym->VerifyIssuedNum(
10218  strServerID,
10219  theCheque.GetTransactionNum()))
10220  theTempNym.AddIssuedNum(
10221  strServerID,
10222  theCheque.GetTransactionNum());
10223  else
10224  otErr << __FUNCTION__
10225  << ": cheque receipt, trying to "
10226  "'remove' an issued number ("
10227  << theCheque.GetTransactionNum()
10228  << ") that already wasn't on my "
10229  "issued list. (So what is this in "
10230  "my inbox, then? Maybe need to "
10231  "download a fresh copy of it.)\n";
10232  }
10233  }
10234  // client is accepting a transfer receipt, which has an
10235  // acceptPending from the recipient
10236  // as the original item within.
10237  //
10238  else if (OTItem::acceptPending ==
10239  pOriginalItem->GetType()) // (which is in
10240  // reference to the
10241  // client's outgoing
10242  // original
10243  // transfer.)
10244  {
10245  if (pNym->VerifyIssuedNum(
10246  strServerID,
10247  pOriginalItem->GetNumberOfOrigin()))
10248  theTempNym.AddIssuedNum(
10249  strServerID,
10250  pOriginalItem->GetNumberOfOrigin());
10251  else
10252  otErr << __FUNCTION__
10253  << ": transferReceipt, trying to "
10254  "'remove' an issued number ("
10255  << pOriginalItem->GetNumberOfOrigin()
10256  << ") that already wasn't on my issued "
10257  "list. (So what is this in my inbox, "
10258  "then? Maybe need to download a fresh "
10259  "copy of it.)\n";
10260  }
10261  else // wrong type.
10262  {
10263  OTString strOriginalItemType;
10264  pOriginalItem->GetTypeString(strOriginalItemType);
10265  otErr << __FUNCTION__
10266  << ": Original item has wrong type, while "
10267  "accepting item receipt:\n"
10268  << strOriginalItemType << "\n";
10269  }
10270  }
10271  else {
10272  otErr << __FUNCTION__
10273  << ": Unable to load original item from string "
10274  "while accepting item receipt:\n"
10275  << strOriginalItem << "\n";
10276  }
10277  } // acceptItemReceipt
10278 
10279  // I'll also go ahead and remove each transaction from theInbox,
10280  // and pass said inbox into the VerifyBalanceAgreement call...
10281  // (So it can simulate as if the inbox was already changed, and
10282  // the total is already calculated, and if it succeeds,
10283  // then we can allow the giant loop below to do it all for
10284  // real.)
10285  // (I'm not saving this copy of the inbox anyway--there's
10286  // another one below.)
10287  //
10288  // theInbox.RemoveTransaction(pServerTransaction->GetTransactionNum());
10289  // // <================
10290  // Now this is done AFTER this loop...
10291  //
10292  theListOfInboxReceiptsBeingRemoved.push_back(
10293  pServerTransaction->GetTransactionNum());
10294 
10295  } // pServerTransaction != ""
10296  } // if pItem type is accept pending or item receipt.
10297  else if ((pItem->GetType() == OTItem::acceptCronReceipt) ||
10298  (pItem->GetType() == OTItem::acceptFinalReceipt) ||
10299  (pItem->GetType() == OTItem::acceptBasketReceipt)) {
10300  OTTransaction* pServerTransaction =
10301  theInbox.GetTransaction(pItem->GetReferenceToNum());
10302 
10303  otInfo << __FUNCTION__
10304  << ": Checking client-side inbox for expected cron or final "
10305  "or basket receipt: " << pItem->GetReferenceToNum()
10306  << "... "; // temp remove
10307 
10308  if (nullptr == pServerTransaction) {
10309  bSuccessFindingAllTransactions = false;
10310  otInfo << __FUNCTION__ << ": NOT found!(Do you have the latest "
10311  "inbox ? )\n"; // temp remove
10312  break;
10313  }
10314  else {
10315  bSuccessFindingAllTransactions = true;
10316 
10317  switch (pItem->GetType()) {
10318 
10320  // pServerTransaction is a marketReceipt or paymentReceipt
10321  //
10322 
10323  // When accepting a cron receipt from the inbox, you don't
10324  // have to clear the issued transaction number.
10325  // In this case, the original trans# is cleared when the
10326  // finalReceipt is generated,
10327  // and the closing trans# is cleared when the finalReceipt
10328  // is cleared.
10329 
10330  // So NO issued numbers being removed or added in this case.
10331  // (But we still remove the receipt from our copy of the
10332  // inbox, below,
10333  // so that the balance agreement will reflect as if it had
10334  // already been
10335  // successfully removed. (Because balance agreement is meant
10336  // to show the new
10337  // state of things, in the event of success--a signed record
10338  // of those things.)
10339  break;
10340 
10342  // pServerTransaction is a finalReceipt
10343 
10344  // IN THIS CASE: If we're accepting a finalReceipt, that
10345  // means all the OTHER receipts related to it
10346  // (sharing the same "in reference to") must ALSO be cleared
10347  // from the inbox aint64_t with it! That's the
10348  // whole point32_t of the finalReceipt -- to make sure all
10349  // related receipts are cleared, when IT is.
10350  //
10351  // The server WILL verify this also (I tested it)... That's
10352  // why we check here, to save the trouble
10353  // of being rejected by the server.
10354  //
10355  // So let's see if the number of related receipts on this
10356  // process inbox (pTransaction) matches
10357  // the number of related receipts in the actual inbox
10358  // (theInbox), as found by the finalReceipt's
10359  // (pServerTransaction) "in reference to" value, which
10360  // should be the same as on the related receipts.
10361 
10362  // (Below) pTransaction is the processInbox transaction.
10363  // Each item on it is in ref to a DIFFERENT receipt,
10364  // even though, if they are marketReceipts, all of THOSE
10365  // receipts are in ref to the original transaction#.
10366  {
10367  // int32_t nRefCount = 0;
10368  std::set<int64_t> setOfRefNumbers; // we'll store them
10369  // here, to disallow
10370  // duplicates, to
10371  // make sure they are
10372  // all unique IDs
10373 
10374  //
10375  // I need to loop through all items on pTransaction (my
10376  // processInbox request)
10377  // For each, look it up on the inbox. (Each item may be
10378  // "in reference to"
10379  // one original transaction or another.) FIND THE ONES
10380  // that are in reference to
10381  // the same # as pServerTransaction is.
10382  //
10383  for (auto& it : pTransaction->GetItemList()) {
10384  OTItem* pItemPointer = it;
10385  if (nullptr == pItemPointer) {
10386  otErr << __FUNCTION__ << ": Pointer: "
10387  "pItemPointer should "
10388  "not have been .\n";
10389  OT_FAIL;
10390  }
10391 
10392  // pItemPointer->GetReferenceToNum() is the server's
10393  // transaction number for the receipt
10394  // that it dropped into my inbox. pTransPointer is
10395  // the receipt itself (hopefully.)
10396  OTTransaction* pTransPointer =
10397  theInbox.GetTransaction(
10398  pItemPointer->GetReferenceToNum());
10399 
10400  // Careful on the logic here...
10401  // ONCE EACH INBOX RECEIPT IS DEFINITELY NOT-"", and
10402  // if *IT* is "in reference to"
10403  // pServerTransaction->GetReferenceToNum(),
10404  // Then increment the count for the transaction.
10405  // COMPARE *THAT* to theInbox.GetCount and we're
10406  // golden!!
10407  // Perhaps the finalReceipt is in reference to #10,
10408  // and there are 6 others that are ALSO in reference
10409  // to #10.
10410  // That's a total of 7 receipts in the inbox that
10411  // are in reference to #10, so my request had better
10412  // have the
10413  // same count :-)
10414  //
10415  if ((nullptr != pTransPointer) &&
10416  (pTransPointer->GetReferenceToNum() ==
10417  pServerTransaction->GetReferenceToNum())) {
10418  // nRefCount++;
10419  // std::set doesn't allow duplicates.
10420  setOfRefNumbers.insert(
10421  pItemPointer->GetReferenceToNum());
10422  }
10423  }
10424 
10425  //
10426  if (static_cast<int32_t>(
10427  setOfRefNumbers.size()) != // IS NOT EQUAL TO...
10428  theInbox.GetTransactionCountInRefTo(
10429  pServerTransaction->GetReferenceToNum()))
10430  /* todo: Notice I'm not making sure the count is
10431  entirely composed of ACCEPTED receipts. (vs
10432  DISPUTED...)
10433  I probably should add code to GetItemCountInRefTo()
10434  so it only counts ACCEPTED receipts.*/
10435  {
10436  otOut
10437  << __FUNCTION__
10438  << ": When accepting a finalReceipt, you MUST "
10439  "accept all related receipts (ones that "
10440  "share the same IN REFERENCE TO transaction "
10441  "number as the finalReceipt "
10442  << pServerTransaction->GetReferenceToNum()
10443  << ")\n"
10444  "Transaction item count (in ref to): "
10445  << setOfRefNumbers.size()
10446  << " Inbox transaction count (in ref to): "
10447  << theInbox.GetTransactionCountInRefTo(
10448  pServerTransaction->GetReferenceToNum())
10449  << ".\n";
10450 
10451  bSuccessFindingAllTransactions = false;
10452  break;
10453  }
10454  // Else NO BREAK;
10455  // break; FALLING THROUGH TO BELOW, to do the
10456  // pNym/theTempNym stuff in the BASKET section...
10457 
10458  // pServerTransaction->GetReferenceToNum() is the
10459  // OPENING number and should already be closed.
10460  //
10461  // IN fact, since the "in reference to" is supposedly
10462  // already closed, then let's just
10463  // MAKE SURE of that, since otherwise it'll screw up my
10464  // future balance agreements. (The
10465  // instant a finalReceipt appears, the "in ref to" is
10466  // already gone on the server's side.)
10467  //
10469  pServerTransaction->GetType()) {
10470  if (pNym->RemoveIssuedNum(
10471  *pNym, strServerID,
10472  pServerTransaction->GetReferenceToNum(),
10473  true)) // bool bSave=true
10474  otWarn
10475  << __FUNCTION__
10476  << ": **** Due to finding a finalReceipt, "
10477  "REMOVING OPENING NUMBER FROM NYM: "
10478  << pServerTransaction->GetReferenceToNum()
10479  << " \n";
10480  else
10481  otWarn
10482  << __FUNCTION__
10483  << ": **** Noticed a finalReceipt, but "
10484  "Opening Number "
10485  << pServerTransaction->GetReferenceToNum()
10486  << " had ALREADY been removed from nym. \n";
10487  }
10488  else
10489  otErr << __FUNCTION__
10490  << ": Expected pServerTransaction to be a "
10491  "final receipt (while finalizing for "
10492  "process inbox.)\n";
10493  //
10494  // pNym won't actually save unless it actually removes
10495  // that #. If the #'s already NOT THERE,
10496  // then the removal will fail, and thus it won't bother
10497  // saving here.
10498  }
10499 
10500  // ... (FALL THROUGH) ...
10501 
10503  // pServerTransaction is a basketReceipt (or finalReceipt,
10504  // since falling through from above.)
10505  //
10506  // Remove the proper issued number, based on the CLOSING
10507  // TRANSACTION NUMBER
10508  // of the finalReceipt/basketReceipt I'm accepting...
10509  //
10510 
10511  if (pNym->VerifyIssuedNum(
10512  strServerID, pServerTransaction->GetClosingNum()))
10513  theTempNym.AddIssuedNum(
10514  strServerID, pServerTransaction->GetClosingNum());
10515  else
10516  otErr << __FUNCTION__
10517  << ": final or basket Receipt, trying to "
10518  "'remove' an issued number ("
10519  << pServerTransaction->GetClosingNum()
10520  << ") that already wasn't on my issued list. (So "
10521  "what is this in my inbox, then? Maybe need "
10522  "to download a fresh copy of it.)\n";
10523  break;
10524 
10525  default: {
10526  OTString strTempType;
10527  pItem->GetTypeString(strTempType);
10528  otErr << __FUNCTION__
10529  << ": Unexpected item type: " << strTempType << "\n";
10530  break;
10531  }
10532  }
10533 
10534  // I'll also go ahead and remove each transaction from theInbox,
10535  // and pass said inbox into the VerifyBalanceAgreement call...
10536  // (So it can simulate as if the inbox was already changed, and
10537  // the total is already calculated, and if it succeeds,
10538  // then we can allow the giant loop below to do it all for
10539  // real.)
10540  // (I'm not saving this copy of the inbox anyway--there's
10541  // another one below.)
10542  //
10543  // theInbox.RemoveTransaction(pItem->GetReferenceToNum());
10544  // Let's remove it this way instead:
10545  //
10546  // theInbox.RemoveTransaction(pServerTransaction->GetTransactionNum());
10547  // // <================
10548  //
10549  // Actually, let's remove it this way:
10550  theListOfInboxReceiptsBeingRemoved.push_back(
10551  pServerTransaction->GetTransactionNum());
10552 
10553  } // else if pServerTransaction NOT "".
10554  } // If acceptCronReceipt/acceptFinalReceipt/acceptBasketReceipt
10555  }
10556  if (!bSuccessFindingAllTransactions) // failure.
10557  {
10558  otOut << __FUNCTION__ << ": transactions in processInbox message do "
10559  "not match actual inbox.\n";
10560 
10561  return ""; // RETURN.
10562  }
10563  // SUCCESS finding all transactions
10564 
10565  while (!theListOfInboxReceiptsBeingRemoved.empty()) {
10566  int64_t lTemp = theListOfInboxReceiptsBeingRemoved.front();
10567  theListOfInboxReceiptsBeingRemoved.pop_front();
10568 
10569  if (false ==
10570  theInbox.RemoveTransaction(
10571  static_cast<int64_t>(lTemp))) // <================
10572  otErr << __FUNCTION__
10573  << ": Failed removing receipt from temporary Inbox: " << lTemp
10574  << " \n";
10575  }
10576 
10577  // SET UP NYM FOR BALANCE AGREEMENT.
10578 
10579  // By this point, theTempNym contains a list of all the transaction numbers
10580  // that are issued to me,
10581  // but that will NOT be issued to me anymore once this processInbox is
10582  // processed.
10583  // Therefore I need to REMOVE those items from my issued list (at least
10584  // temporarily) in order to
10585  // calculate the balance agreement properly. So I used theTempNym as a temp
10586  // variable to store those
10587  // numbers, so I can remove them from my Nym and them add them again after
10588  // generating the statement.
10589  //
10590  for (int32_t i = 0; i < theTempNym.GetIssuedNumCount(theServerID); i++) {
10591  int64_t lTemp = theTempNym.GetIssuedNum(theServerID, i);
10592  pNym->RemoveIssuedNum(strServerID, static_cast<int64_t>(lTemp));
10593  }
10594  // BALANCE AGREEMENT
10595  //
10596  // The item is signed and saved within this call as well. No need to do that
10597  // again.
10598  //
10599  OTItem* pBalanceItem = theInbox.GenerateBalanceStatement(
10600  static_cast<int64_t>(lTotalBeingAccepted), *pTransaction, *pNym,
10601  *pAccount, theOutbox);
10602  // Here I am adding these numbers back again, since I removed them to
10603  // generate the balance agreement.
10604  // (They won't be removed for real until I receive the server's
10605  // acknowledgment that those numbers
10606  // really were removed. theTempNym then I have to keep them and use them for
10607  // my balance agreements.)
10608  //
10609  for (int32_t i = 0; i < theTempNym.GetIssuedNumCount(theServerID); i++) {
10610  int64_t lTemp = theTempNym.GetIssuedNum(theServerID, i);
10611  pNym->AddIssuedNum(strServerID, static_cast<int64_t>(lTemp));
10612  }
10613 
10614  if (nullptr == pBalanceItem) {
10615  otOut << __FUNCTION__ << ": ERROR generating balance statement.\n";
10616 
10617  return "";
10618  }
10619 
10620  // the transaction will handle cleaning up the transaction item.
10621  pTransaction->AddItem(*pBalanceItem);
10622  // sign the item
10623  // This already happens in the GenerateBalanceStatement() call above.
10624  // I would actually have to RELEASE the signatures if I wanted to sign
10625  // again!
10626  // (Unless I WANT two signatures...)
10627  //
10628  // pBalanceItem->SignContract(*pNym);
10629  // pBalanceItem->SaveContract();
10630 
10631  pTransaction->ReleaseSignatures();
10632  pTransaction->SignContract(*pNym);
10633  pTransaction->SaveContract();
10634 
10635  theLedger.ReleaseSignatures();
10636  theLedger.SignContract(*pNym);
10637  theLedger.SaveContract();
10638 
10639  OTString strOutput(theLedger); // For the output
10640 
10641  std::string pBuf = strOutput.Get();
10642 
10643  return pBuf;
10644 }
10645 
10646 // Retrieve Voucher from Transaction
10647 //
10648 // If you withdrew into a voucher instead of cash, this function allows
10649 // you to retrieve the actual voucher cheque from the reply transaction.
10650 // (A voucher is a cheque drawn on an internal server account instead
10651 // of a user's asset account, so the voucher cannot ever bounce due to
10652 // insufficient funds. We are accustomed to this functionality already
10653 // in our daily lives, via "money orders" and "cashier's cheques".)
10654 //
10655 // How would you use this in full?
10656 //
10657 // First, call OTAPI_Exec::withdrawVoucher() in order to send the request
10658 // to the server. (You may optionally call OTAPI_Exec::FlushMessageBuffer()
10659 // before doing this.)
10660 //
10661 // Then, call OTAPI_Exec::PopMessageBuffer() to retrieve any server reply.
10662 //
10663 // If there is a message from the server in reply, then call
10664 // OTAPI_Exec::Message_GetCommand to verify that it's a reply to the message
10665 // that you sent, and call OTAPI_Exec::Message_GetSuccess to verify whether
10666 // the message was a success.
10667 //
10668 // If it was a success, next call OTAPI_Exec::Message_GetLedger to retrieve
10669 // the actual "reply ledger" from the server.
10670 //
10671 // Penultimately, call OTAPI_Exec::Ledger_GetTransactionByID() and then,
10672 // finally, call OTAPI_Exec::Transaction_GetVoucher() (below) in order to
10673 // retrieve the voucher cheque itself from the transaction.
10674 //
10676  const std::string& SERVER_ID, const std::string& USER_ID,
10677  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
10678 {
10679  if (SERVER_ID.empty()) {
10680  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
10681  OT_FAIL;
10682  }
10683  if (USER_ID.empty()) {
10684  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
10685  OT_FAIL;
10686  }
10687  if (ACCOUNT_ID.empty()) {
10688  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
10689  OT_FAIL;
10690  }
10691  if (THE_TRANSACTION.empty()) {
10692  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
10693  OT_FAIL;
10694  }
10695 
10696  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
10697  theAccountID(ACCOUNT_ID);
10698 
10699  OTString strTransaction(THE_TRANSACTION);
10700 
10701  OTString strOutput;
10702 
10704  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
10705  if (nullptr == pNym) return "";
10706 
10707  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
10708 
10709  if (!theTransaction.LoadContractFromString(strTransaction)) {
10710  OTString strAcctID(theAccountID);
10711  otErr << __FUNCTION__
10712  << ": Error loading transaction from string. Acct ID: "
10713  << strAcctID << "\n";
10714  return "";
10715  }
10716  // No need to check if transaction is abbreviated, since it's coming from a
10717  // message ledger.
10718  // (Those always contain the full version of the transactions,
10719  // automatically.)
10720 
10721  if (OTTransaction::atWithdrawal != theTransaction.GetType()) {
10722  otErr << __FUNCTION__ << ": Error: tried to retrieve voucher from "
10723  "wrong transaction (not atWithdrawal).\n";
10724  return "";
10725  }
10726 
10727  // loop through the ALL items that make up this transaction and check to see
10728  // if a response to withdrawal.
10729 
10730  // if pointer not null, and it's a withdrawal, and it's an acknowledgement
10731  // (not a rejection or error)
10732  for (auto& it : theTransaction.GetItemList()) {
10733  OTItem* pItem = it;
10734  if (nullptr == pItem) {
10735  otErr << __FUNCTION__ << ": Pointer: "
10736  << "pItem"
10737  << " should not have been .\n";
10738  OT_FAIL;
10739  }
10740 
10741  if ((OTItem::atWithdrawVoucher == pItem->GetType()) &&
10742  (OTItem::acknowledgement == pItem->GetStatus())) {
10743  OTString strVoucher;
10744  pItem->GetAttachment(strVoucher);
10745 
10746  OTCheque theVoucher;
10747  if (theVoucher.LoadContractFromString(strVoucher)) // Todo
10748  // additional
10749  // verification
10750  // here on the
10751  // cheque.
10752  {
10753  theVoucher.SaveContractRaw(strOutput);
10754  break;
10755  }
10756  }
10757  }
10758 
10759  // Didn't find one.
10760  if (!strOutput.Exists()) return "";
10761 
10762  // We found a voucher -- let's return it!
10763  //
10764  std::string pBuf = strOutput.Get();
10765 
10766  return pBuf;
10767 }
10768 
10770  const std::string& SERVER_ID, const std::string& USER_ID,
10771  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
10772 {
10773  if (SERVER_ID.empty()) {
10774  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
10775  OT_FAIL;
10776  }
10777  if (USER_ID.empty()) {
10778  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
10779  OT_FAIL;
10780  }
10781  if (ACCOUNT_ID.empty()) {
10782  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
10783  OT_FAIL;
10784  }
10785  if (THE_TRANSACTION.empty()) {
10786  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
10787  OT_FAIL;
10788  }
10789 
10790  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
10791  theAccountID(ACCOUNT_ID);
10792 
10793  OTString strTransaction(THE_TRANSACTION);
10794 
10796  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
10797  if (nullptr == pNym) return "";
10798 
10799  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
10800 
10801  if (!theTransaction.LoadContractFromString(strTransaction)) {
10802  OTString strAcctID(theAccountID);
10803  otErr << __FUNCTION__
10804  << ": Error loading transaction from string. Acct ID: "
10805  << strAcctID << "\n";
10806  return "";
10807  }
10808  OTTransaction* pTransaction = nullptr;
10809  std::unique_ptr<OTTransaction> theTransAngel;
10810 
10811  if (theTransaction.IsAbbreviated()) {
10812  int64_t lBoxType = 0;
10813 
10814  if (theTransaction.Contains("nymboxRecord"))
10815  lBoxType = static_cast<int64_t>(OTLedger::nymbox);
10816  else if (theTransaction.Contains("inboxRecord"))
10817  lBoxType = static_cast<int64_t>(OTLedger::inbox);
10818  else if (theTransaction.Contains("outboxRecord"))
10819  lBoxType = static_cast<int64_t>(OTLedger::outbox);
10820  else if (theTransaction.Contains("paymentInboxRecord"))
10821  lBoxType = static_cast<int64_t>(OTLedger::paymentInbox);
10822  else if (theTransaction.Contains("recordBoxRecord"))
10823  lBoxType = static_cast<int64_t>(OTLedger::recordBox);
10824  else if (theTransaction.Contains("expiredBoxRecord"))
10825  lBoxType = static_cast<int64_t>(OTLedger::expiredBox);
10826  else {
10827  otErr << __FUNCTION__ << ": Error loading from abbreviated "
10828  "transaction: unknown ledger type.\n";
10829  return "";
10830  }
10831  pTransaction =
10832  LoadBoxReceipt(theTransaction, static_cast<int64_t>(lBoxType));
10833  if (nullptr == pTransaction) {
10834  otErr << __FUNCTION__ << ": Error loading from abbreviated "
10835  "transaction: failed loading box "
10836  "receipt.\n";
10837  return "";
10838  }
10839  theTransAngel.reset(pTransaction);
10840  }
10841  else
10842  pTransaction = &theTransaction;
10843  OTIdentifier theOutput;
10844 
10845  bool bSuccess = pTransaction->GetSenderUserIDForDisplay(theOutput);
10846 
10847  if (bSuccess) {
10848  OTString strOutput(theOutput);
10849 
10850  // Didn't find one.
10851  if (!strOutput.Exists()) return "";
10852 
10853  // We found it -- let's return the user ID
10854  //
10855  std::string pBuf = strOutput.Get();
10856 
10857  return pBuf;
10858  }
10859  else
10860  return "";
10861 }
10862 
10864  const std::string& SERVER_ID, const std::string& USER_ID,
10865  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
10866 {
10867  if (SERVER_ID.empty()) {
10868  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
10869  OT_FAIL;
10870  }
10871  if (USER_ID.empty()) {
10872  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
10873  OT_FAIL;
10874  }
10875  if (ACCOUNT_ID.empty()) {
10876  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
10877  OT_FAIL;
10878  }
10879  if (THE_TRANSACTION.empty()) {
10880  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
10881  OT_FAIL;
10882  }
10883 
10884  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
10885  theAccountID(ACCOUNT_ID);
10886 
10887  OTString strTransaction(THE_TRANSACTION);
10888 
10890  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
10891  if (nullptr == pNym) return "";
10892  // By this point, pNym is a good pointer, and is on the wallet. (No need to
10893  // cleanup.)
10894  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
10895 
10896  if (!theTransaction.LoadContractFromString(strTransaction)) {
10897  OTString strAcctID(theAccountID);
10898  otErr << __FUNCTION__
10899  << ": Error loading transaction from string. Acct ID: "
10900  << strAcctID << "\n";
10901  return "";
10902  }
10903  OTTransaction* pTransaction = nullptr;
10904  std::unique_ptr<OTTransaction> theTransAngel;
10905 
10906  if (theTransaction.IsAbbreviated()) {
10907  int64_t lBoxType = 0;
10908 
10909  if (theTransaction.Contains("nymboxRecord"))
10910  lBoxType = static_cast<int64_t>(OTLedger::nymbox);
10911  else if (theTransaction.Contains("inboxRecord"))
10912  lBoxType = static_cast<int64_t>(OTLedger::inbox);
10913  else if (theTransaction.Contains("outboxRecord"))
10914  lBoxType = static_cast<int64_t>(OTLedger::outbox);
10915  else if (theTransaction.Contains("paymentInboxRecord"))
10916  lBoxType = static_cast<int64_t>(OTLedger::paymentInbox);
10917  else if (theTransaction.Contains("recordBoxRecord"))
10918  lBoxType = static_cast<int64_t>(OTLedger::recordBox);
10919  else if (theTransaction.Contains("expiredBoxRecord"))
10920  lBoxType = static_cast<int64_t>(OTLedger::expiredBox);
10921  else {
10922  otErr << __FUNCTION__ << ": Error loading from abbreviated "
10923  "transaction: unknown ledger type. \n";
10924  return "";
10925  }
10926  pTransaction =
10927  LoadBoxReceipt(theTransaction, static_cast<int64_t>(lBoxType));
10928  if (nullptr == pTransaction) {
10929  otErr << __FUNCTION__ << ": Error loading from abbreviated "
10930  "transaction: failed loading box receipt.";
10931  return "";
10932  }
10933  theTransAngel.reset(pTransaction);
10934  }
10935  else
10936  pTransaction = &theTransaction;
10937 
10938  OTIdentifier theOutput;
10939 
10940  bool bSuccess = pTransaction->GetRecipientUserIDForDisplay(theOutput);
10941 
10942  // Normally, there IS NO recipient user ID for a transfer (only a recipient
10943  // acct ID.)
10944  // But here, as a special trick, I'll see if the account is in my address
10945  // book.
10946  // THIS MEANS THE ADDRESS BOOK needs to store nyms (for other people, their
10947  // public nym)
10948  // as well as a list of acct IDs that I have associated with each Nym. That
10949  // way, I can
10950  // later look up the Nym ID based on the acct ID, and then look up my
10951  // display label for
10952  // that Nym.
10953  //
10954  // if (!bSuccess && (theTransaction.GetType() == OTTransaction::pending))
10955  // {
10956  // // AS SOON AS ADDRESS BOOK FEATURE IS ADDED, THEN THIS CAN BE
10957  // COMPLETED HERE.
10958  // }
10959 
10960  if (bSuccess) {
10961  OTString strOutput(theOutput);
10962 
10963  // Didn't find one.
10964  if (!strOutput.Exists()) return "";
10965 
10966  // We found it -- let's return the user ID
10967  //
10968  std::string pBuf = strOutput.Get();
10969 
10970  return pBuf;
10971  }
10972  else
10973  return "";
10974 }
10975 
10977  const std::string& SERVER_ID, const std::string& USER_ID,
10978  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
10979 {
10980  if (SERVER_ID.empty()) {
10981  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
10982  OT_FAIL;
10983  }
10984  if (USER_ID.empty()) {
10985  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
10986  OT_FAIL;
10987  }
10988  if (ACCOUNT_ID.empty()) {
10989  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
10990  OT_FAIL;
10991  }
10992  if (THE_TRANSACTION.empty()) {
10993  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
10994  OT_FAIL;
10995  }
10996 
10997  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
10998  theAccountID(ACCOUNT_ID);
10999 
11000  OTString strTransaction(THE_TRANSACTION);
11001 
11003  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11004  if (nullptr == pNym) return "";
11005 
11006  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11007 
11008  if (!theTransaction.LoadContractFromString(strTransaction)) {
11009  OTString strAcctID(theAccountID);
11010  otErr << __FUNCTION__
11011  << ": Error loading transaction from string. Acct ID: "
11012  << strAcctID << "\n";
11013  return "";
11014  }
11015  OTTransaction* pTransaction = nullptr;
11016  std::unique_ptr<OTTransaction> theTransAngel;
11017 
11018  if (theTransaction.IsAbbreviated()) {
11019  int64_t lBoxType = 0;
11020 
11021  if (theTransaction.Contains("nymboxRecord"))
11022  lBoxType = static_cast<int64_t>(OTLedger::nymbox);
11023  else if (theTransaction.Contains("inboxRecord"))
11024  lBoxType = static_cast<int64_t>(OTLedger::inbox);
11025  else if (theTransaction.Contains("outboxRecord"))
11026  lBoxType = static_cast<int64_t>(OTLedger::outbox);
11027  else if (theTransaction.Contains("paymentInboxRecord"))
11028  lBoxType = static_cast<int64_t>(OTLedger::paymentInbox);
11029  else if (theTransaction.Contains("recordBoxRecord"))
11030  lBoxType = static_cast<int64_t>(OTLedger::recordBox);
11031  else if (theTransaction.Contains("expiredBoxRecord"))
11032  lBoxType = static_cast<int64_t>(OTLedger::expiredBox);
11033  else {
11034  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11035  "transaction: unknown ledger type.\n";
11036  return "";
11037  }
11038  pTransaction =
11039  LoadBoxReceipt(theTransaction, static_cast<int64_t>(lBoxType));
11040  if (nullptr == pTransaction) {
11041  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11042  "transaction: failed loading box receipt. "
11043  "\n";
11044  return "";
11045  }
11046  theTransAngel.reset(pTransaction);
11047  }
11048  else
11049  pTransaction = &theTransaction;
11050 
11051  OTIdentifier theOutput;
11052 
11053  bool bSuccess = pTransaction->GetSenderAcctIDForDisplay(theOutput);
11054 
11055  if (bSuccess) {
11056  OTString strOutput(theOutput);
11057 
11058  // Didn't find one.
11059  if (!strOutput.Exists()) return "";
11060 
11061  // We found it -- let's return the user ID
11062  //
11063  std::string pBuf = strOutput.Get();
11064 
11065  return pBuf;
11066  }
11067  else
11068  return "";
11069 }
11070 
11072  const std::string& SERVER_ID, const std::string& USER_ID,
11073  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
11074 {
11075  if (SERVER_ID.empty()) {
11076  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11077  OT_FAIL;
11078  }
11079  if (USER_ID.empty()) {
11080  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11081  OT_FAIL;
11082  }
11083  if (ACCOUNT_ID.empty()) {
11084  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11085  OT_FAIL;
11086  }
11087  if (THE_TRANSACTION.empty()) {
11088  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11089  OT_FAIL;
11090  }
11091 
11092  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11093  theAccountID(ACCOUNT_ID);
11094 
11095  OTString strTransaction(THE_TRANSACTION);
11096 
11098  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11099  if (nullptr == pNym) return "";
11100 
11101  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11102 
11103  if (!theTransaction.LoadContractFromString(strTransaction)) {
11104  OTString strAcctID(theAccountID);
11105  otErr << __FUNCTION__ << ": Error loading transaction from string in "
11106  "OTAPI_Exec::Transaction_GetRecipientAcctID. "
11107  "Acct ID: " << strAcctID << "\n";
11108  return "";
11109  }
11110 
11111  OTTransaction* pTransaction = nullptr;
11112  std::unique_ptr<OTTransaction> theTransAngel;
11113 
11114  if (theTransaction.IsAbbreviated()) {
11115  int64_t lBoxType = 0;
11116 
11117  if (theTransaction.Contains("nymboxRecord"))
11118  lBoxType = static_cast<int64_t>(OTLedger::nymbox);
11119  else if (theTransaction.Contains("inboxRecord"))
11120  lBoxType = static_cast<int64_t>(OTLedger::inbox);
11121  else if (theTransaction.Contains("outboxRecord"))
11122  lBoxType = static_cast<int64_t>(OTLedger::outbox);
11123  else if (theTransaction.Contains("paymentInboxRecord"))
11124  lBoxType = static_cast<int64_t>(OTLedger::paymentInbox);
11125  else if (theTransaction.Contains("recordBoxRecord"))
11126  lBoxType = static_cast<int64_t>(OTLedger::recordBox);
11127  else if (theTransaction.Contains("expiredBoxRecord"))
11128  lBoxType = static_cast<int64_t>(OTLedger::expiredBox);
11129  else {
11130  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11131  "transaction: unknown ledger type. \n";
11132  return "";
11133  }
11134  pTransaction =
11135  LoadBoxReceipt(theTransaction, static_cast<int64_t>(lBoxType));
11136  if (nullptr == pTransaction) {
11137  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11138  "transaction: failed loading box "
11139  "receipt.\n";
11140  return "";
11141  }
11142  theTransAngel.reset(pTransaction);
11143  }
11144  else
11145  pTransaction = &theTransaction;
11146  OTIdentifier theOutput;
11147 
11148  bool bSuccess = pTransaction->GetRecipientAcctIDForDisplay(theOutput);
11149 
11150  if (bSuccess) {
11151  OTString strOutput(theOutput);
11152 
11153  // Didn't find one.
11154  if (!strOutput.Exists()) return "";
11155 
11156  // We found it -- let's return the user ID
11157  //
11158  std::string pBuf = strOutput.Get();
11159 
11160  return pBuf;
11161  }
11162  else
11163  return "";
11164 }
11165 
11166 //
11167 // PENDING TRANSFER (various functions)
11168 //
11169 // When someone has sent you a PENDING TRANSFER (a form of transaction
11170 // that will be sitting in your inbox waiting for you to accept/reject it)
11171 // then, as you are reading the inbox, you can use these functions in
11172 // order to get data from the pending transfer.
11173 //
11174 
11176  const std::string& SERVER_ID, const std::string& USER_ID,
11177  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
11178 {
11179  if (SERVER_ID.empty()) {
11180  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11181  OT_FAIL;
11182  }
11183  if (USER_ID.empty()) {
11184  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11185  OT_FAIL;
11186  }
11187  if (ACCOUNT_ID.empty()) {
11188  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11189  OT_FAIL;
11190  }
11191  if (THE_TRANSACTION.empty()) {
11192  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11193  OT_FAIL;
11194  }
11195 
11196  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11197  theAccountID(ACCOUNT_ID);
11198 
11199  OTString strTransaction(THE_TRANSACTION);
11201  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11202  if (nullptr == pNym) return "";
11203  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11204 
11205  if (!theTransaction.LoadContractFromString(strTransaction)) {
11206  OTString strAcctID(theAccountID);
11207  otErr << __FUNCTION__
11208  << ": Error loading transaction from string. Acct ID: "
11209  << strAcctID << "\n";
11210  return "";
11211  }
11212  OTTransaction* pTransaction = nullptr;
11213  std::unique_ptr<OTTransaction> theTransAngel;
11214 
11215  if (theTransaction.IsAbbreviated()) {
11216  int64_t lBoxType = 0;
11217 
11218  if (theTransaction.Contains("nymboxRecord"))
11219  lBoxType = static_cast<int64_t>(OTLedger::nymbox);
11220  else if (theTransaction.Contains("inboxRecord"))
11221  lBoxType = static_cast<int64_t>(OTLedger::inbox);
11222  else if (theTransaction.Contains("outboxRecord"))
11223  lBoxType = static_cast<int64_t>(OTLedger::outbox);
11224  else if (theTransaction.Contains("paymentInboxRecord"))
11225  lBoxType = static_cast<int64_t>(OTLedger::paymentInbox);
11226  else if (theTransaction.Contains("recordBoxRecord"))
11227  lBoxType = static_cast<int64_t>(OTLedger::recordBox);
11228  else if (theTransaction.Contains("expiredBoxRecord"))
11229  lBoxType = static_cast<int64_t>(OTLedger::expiredBox);
11230  else {
11231  otErr << __FUNCTION__ << " Error loading from abbreviated "
11232  "transaction: unknown ledger type. \n";
11233  return "";
11234  }
11235  pTransaction =
11236  LoadBoxReceipt(theTransaction, static_cast<int64_t>(lBoxType));
11237  if (nullptr == pTransaction) {
11238  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11239  "transaction: failed loading box receipt. "
11240  "\n";
11241  return "";
11242  }
11243  theTransAngel.reset(pTransaction);
11244  }
11245  else
11246  pTransaction = &theTransaction;
11247  if (OTTransaction::pending != pTransaction->GetType()) {
11248  otErr << __FUNCTION__
11249  << ": wrong transaction type: " << pTransaction->GetTypeString()
11250  << ". (Expected \"pending\".)\n";
11251  return "";
11252  }
11253  OTString strReference;
11254  pTransaction->GetReferenceString(strReference);
11255 
11256  if (!strReference.Exists()) {
11257  otErr << __FUNCTION__
11258  << ": No reference string found on transaction.\n";
11259  return "";
11260  }
11261  std::unique_ptr<OTItem> pItem(OTItem::CreateItemFromString(
11262  strReference, theServerID, pTransaction->GetReferenceToNum()));
11263 
11264  if (nullptr == pItem) {
11265  otErr << __FUNCTION__
11266  << ": Failed loading transaction item from string.\n";
11267  return "";
11268  }
11269 
11270  // pItem will be automatically cleaned up when it goes out of scope.
11271  if ((OTItem::transfer != pItem->GetType()) ||
11272  (OTItem::request != pItem->GetStatus())) {
11273  otErr << __FUNCTION__ << ": Wrong item type or status attached as "
11274  "reference on transaction.\n";
11275  return "";
11276  }
11277  OTString strOutput;
11278 
11279  pItem->GetNote(strOutput);
11280  // Didn't find one.
11281  if (!strOutput.Exists()) return "";
11282 
11283  // We found a note -- let's return it!
11284  //
11285  std::string pBuf = strOutput.Get();
11286 
11287  return pBuf;
11288 }
11289 
11291  const std::string& SERVER_ID, const std::string& USER_ID,
11292  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
11293 {
11294  if (SERVER_ID.empty()) {
11295  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11296  OT_FAIL;
11297  }
11298  if (USER_ID.empty()) {
11299  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11300  OT_FAIL;
11301  }
11302  if (ACCOUNT_ID.empty()) {
11303  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11304  OT_FAIL;
11305  }
11306  if (THE_TRANSACTION.empty()) {
11307  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11308  OT_FAIL;
11309  }
11310 
11311  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11312  theAccountID(ACCOUNT_ID);
11313 
11314  OTString strTransaction(THE_TRANSACTION);
11315 
11317  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11318  if (nullptr == pNym) return OT_ERROR_AMOUNT;
11319 
11320  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11321 
11322  if (!theTransaction.LoadContractFromString(strTransaction)) {
11323  OTString strAcctID(theAccountID);
11324  otErr << __FUNCTION__
11325  << ": Error loading transaction from string. Acct ID: "
11326  << strAcctID << "\n";
11327  return -1;
11328  }
11329 
11330  OTTransaction* pTransaction = nullptr;
11331  std::unique_ptr<OTTransaction> theTransAngel;
11332 
11333  if (theTransaction.IsAbbreviated()) {
11334  int64_t lBoxType = 0;
11335 
11336  if (theTransaction.Contains("nymboxRecord"))
11337  lBoxType = static_cast<int64_t>(OTLedger::nymbox);
11338  else if (theTransaction.Contains("inboxRecord"))
11339  lBoxType = static_cast<int64_t>(OTLedger::inbox);
11340  else if (theTransaction.Contains("outboxRecord"))
11341  lBoxType = static_cast<int64_t>(OTLedger::outbox);
11342  else if (theTransaction.Contains("paymentInboxRecord"))
11343  lBoxType = static_cast<int64_t>(OTLedger::paymentInbox);
11344  else if (theTransaction.Contains("recordBoxRecord"))
11345  lBoxType = static_cast<int64_t>(OTLedger::recordBox);
11346  else if (theTransaction.Contains("expiredBoxRecord"))
11347  lBoxType = static_cast<int64_t>(OTLedger::expiredBox);
11348  else {
11349  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11350  "transaction: unknown ledger type. \n";
11351  return -1;
11352  }
11353  pTransaction =
11354  LoadBoxReceipt(theTransaction, static_cast<int64_t>(lBoxType));
11355  if (nullptr == pTransaction) {
11356  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11357  "transaction: failed loading box receipt. "
11358  "\n";
11359  return -1;
11360  }
11361  theTransAngel.reset(pTransaction);
11362  }
11363  else
11364  pTransaction = &theTransaction;
11365 
11366  return pTransaction->GetReceiptAmount();
11367 }
11368 
11369 // There is a notice in my inbox, from the server, informing me of
11370 // a pending transfer.
11371 // Oh? And this notice is in reference to what transaction ID?
11372 // This function will return the ID of the original transaction
11373 // that the sender used to send me the transfer in the first place.
11374 // Since his actual request is attached to the pending transaction,
11375 // I can use this function to look up the number.
11376 //
11377 // Returns cheque #, or market offer #, or payment plan #, or pending transfer #
11378 // (Meant to be used on inbox items.)
11379 //
11381  const std::string& SERVER_ID, const std::string& USER_ID,
11382  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
11383 {
11384  if (SERVER_ID.empty()) {
11385  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11386  OT_FAIL;
11387  }
11388  if (USER_ID.empty()) {
11389  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11390  OT_FAIL;
11391  }
11392  if (ACCOUNT_ID.empty()) {
11393  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11394  OT_FAIL;
11395  }
11396  if (THE_TRANSACTION.empty()) {
11397  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11398  OT_FAIL;
11399  }
11400 
11401  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11402  theAccountID(ACCOUNT_ID);
11403 
11404  OTString strTransaction(THE_TRANSACTION);
11405 
11407  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11408  if (nullptr == pNym) return -1;
11409 
11410  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11411 
11412  if (!theTransaction.LoadContractFromString(strTransaction)) {
11413  OTString strAcctID(theAccountID);
11414  otErr << __FUNCTION__
11415  << ": Error loading transaction from string. Acct ID: "
11416  << strAcctID << "\n";
11417  return -1;
11418  }
11419 
11420  // NO need to load abbreviated version here, since it already stores this
11421  // number.
11422  //
11423  const int64_t lDisplayNum = theTransaction.GetReferenceNumForDisplay();
11424  return lDisplayNum;
11425 }
11426 
11427 //
11428 // Get Transaction Type (internally uses GetTransactionTypeString().)
11429 //
11431  const std::string& SERVER_ID, const std::string& USER_ID,
11432  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
11433 {
11434  if (SERVER_ID.empty()) {
11435  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11436  OT_FAIL;
11437  }
11438  if (USER_ID.empty()) {
11439  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11440  OT_FAIL;
11441  }
11442  if (ACCOUNT_ID.empty()) {
11443  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11444  OT_FAIL;
11445  }
11446  if (THE_TRANSACTION.empty()) {
11447  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11448  OT_FAIL;
11449  }
11450 
11451  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11452  theAccountID(ACCOUNT_ID);
11453 
11454  OTString strTransaction(THE_TRANSACTION);
11455 
11457  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11458  if (nullptr == pNym) return "";
11459  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11460 
11461  if (!theTransaction.LoadContractFromString(strTransaction)) {
11462  OTString strAcctID(theAccountID);
11463  otErr << __FUNCTION__
11464  << ": Error loading transaction from string. Acct ID: "
11465  << strAcctID << "\n";
11466  return "";
11467  }
11468  // NO need to load abbreviated version, since it already stores this number.
11469 
11470  std::string pBuf = theTransaction.GetTypeString();
11471 
11472  return pBuf;
11473 }
11474 
11475 // Transactions do not have request numbers. However, if you have a replyNotice
11476 // in your Nymbox, which is an OTTransaction object, it will CONTAIN a server
11477 // reply to some previous message. This function will only work on a
11478 // replyNotice,
11479 // and it returns the actual request number of the server reply inside that
11480 // notice.
11481 // Used for calling OTAPI_Exec::HaveAlreadySeenReply() in order to see if we've
11482 // already
11483 // processed the reply for that message.
11484 // Returns "" on Error.
11485 //
11487  const std::string& SERVER_ID, const std::string& USER_ID,
11488  const std::string& THE_TRANSACTION) const
11489 {
11490  if (SERVER_ID.empty()) {
11491  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11492  OT_FAIL;
11493  }
11494  if (USER_ID.empty()) {
11495  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11496  OT_FAIL;
11497  }
11498  if (THE_TRANSACTION.empty()) {
11499  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11500  OT_FAIL;
11501  }
11502 
11503  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11504  theAccountID(USER_ID); // account IS user, for Nymbox (the only box that
11505  // carries replyNotices...)
11506 
11507  OTString strTransaction(THE_TRANSACTION);
11508 
11510  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11511  if (nullptr == pNym) return -1;
11512 
11513  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11514 
11515  if (!theTransaction.LoadContractFromString(strTransaction)) {
11516  OTString strUserID(theUserID);
11517  otErr << __FUNCTION__
11518  << ": Error loading transaction from string. User ID: "
11519  << strUserID << "\n";
11520  return -1;
11521  }
11522 
11523  if (OTTransaction::replyNotice != theTransaction.GetType()) {
11524  OTString strUserID(theUserID);
11525  otErr << __FUNCTION__ << ": Unexpected transaction type: "
11526  << theTransaction.GetTypeString()
11527  << ". (Expected: replyNotice) User: " << strUserID << "\n";
11528  return -1;
11529  }
11530  // NO need to load abbreviated version, since it already stores this number.
11531 
11532  const int64_t lRequestNumber = theTransaction.GetRequestNum();
11533 
11534  return lRequestNumber;
11535 }
11536 
11537 //
11538 // Get Transaction Date Signed (internally uses
11539 // OTTransaction::GetDateSigned().)
11540 //
11542  const std::string& SERVER_ID, const std::string& USER_ID,
11543  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
11544 {
11545  if (SERVER_ID.empty()) {
11546  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11547  OT_FAIL;
11548  }
11549  if (USER_ID.empty()) {
11550  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11551  OT_FAIL;
11552  }
11553  if (ACCOUNT_ID.empty()) {
11554  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11555  OT_FAIL;
11556  }
11557  if (THE_TRANSACTION.empty()) {
11558  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11559  OT_FAIL;
11560  }
11561 
11562  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11563  theAccountID(ACCOUNT_ID);
11564 
11565  OTString strTransaction(THE_TRANSACTION);
11566 
11568  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11569  if (nullptr == pNym) return OTTimeGetTimeFromSeconds(-1);
11570 
11571  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11572 
11573  if (!theTransaction.LoadContractFromString(strTransaction)) {
11574  OTString strAcctID(theAccountID);
11575  otErr << __FUNCTION__
11576  << ": Error loading transaction from string. Acct ID: "
11577  << strAcctID << "\n";
11578  return OTTimeGetTimeFromSeconds(-1);
11579  }
11580  // NO need to load abbreviated version here, since it already stores the
11581  // date.
11582 
11583  OTString strOutput;
11584  return theTransaction.GetDateSigned();
11585 }
11586 
11587 //
11588 // Get TransactionSuccess
11589 //
11590 // OT_TRUE (1) == acknowledgment
11591 // OT_FALSE (0) == rejection
11592 // OT_ERROR(-1) == error_state (such as dropped message.)
11593 //
11594 // Returns OT_BOOL.
11595 //
11597  const std::string& SERVER_ID, const std::string& USER_ID,
11598  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
11599 {
11600  if (SERVER_ID.empty()) {
11601  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11602  OT_FAIL;
11603  }
11604  if (USER_ID.empty()) {
11605  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11606  OT_FAIL;
11607  }
11608  if (ACCOUNT_ID.empty()) {
11609  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11610  OT_FAIL;
11611  }
11612  if (THE_TRANSACTION.empty()) {
11613  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11614  OT_FAIL;
11615  }
11616 
11617  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11618  theAccountID(ACCOUNT_ID);
11619 
11620  OTString strTransaction(THE_TRANSACTION);
11622  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11623  if (nullptr == pNym) return OT_ERROR;
11624  // By this point, pNym is a good pointer, and is on the wallet. (No need to
11625  // cleanup.)
11626  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11627 
11628  if (!theTransaction.LoadContractFromString(strTransaction)) {
11629  OTString strAcctID(theAccountID);
11630  otErr << __FUNCTION__
11631  << ": Error loading transaction from string. Acct ID: "
11632  << strAcctID << "\n";
11633  return OT_ERROR;
11634  }
11635  OTTransaction* pTransaction = nullptr;
11636  std::unique_ptr<OTTransaction> theTransAngel;
11637 
11638  if (theTransaction.IsAbbreviated()) // Abbreviated.
11639  {
11640  int64_t lBoxType = 0;
11641 
11642  if (theTransaction.Contains("nymboxRecord"))
11643  lBoxType = static_cast<int64_t>(OTLedger::nymbox);
11644  else if (theTransaction.Contains("inboxRecord"))
11645  lBoxType = static_cast<int64_t>(OTLedger::inbox);
11646  else if (theTransaction.Contains("outboxRecord"))
11647  lBoxType = static_cast<int64_t>(OTLedger::outbox);
11648  else if (theTransaction.Contains("paymentInboxRecord"))
11649  lBoxType = static_cast<int64_t>(OTLedger::paymentInbox);
11650  else if (theTransaction.Contains("recordBoxRecord"))
11651  lBoxType = static_cast<int64_t>(OTLedger::recordBox);
11652  else if (theTransaction.Contains("expiredBoxRecord"))
11653  lBoxType = static_cast<int64_t>(OTLedger::expiredBox);
11654  else {
11655  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11656  "transaction: unknown ledger type. \n";
11657  return OT_ERROR;
11658  }
11659  pTransaction =
11660  LoadBoxReceipt(theTransaction, static_cast<int64_t>(lBoxType));
11661  if (nullptr == pTransaction) {
11662  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11663  "transaction: failed loading box receipt. "
11664  "\n";
11665  return OT_ERROR;
11666  }
11667  theTransAngel.reset(pTransaction);
11668  }
11669  else // NOT abbreviated.
11670  pTransaction = &theTransaction;
11671 
11672  if (pTransaction->GetSuccess()) {
11673  return OT_TRUE;
11674  }
11675  else {
11676  const int64_t lTransactionNum = pTransaction->GetTransactionNum();
11677 
11678  otErr << __FUNCTION__
11679  << ": ** FYI, this transaction has a 'failure' status from the "
11680  "server. TransNum: " << lTransactionNum << "\n";
11681  }
11682 
11683  return OT_FALSE;
11684 }
11685 
11687  const std::string& SERVER_ID, const std::string& USER_ID,
11688  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
11689 {
11690  if (SERVER_ID.empty()) {
11691  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11692  OT_FAIL;
11693  }
11694  if (USER_ID.empty()) {
11695  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11696  OT_FAIL;
11697  }
11698  if (ACCOUNT_ID.empty()) {
11699  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11700  OT_FAIL;
11701  }
11702  if (THE_TRANSACTION.empty()) {
11703  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11704  OT_FAIL;
11705  }
11706 
11707  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11708  theAccountID(ACCOUNT_ID);
11709 
11710  OTString strTransaction(THE_TRANSACTION);
11712  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11713  if (nullptr == pNym) return OT_ERROR;
11714  // By this point, pNym is a good pointer, and is on the wallet. (No need to
11715  // cleanup.)
11716  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11717 
11718  if (!theTransaction.LoadContractFromString(strTransaction)) {
11719  OTString strAcctID(theAccountID);
11720  otErr << __FUNCTION__
11721  << ": Error loading transaction from string. Acct ID: "
11722  << strAcctID << "\n";
11723  return OT_ERROR;
11724  }
11725  OTTransaction* pTransaction = nullptr;
11726  std::unique_ptr<OTTransaction> theTransAngel;
11727 
11728  // Note: This is an artifact from Transaction_GetSuccess, whose code was
11729  // copied to make
11730  // this function. In reality, a cancelled transaction will never be
11731  // abbreviated, since it
11732  // won't be used as any kind of box receipt in the first place. Rather, a
11733  // canceled transaction
11734  // will only occur as a server reply to a transaction request. For example,
11735  // if you cancel a
11736  // cheque, or cancel a payment plan, and that cancellation is successful,
11737  // then the server
11738  // will return a "reply transaction" to that request, which has 'cancelled'
11739  // set to true.
11740  // So why am I leaving this code here for now? We can trim it down later I
11741  // suppose.
11742  //
11743  if (theTransaction.IsAbbreviated()) // Abbreviated.
11744  {
11745  int64_t lBoxType = 0;
11746 
11747  if (theTransaction.Contains("nymboxRecord"))
11748  lBoxType = static_cast<int64_t>(OTLedger::nymbox);
11749  else if (theTransaction.Contains("inboxRecord"))
11750  lBoxType = static_cast<int64_t>(OTLedger::inbox);
11751  else if (theTransaction.Contains("outboxRecord"))
11752  lBoxType = static_cast<int64_t>(OTLedger::outbox);
11753  else if (theTransaction.Contains("paymentInboxRecord"))
11754  lBoxType = static_cast<int64_t>(OTLedger::paymentInbox);
11755  else if (theTransaction.Contains("recordBoxRecord"))
11756  lBoxType = static_cast<int64_t>(OTLedger::recordBox);
11757  else if (theTransaction.Contains("expiredBoxRecord"))
11758  lBoxType = static_cast<int64_t>(OTLedger::expiredBox);
11759  else {
11760  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11761  "transaction: unknown ledger type. \n";
11762  return OT_ERROR;
11763  }
11764  pTransaction =
11765  LoadBoxReceipt(theTransaction, static_cast<int64_t>(lBoxType));
11766  if (nullptr == pTransaction) {
11767  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11768  "transaction: failed loading box receipt. "
11769  "\n";
11770  return OT_ERROR;
11771  }
11772  theTransAngel.reset(pTransaction);
11773  }
11774  else // NOT abbreviated.
11775  pTransaction = &theTransaction;
11776  if (pTransaction->IsCancelled()) {
11777  return OT_TRUE;
11778  }
11779 
11780  return OT_FALSE;
11781 }
11782 
11783 //
11784 // Get Balance Agreement Success
11785 // (from a TRANSACTION.)
11786 // true (1) == acknowledgment
11787 // false (0) == rejection
11788 // NEW: -1 (-1) for error
11789 //
11791  const std::string& SERVER_ID, const std::string& USER_ID,
11792  const std::string& ACCOUNT_ID, const std::string& THE_TRANSACTION) const
11793 {
11794  if (SERVER_ID.empty()) {
11795  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11796  OT_FAIL;
11797  }
11798  if (USER_ID.empty()) {
11799  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11800  OT_FAIL;
11801  }
11802  if (ACCOUNT_ID.empty()) {
11803  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11804  OT_FAIL;
11805  }
11806  if (THE_TRANSACTION.empty()) {
11807  otErr << __FUNCTION__ << ": Null: THE_TRANSACTION passed in!\n";
11808  OT_FAIL;
11809  }
11810 
11811  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11812  theAccountID(ACCOUNT_ID);
11813 
11814  OTString strTransaction(THE_TRANSACTION);
11815 
11817  theUserID, false, __FUNCTION__); // These copiously log, and ASSERT.
11818  if (nullptr == pNym) return OT_ERROR;
11819  // By this point, pNym is a good pointer, and is on the wallet. (No need to
11820  // cleanup.)
11821  OTTransaction theTransaction(theUserID, theAccountID, theServerID);
11822 
11823  if (!theTransaction.LoadContractFromString(strTransaction)) {
11824  OTString strAcctID(theAccountID);
11825  otErr << __FUNCTION__
11826  << ": Error loading transaction from string. Acct ID: "
11827  << strAcctID << "\n";
11828  return OT_ERROR;
11829  }
11830  OTTransaction* pTransaction = nullptr;
11831  std::unique_ptr<OTTransaction> theTransAngel;
11832 
11833  if (theTransaction.IsAbbreviated()) // IF TRANSACTION IS ABBREVIATED (Ledger
11834  // may only contain stubs, not full
11835  // records...)
11836  {
11837  int64_t lBoxType = 0;
11838 
11839  if (theTransaction.Contains("nymboxRecord"))
11840  lBoxType = static_cast<int64_t>(OTLedger::nymbox);
11841  else if (theTransaction.Contains("inboxRecord"))
11842  lBoxType = static_cast<int64_t>(OTLedger::inbox);
11843  else if (theTransaction.Contains("outboxRecord"))
11844  lBoxType = static_cast<int64_t>(OTLedger::outbox);
11845  else if (theTransaction.Contains("paymentInboxRecord"))
11846  lBoxType = static_cast<int64_t>(OTLedger::paymentInbox);
11847  else if (theTransaction.Contains("recordBoxRecord"))
11848  lBoxType = static_cast<int64_t>(OTLedger::recordBox);
11849  else if (theTransaction.Contains("expiredBoxRecord"))
11850  lBoxType = static_cast<int64_t>(OTLedger::expiredBox);
11851  else {
11852  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11853  "transaction: unknown ledger type. \n";
11854  return OT_ERROR;
11855  }
11856  pTransaction =
11857  LoadBoxReceipt(theTransaction, static_cast<int64_t>(lBoxType));
11858  if (nullptr == pTransaction) {
11859  otErr << __FUNCTION__ << ": Error loading from abbreviated "
11860  "transaction: failed loading box "
11861  "receipt.\n";
11862  return OT_ERROR;
11863  }
11864  theTransAngel.reset(pTransaction);
11865  }
11866  else
11867  pTransaction = &theTransaction;
11868  // At this point, I actually have the transaction pointer, so let's return
11869  // its success status
11870  OTItem* pReplyItem = pTransaction->GetItem(OTItem::atBalanceStatement);
11871 
11872  if (nullptr == pReplyItem)
11873  pReplyItem = pTransaction->GetItem(OTItem::atTransactionStatement);
11874 
11875  if (nullptr == pReplyItem) {
11876  otErr << __FUNCTION__ << ": good transaction (could have been "
11877  "abbreviated though) but uncovered \"\" item "
11878  "pointer.\n";
11879  return OT_ERROR; // Weird.
11880  }
11881 
11882  return (pReplyItem->GetStatus() == OTItem::acknowledgement) ? OT_TRUE
11883  : OT_FALSE;
11884 }
11885 
11886 // GET BALANCE AGREEMENT SUCCESS (From a MESSAGE.)
11887 //
11888 // Returns true (1) for Success and false (0) for Failure.
11889 // New: returns -1 (-1) for error.
11890 //
11892  const std::string& SERVER_ID, const std::string& USER_ID,
11893  const std::string& ACCOUNT_ID, const std::string& THE_MESSAGE) const
11894 {
11895  if (SERVER_ID.empty()) {
11896  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
11897  OT_FAIL;
11898  }
11899  if (USER_ID.empty()) {
11900  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
11901  OT_FAIL;
11902  }
11903  if (ACCOUNT_ID.empty()) {
11904  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
11905  OT_FAIL;
11906  }
11907  if (THE_MESSAGE.empty()) {
11908  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
11909  OT_FAIL;
11910  }
11911 
11912  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
11913  theAccountID(ACCOUNT_ID);
11914 
11915  OTString strMessage(THE_MESSAGE);
11916 
11917  OTMessage theMessage;
11918 
11919  if (!strMessage.Exists() ||
11920  !theMessage.LoadContractFromString(strMessage)) {
11921  otOut << __FUNCTION__ << ": Unable to load message.\n";
11922  return OT_ERROR;
11923  }
11924 
11925  // It's not a transaction request or response, so the Payload wouldn't
11926  // contain a ledger. (Don't want to pass back whatever it DOES contain
11927  // in that case, now do I?)
11928  //
11929  if ((false == theMessage.m_strCommand.Compare("@notarizeTransactions")) &&
11930  (false == theMessage.m_strCommand.Compare("@processNymbox")) &&
11931  (false == theMessage.m_strCommand.Compare("@processInbox"))) {
11932  otOut << __FUNCTION__
11933  << ": Wrong message type: " << theMessage.m_strCommand << "\n";
11934  return OT_ERROR;
11935  }
11936 
11937  // The ledger is stored in the Payload, we'll grab it into the String.
11938  OTString strLedger(theMessage.m_ascPayload);
11939 
11940  if (!strLedger.Exists()) {
11941  otOut << __FUNCTION__ << ": No ledger found on message.\n";
11942  return OT_ERROR;
11943  }
11944 
11945  OTLedger theLedger(theUserID, theAccountID, theServerID);
11946 
11947  if (!theLedger.LoadLedgerFromString(strLedger)) {
11948  OTString strAcctID(theAccountID);
11949  otErr << __FUNCTION__
11950  << ": Error loading ledger from string. Acct ID: " << strAcctID
11951  << "\n";
11952  return OT_ERROR;
11953  }
11954 
11955  // At this point, I know theLedger loaded successfully.
11956 
11957  if (theLedger.GetTransactionCount() <= 0) {
11958  otErr << __FUNCTION__ << " bad count in message ledger: "
11959  << theLedger.GetTransactionCount() << "\n";
11960  return OT_ERROR; // out of bounds. I'm saving from an OT_ASSERT_MSG()
11961  // happening here. (Maybe I shouldn't.)
11962  }
11963 
11964  OTTransaction* pReplyTransaction = theLedger.GetTransactionByIndex(
11965  0); // Right now this is a defacto standard. (only 1 transaction per
11966  // message ledger, excepting process inbox. <== why? That's one as
11967  // well I thought. And has multiple items attached.)
11968 
11969  if (nullptr == pReplyTransaction) {
11970  otErr << __FUNCTION__
11971  << " good index but uncovered \"\" pointer there: " << 0 << "\n";
11972  return OT_ERROR; // Weird.
11973  }
11974 
11975  // At this point, I actually have the transaction pointer, so let's return
11976  // its success status
11977  OTItem* pReplyItem = pReplyTransaction->GetItem(OTItem::atBalanceStatement);
11978 
11979  if (nullptr == pReplyItem)
11980  pReplyItem = pReplyTransaction->GetItem(OTItem::atTransactionStatement);
11981 
11982  if (nullptr == pReplyItem) {
11983  otErr << __FUNCTION__
11984  << " good index but uncovered \"\" item pointer: " << 0 << "\n";
11985  return OT_ERROR; // Weird.
11986  }
11987 
11988  if (pReplyItem->GetStatus() == OTItem::acknowledgement) {
11989  return OT_TRUE;
11990  }
11991 
11992  return OT_FALSE;
11993 }
11994 
11995 /*
11996 std::string OTAPI_Exec::LoadPurse(const std::string& SERVER_ID,
11997  std::string ASSET_TYPE_ID,
11998  std::string USER_ID) // returns "", or a
11999 purse.
12000 {
12001  OT_ASSERT_MSG("" != SERVER_ID, "Null SERVER_ID passed in.");
12002  OT_ASSERT_MSG("" != ASSET_TYPE_ID, "Null ASSET_TYPE_ID passed in.");
12003  OT_ASSERT_MSG("" != USER_ID, "Null USER_ID passed in.");
12004 
12005  const OTIdentifier theServerID(SERVER_ID);
12006  const OTIdentifier theAssetID(ASSET_TYPE_ID);
12007  const OTIdentifier theUserID(USER_ID);
12008 
12009  // There is an OT_ASSERT in here for memory failure,
12010  // but it still might return "" if various verification fails.
12011  OTPurse * pPurse = OTAPI()->LoadPurse(theServerID, theAssetID, theUserID);
12012 
12013  // Make sure it gets cleaned up when this goes out of scope.
12014  OTCleanup<OTPurse> thePurseAngel(pPurse); // I pass the pointer, in case
12015 it's "".
12016 
12017  if (nullptr == pPurse)
12018  {
12019  otOut << "Failure calling OT_API::LoadPurse in
12020 OTAPI_Exec::LoadPurse.\n Server: " << SERVER_ID << "\n Asset Type: " <<
12021 ASSET_TYPE_ID << "\n";
12022  }
12023  else // success
12024  {
12025  OTString strOutput(*pPurse); // For the output
12026 
12027  std::string pBuf = strOutput.Get();
12028 
12029 
12030 
12031  return pBuf;
12032  }
12033 
12034  return "";
12035 }
12036 */
12037 
12038 // PURSE FUNCTIONS
12039 
12040 // Warning! This will overwrite whatever purse is there.
12041 // The proper way to use this function is, LOAD the purse,
12042 // then IMPORT whatever other purse you want into it, then
12043 // SAVE it again.
12044 bool OTAPI_Exec::SavePurse(const std::string& SERVER_ID,
12045  const std::string& ASSET_TYPE_ID,
12046  const std::string& USER_ID,
12047  const std::string& THE_PURSE) const // returns bool
12048 {
12049  if (SERVER_ID.empty()) {
12050  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12051  OT_FAIL;
12052  }
12053  if (ASSET_TYPE_ID.empty()) {
12054  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12055  OT_FAIL;
12056  }
12057  if (USER_ID.empty()) {
12058  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
12059  OT_FAIL;
12060  }
12061  if (THE_PURSE.empty()) {
12062  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12063  OT_FAIL;
12064  }
12065 
12066  std::string strFunc = __FUNCTION__;
12067  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID),
12068  theUserID(USER_ID);
12069  const OTString strPurse(THE_PURSE);
12070  bool bSuccess = false;
12071  Purse thePurse(theServerID, theAssetTypeID, theUserID);
12072 
12073  if (strPurse.Exists() && thePurse.LoadContractFromString(strPurse)) {
12074  // NOTE: no need to verify the server / asset ID here, since the call
12075  // to SavePurse already does that.
12076  //
12077  // if ((theServerID != thePurse.GetServerID()) ||
12078  // (theAssetTypeID != thePurse.GetAssetID()))
12079  // {
12080  // otOut << strFunc << ": Failure loading purse from string;
12081  // server "
12082  // "or asset ID didn't match what was
12083  // expected:\n" << strPurse << "\n";
12084  // }
12085  if (OTAPI()->SavePurse(theServerID, theAssetTypeID, theUserID,
12086  thePurse)) {
12087  bSuccess = true;
12088  }
12089  else {
12090  otOut << strFunc << ": Failure saving purse:\n" << strPurse << "\n";
12091  }
12092  }
12093  else {
12094  otOut << strFunc << ": Failure loading purse from string:\n" << strPurse
12095  << "\n";
12096  }
12097 
12098  return bSuccess;
12099 }
12100 
12101 // LOAD PURSE -- (from local storage)
12102 //
12103 // Based on Asset Type ID: load a purse, a public mint, or an asset contract
12104 // and return it as a string -- or return "" if it wasn't found.
12105 //
12106 std::string OTAPI_Exec::LoadPurse(const std::string& SERVER_ID,
12107  const std::string& ASSET_TYPE_ID,
12108  const std::string& USER_ID) const // returns
12109  // "", or
12110  // a purse.
12111 {
12112  if (SERVER_ID.empty()) {
12113  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12114  OT_FAIL;
12115  }
12116  if (ASSET_TYPE_ID.empty()) {
12117  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12118  OT_FAIL;
12119  }
12120  if (USER_ID.empty()) {
12121  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
12122  OT_FAIL;
12123  }
12124  const OTIdentifier theServerID(SERVER_ID);
12125  const OTIdentifier theAssetID(ASSET_TYPE_ID);
12126  const OTIdentifier theUserID(USER_ID);
12127  // There is an OT_ASSERT in here for memory failure,
12128  // but it still might return "" if various verification fails.
12129 
12130  std::unique_ptr<Purse> pPurse(
12131  OTAPI()->LoadPurse(theServerID, theAssetID, theUserID));
12132 
12133  if (nullptr == pPurse) {
12134  otInfo << "OTAPI_Exec::LoadPurse() received null when called "
12135  "OT_API::LoadPurse(). Server: " << SERVER_ID
12136  << " Asset Type: " << ASSET_TYPE_ID << "\n";
12137  }
12138  else // success
12139  {
12140  OTString strOutput(*pPurse); // For the output
12141  std::string pBuf = strOutput.Get();
12142  return pBuf;
12143  }
12144 
12145  return "";
12146 }
12147 
12148 // Get Purse Total Value (internally uses GetTotalValue().)
12149 //
12150 // Returns the purported sum of all the tokens within.
12151 //
12152 int64_t OTAPI_Exec::Purse_GetTotalValue(const std::string& SERVER_ID,
12153  const std::string& ASSET_TYPE_ID,
12154  const std::string& THE_PURSE) const
12155 {
12156  if (SERVER_ID.empty()) {
12157  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12158  OT_FAIL;
12159  }
12160  if (ASSET_TYPE_ID.empty()) {
12161  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12162  OT_FAIL;
12163  }
12164  if (THE_PURSE.empty()) {
12165  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12166  OT_FAIL;
12167  }
12168  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID);
12169  OTString strPurse(THE_PURSE);
12170  Purse thePurse(theServerID, theAssetTypeID);
12171 
12172  if (!thePurse.LoadContractFromString(strPurse)) {
12173  OTString strAssetTypeID(theAssetTypeID);
12174  otErr << __FUNCTION__
12175  << ": Error loading purse from string. Asset Type ID: "
12176  << strAssetTypeID << "\n";
12177  return OT_ERROR_AMOUNT;
12178  }
12179 
12180  int64_t lTotalValue = thePurse.GetTotalValue();
12181  return lTotalValue > 0 ? lTotalValue : 0;
12182 }
12183 
12184 // Returns a count of the tokens inside this purse. (Coins.)
12185 // or -1 in case of error.
12186 //
12187 int32_t OTAPI_Exec::Purse_Count(const std::string& SERVER_ID,
12188  const std::string& ASSET_TYPE_ID,
12189  const std::string& THE_PURSE) const
12190 {
12191  if (SERVER_ID.empty()) {
12192  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12193  OT_FAIL;
12194  }
12195  if (ASSET_TYPE_ID.empty()) {
12196  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12197  OT_FAIL;
12198  }
12199  if (THE_PURSE.empty()) {
12200  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12201  OT_FAIL;
12202  }
12203 
12204  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID);
12205  const OTString strPurse(THE_PURSE);
12206  Purse thePurse(theServerID, theAssetTypeID);
12207 
12208  if (strPurse.Exists() && thePurse.LoadContractFromString(strPurse) &&
12209  (thePurse.GetServerID() == theServerID) &&
12210  (thePurse.GetAssetID() == theAssetTypeID)) {
12211  return thePurse.Count();
12212  }
12213 
12214  return OT_ERROR;
12215 }
12216 
12217 // Some purses are encrypted to a specific Nym.
12218 // Whereas other purses are encrypted to a passphrase.
12219 // This function returns bool and lets you know, either way.
12220 //
12221 bool OTAPI_Exec::Purse_HasPassword(const std::string& SERVER_ID,
12222  const std::string& THE_PURSE) const
12223 {
12224  if (SERVER_ID.empty()) {
12225  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12226  OT_FAIL;
12227  }
12228  if (THE_PURSE.empty()) {
12229  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12230  OT_FAIL;
12231  }
12232 
12233  const OTIdentifier theServerID(SERVER_ID);
12234  const OTString strPurse(THE_PURSE);
12235  Purse thePurse(theServerID);
12236 
12237  if (strPurse.Exists() && thePurse.LoadContractFromString(strPurse) &&
12238  (thePurse.GetServerID() == theServerID)) {
12239  return thePurse.IsPasswordProtected();
12240  }
12241 
12242  return false;
12243 }
12244 
12245 // returns "", or a purse.
12246 //
12247 std::string OTAPI_Exec::CreatePurse(const std::string& SERVER_ID,
12248  const std::string& ASSET_TYPE_ID,
12249  const std::string& OWNER_ID,
12250  const std::string& SIGNER_ID) const
12251 {
12252  if (SERVER_ID.empty()) {
12253  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12254  OT_FAIL;
12255  }
12256  if (ASSET_TYPE_ID.empty()) {
12257  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12258  OT_FAIL;
12259  }
12260  if (OWNER_ID.empty()) {
12261  otErr << __FUNCTION__ << ": Null: OWNER_ID passed in!\n";
12262  OT_FAIL;
12263  }
12264  if (SIGNER_ID.empty()) {
12265  otErr << __FUNCTION__ << ": Null: SIGNER_ID passed in!\n";
12266  OT_FAIL;
12267  }
12268 
12269  std::string strFunc = __FUNCTION__;
12270 
12271  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID),
12272  theOwnerID(OWNER_ID), theSignerID(SIGNER_ID);
12273  OTPasswordData thePWData(
12274  "Creating a cash purse. Enter wallet master password.");
12275  OTPseudonym* pOwnerNym =
12276  OTAPI()->GetOrLoadNym(theOwnerID, false, strFunc.c_str(), &thePWData);
12277  if (nullptr == pOwnerNym) return "";
12278  OTPseudonym* pSignerNym = OTAPI()->GetOrLoadPrivateNym(
12279  theSignerID, false, strFunc.c_str(),
12280  &thePWData); // These copiously log, and ASSERT.
12281  if (nullptr == pSignerNym) return "";
12282  // By this point, pSignerNym is a good pointer, and is on the wallet. (No
12283  // need to cleanup.)
12284  std::unique_ptr<Purse> pPurse(
12285  OTAPI()->CreatePurse(theServerID, theAssetTypeID, theOwnerID));
12286 
12287  if (nullptr != pPurse) {
12288  pPurse->SignContract(*pSignerNym, &thePWData);
12289  pPurse->SaveContract();
12290  const OTString strOutput(*pPurse);
12291  std::string pBuf = strOutput.Get();
12292 
12293  return pBuf;
12294  }
12295  return "";
12296 }
12297 
12298 // When we create a password-protected purse, OWNER_ID has changed to SIGNER_ID,
12299 // since we still need a Nym to sign it (in order to save it to string.) But
12300 // this
12301 // Nym will not be the owner. There is no owner, and the tokens are not
12302 // encrypted
12303 // to any Nym (but instead to a passphrase.)
12304 //
12305 // returns "", or a purse.
12306 //
12308  const std::string& SERVER_ID, const std::string& ASSET_TYPE_ID,
12309  const std::string& SIGNER_ID) const
12310 {
12311  if (SERVER_ID.empty()) {
12312  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12313  OT_FAIL;
12314  }
12315  if (ASSET_TYPE_ID.empty()) {
12316  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12317  OT_FAIL;
12318  }
12319  if (SIGNER_ID.empty()) {
12320  otErr << __FUNCTION__ << ": Null: SIGNER_ID passed in!\n";
12321  OT_FAIL;
12322  }
12323  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID),
12324  theSignerID(SIGNER_ID);
12325  OTPasswordData thePWData("Creating a password-protected cash purse.");
12327  theSignerID, false, __FUNCTION__,
12328  &thePWData); // These copiously log, and ASSERT.
12329  if (nullptr == pNym) return "";
12330  // By this point, pNym is a good pointer, and is on the wallet. (No need to
12331  // cleanup.)
12332  std::unique_ptr<Purse> pPurse(
12333  OTAPI()->CreatePurse_Passphrase(theServerID, theAssetTypeID));
12334 
12335  if (nullptr != pPurse) {
12336  pPurse->SignContract(*pNym, &thePWData);
12337  pPurse->SaveContract();
12338  const OTString strOutput(*pPurse);
12339  std::string pBuf = strOutput.Get();
12340 
12341  return pBuf;
12342  }
12343  return "";
12344 }
12345 
12346 // Returns the TOKEN on top of the stock (LEAVING it on top of the stack,
12347 // but giving you a decrypted string copy of it.)
12348 //
12349 // OWNER_ID can be "", **if** the purse is password-protected.
12350 // (It's just ignored in that case.) Otherwise MUST contain the NymID for
12351 // the Purse owner (necessary to decrypt the token.)
12352 //
12353 // returns "" if failure.
12354 //
12356  const std::string& SERVER_ID, const std::string& ASSET_TYPE_ID,
12357  const std::string& OWNER_ID, // This should be "", **IF** purse is
12358  // password-protected. Otherwise MUST contain
12359  // the NymID for the Purse owner (necessary to
12360  // decrypt the token.)
12361  const std::string& THE_PURSE) const
12362 {
12363  OTString strOutput; // for later.
12364 
12365  if (SERVER_ID.empty()) {
12366  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12367  OT_FAIL;
12368  }
12369  if (ASSET_TYPE_ID.empty()) {
12370  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12371  OT_FAIL;
12372  }
12373  // if (OWNER_ID.empty()) { otErr << __FUNCTION__ << ": Null:
12374  // OWNER_ID passed
12375  // in!\n"; OT_FAIL; }
12376  if (THE_PURSE.empty()) {
12377  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12378  OT_FAIL;
12379  }
12380 
12381  std::string strFunc = __FUNCTION__; //"OTAPI_Exec::Purse_Peek";
12382  OTPasswordData thePWData("Peeking at cash purse contents.");
12383  const bool& bDoesOwnerIDExist =
12384  (("" != OWNER_ID) && ('\0' != OWNER_ID[0])); // If bDoesOwnerIDExist is
12385  // not true, then the purse
12386  // MUST be
12387  // password-protected.
12388  OTIdentifier theOwnerID;
12389  if (bDoesOwnerIDExist) {
12390  const OTString strOwnerID(OWNER_ID);
12391  OTPseudonym* pNym = nullptr;
12392  if (strOwnerID.Exists()) {
12393  theOwnerID.SetString(strOwnerID);
12394  pNym = OTAPI()->GetOrLoadPrivateNym(
12395  theOwnerID, false, strFunc.c_str(),
12396  &thePWData); // These copiously log, and ASSERT.
12397  }
12398  if (nullptr == pNym) return "";
12399  }
12400  // By this point, pNym is a good pointer, and is on the wallet. (No need to
12401  // cleanup.)
12402  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID);
12403  const OTString strPurse(THE_PURSE);
12404  std::unique_ptr<Token> pToken(OTAPI()->Purse_Peek(
12405  theServerID, theAssetTypeID, strPurse,
12406  bDoesOwnerIDExist ? &theOwnerID : nullptr, nullptr));
12407  if (nullptr != pToken) {
12408  pToken->SaveContractRaw(strOutput);
12409 
12410  std::string pBuf = strOutput.Get();
12411 
12412  return pBuf;
12413  }
12414  else
12415  otOut << strFunc << ": Failed peeking at a token on a cash purse.\n";
12416  return "";
12417 }
12418 
12419 // Removes the token from the top of the stock and DESTROYS IT,
12420 // and RETURNS THE UPDATED PURSE (with the token now missing from it.)
12421 //
12422 // WARNING: Do not call this function unless you have PEEK()d FIRST!!
12423 // Otherwise you will lose the token and get left "holding the bag".
12424 //
12425 // returns "" if failure.
12426 //
12428  const std::string& SERVER_ID, const std::string& ASSET_TYPE_ID,
12429  const std::string& OWNER_OR_SIGNER_ID, // The purse, in order to be changed,
12430  // must be
12431  // re-signed, which requires a private Nym. If the
12432  // purse is password-protected, then there's no
12433  // owner, but you still need to pass a Nym in here
12434  // to sign it (doesn't really matter which one, as
12435  // long as the private key is available, for
12436  // signing.) In that case, he's the signer. But if
12437  // the purse DOES have a Nym owner, then you MUST
12438  // pass the owner's Nym ID here, in order for this
12439  // action to be successful. (Because we must be able
12440  // to load the private key for that Nym, in order to
12441  // perform the pop. In which case we might as well
12442  // use the same Nym for signing...)
12443  const std::string& THE_PURSE) const
12444 {
12445  OTString strOutput; // for later.
12446 
12447  if (SERVER_ID.empty()) {
12448  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12449  OT_FAIL;
12450  }
12451  if (ASSET_TYPE_ID.empty()) {
12452  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12453  OT_FAIL;
12454  }
12455  if (OWNER_OR_SIGNER_ID.empty()) {
12456  otErr << __FUNCTION__ << ": Null: OWNER_OR_SIGNER_ID passed in!\n";
12457  OT_FAIL;
12458  }
12459  if (THE_PURSE.empty()) {
12460  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12461  OT_FAIL;
12462  }
12463 
12464  std::string strFunc = __FUNCTION__; //"OTAPI_Exec::Purse_Pop";
12465  const OTString strReason("Popping a token off of a cash purse.");
12466  OTPasswordData thePWData(strReason);
12467  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID),
12468  theNymID(OWNER_OR_SIGNER_ID);
12469  const OTString strPurse(THE_PURSE);
12471  theNymID, false, strFunc.c_str(),
12472  &thePWData); // These copiously log, and ASSERT.
12473  if (nullptr == pNym) return "";
12474  // By this point, pNym is a good pointer, and is on the wallet. (No need to
12475  // cleanup.)
12476  std::unique_ptr<Purse> pPurse(OTAPI()->Purse_Pop(
12477  theServerID, theAssetTypeID, strPurse,
12478  &theNymID, // Note: if the purse is password-protected, then this
12479  // parameter is ignored.
12480  &strReason));
12481  if (nullptr != pPurse) {
12482  pPurse->ReleaseSignatures();
12483  pPurse->SignContract(*pNym, &thePWData);
12484  pPurse->SaveContract();
12485 
12486  pPurse->SaveContractRaw(strOutput);
12487  std::string pBuf = strOutput.Get();
12488 
12489  return pBuf;
12490  }
12491  else
12492  otOut << strFunc << ": Failed popping a token off of a cash purse.\n";
12493 
12494  return "";
12495 }
12496 
12497 // Makes an exact copy of a purse, except with no tokens inside. (Value of
12498 // zero.)
12499 // Useful when you need to create a temporary purse for moving tokens around,
12500 // and
12501 // you don't want some new symmetric/master key being generated for that purse
12502 // as
12503 // though it were really some new "other purse."
12504 // For example, if you have a password-protected purse, you might want to pop
12505 // all of
12506 // the tokens off of it, and as you iterate, re-assign half of them to new
12507 // ownership,
12508 // push those onto a new purse owned by that new owner. But you only want to do
12509 // this
12510 // with half of the tokens... the other half of the tokens, you just want to
12511 // push onto
12512 // a temp purse (for the loop) that's owned by the original owner, so you can
12513 // then save
12514 // it back over the original in storage (since it contains "all the tokens that
12515 // WEREN'T
12516 // deposited" or "all the tokens that WEREN'T exported" etc.
12517 //
12518 // The point? If the "original owner" is a password-protected purse with a
12519 // symmetric
12520 // key, then you can't just generate some new "temp purse" without also
12521 // generating a
12522 // whole new KEY, which you DO NOT want to do. You also don't want to have to
12523 // deal with
12524 // re-assigning ownership back and forth between the two purses -- you just want
12525 // to
12526 // shove some tokens into one temporarily so you can finish your loop.
12527 // You could take the original purse and make a copy of it, and then just pop
12528 // all the
12529 // tokens off of it one-by-one, but that is very cumbersome and expensive. But
12530 // that'd
12531 // be the only way to get a copy of the original purse with the SAME symmetric
12532 // key,
12533 // except empty, so you can use it as a temp purse.
12534 // Therefore, to make that easier and solve that whole dilemma, I present:
12535 // OTAPI_Exec::Purse_Empty.
12536 // OTAPI_Exec::Purse_Empty takes a purse and returns an empty version of it
12537 // (except if there's
12538 // a symmetric/master key inside, those are preserved, so you can use it as a
12539 // temp purse.)
12540 //
12541 // This function is effectively the same thing as calling Pop until the purse is
12542 // empty.
12543 // Returns: the empty purse, or "" if failure.
12544 //
12545 std::string OTAPI_Exec::Purse_Empty(const std::string& SERVER_ID,
12546  const std::string& ASSET_TYPE_ID,
12547  const std::string& SIGNER_ID,
12548  const std::string& THE_PURSE) const
12549 {
12550  OTString strOutput; // for later.
12551 
12552  if (SERVER_ID.empty()) {
12553  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12554  OT_FAIL;
12555  }
12556  if (ASSET_TYPE_ID.empty()) {
12557  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12558  OT_FAIL;
12559  }
12560  if (SIGNER_ID.empty()) {
12561  otErr << __FUNCTION__ << ": Null: SIGNER_ID passed in!\n";
12562  OT_FAIL;
12563  }
12564  if (THE_PURSE.empty()) {
12565  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12566  OT_FAIL;
12567  }
12568 
12569  std::string strFunc = __FUNCTION__; //"OTAPI_Exec::Purse_Empty";
12570  const OTString strReason("Creating an empty copy of a cash purse.");
12571  OTPasswordData thePWData(strReason);
12572  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID),
12573  theNymID(SIGNER_ID);
12574  const OTString strPurse(THE_PURSE);
12576  theNymID, false, strFunc.c_str(),
12577  &thePWData); // These copiously log, and ASSERT.
12578  if (nullptr == pNym) return "";
12579  // By this point, pNym is a good pointer, and is on the wallet. (No need to
12580  // cleanup.)
12581  std::unique_ptr<Purse> pPurse(OTAPI()->Purse_Empty(
12582  theServerID, theAssetTypeID, strPurse, &strReason));
12583  if (nullptr != pPurse) {
12584  pPurse->ReleaseSignatures();
12585  pPurse->SignContract(*pNym, &thePWData);
12586  pPurse->SaveContract();
12587 
12588  pPurse->SaveContractRaw(strOutput);
12589  std::string pBuf = strOutput.Get();
12590 
12591  return pBuf;
12592  }
12593  else
12594  otOut << strFunc << ": Failed emptying a cash purse.\n";
12595 
12596  return "";
12597 }
12598 
12599 // Pushes a token onto the stack (of the purse.)
12600 // Returns the updated purse (now including the token.)
12601 //
12602 // Returns "" if failure.
12603 //
12605  const std::string& SERVER_ID, const std::string& ASSET_TYPE_ID,
12606  const std::string& SIGNER_ID, // The purse, in order to be changed, must be
12607  // re-signed, which requires a private Nym.
12608  // Even if the purse is password-protected,
12609  // then there's no owner, but you still need
12610  // to pass a Nym in here to sign it (doesn't
12611  // really matter which one, but must have
12612  // private key for signing.)
12613  const std::string& OWNER_ID, // If the purse is password-protected, then
12614  // there's no owner, and this owner parameter
12615  // should be "". However, if the purse DOES
12616  // have a Nym owner, then you MUST pass the
12617  // owner's Nym ID here, in order for this
12618  // action to be successful. Furthermore, the
12619  // public key for that Nym must be available,
12620  // in order to encrypt the token being pushed
12621  // into the purse. (Private key NOT necessary
12622  // for owner, in this case.) If this fails due
12623  // to public key not being available, just
12624  // download it from the server and try again.
12625  const std::string& THE_PURSE, const std::string& THE_TOKEN) const
12626 {
12627  OTString strOutput; // for later.
12628 
12629  if (SERVER_ID.empty()) {
12630  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12631  OT_FAIL;
12632  }
12633  if (ASSET_TYPE_ID.empty()) {
12634  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12635  OT_FAIL;
12636  }
12637  if (SIGNER_ID.empty()) {
12638  otErr << __FUNCTION__ << ": Null: SIGNER_ID passed in!\n";
12639  OT_FAIL;
12640  }
12641  // if (OWNER_ID.empty()) { otErr << __FUNCTION__ << ": Null:
12642  // OWNER_ID passed
12643  // in!\n"; OT_FAIL; }
12644  if (THE_PURSE.empty()) {
12645  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12646  OT_FAIL;
12647  }
12648  if (THE_TOKEN.empty()) {
12649  otErr << __FUNCTION__ << ": Null: THE_TOKEN passed in!\n";
12650  OT_FAIL;
12651  }
12652 
12653  std::string strFunc = __FUNCTION__; //"OTAPI_Exec::Purse_Push";
12654  const OTString strReason("Pushing a token onto a cash purse.");
12655  OTPasswordData thePWData(strReason);
12656  const bool& bDoesOwnerIDExist =
12657  (("" != OWNER_ID) && ('\0' != OWNER_ID[0])); // If bDoesOwnerIDExist is
12658  // not true, then the purse
12659  // MUST be
12660  // password-protected.
12661  OTIdentifier theOwnerID;
12662  if (bDoesOwnerIDExist) {
12663  const OTString strOwnerID(OWNER_ID);
12664  OTPseudonym* pOwnerNym = nullptr;
12665  if (strOwnerID.Exists()) {
12666  theOwnerID.SetString(strOwnerID);
12667  pOwnerNym = OTAPI()->GetOrLoadNym(
12668  theOwnerID, false, strFunc.c_str(),
12669  &thePWData); // These copiously log, and ASSERT.
12670  }
12671  if (nullptr == pOwnerNym) return "";
12672  }
12673  // By this point, pOwnerNym is a good pointer, and is on the wallet. (No
12674  // need to cleanup.)
12675  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID);
12676  const OTString strPurse(THE_PURSE), strToken(THE_TOKEN);
12677  std::unique_ptr<Purse> pPurse(OTAPI()->Purse_Push(
12678  theServerID, theAssetTypeID, strPurse, strToken,
12679  bDoesOwnerIDExist ? &theOwnerID : nullptr, // Note: if the purse is
12680  // password-protected, then this
12681  // parameter should be "".
12682  &strReason));
12683  if (nullptr != pPurse) {
12684  const OTIdentifier theSignerID(SIGNER_ID);
12685  OTPseudonym* pSignerNym = OTAPI()->GetOrLoadPrivateNym(
12686  theSignerID, false, strFunc.c_str(),
12687  &thePWData); // These copiously log, and ASSERT.
12688  if (nullptr == pSignerNym) return "";
12689  // By this point, pSignerNym is a good pointer, and is on the wallet.
12690  // (No need to cleanup.)
12691  pPurse->ReleaseSignatures();
12692  pPurse->SignContract(*pSignerNym, &thePWData);
12693  pPurse->SaveContract();
12694 
12695  pPurse->SaveContractRaw(strOutput);
12696  std::string pBuf = strOutput.Get();
12697 
12698  return pBuf;
12699  }
12700  else
12701  otOut << strFunc << ": Failed pushing a token onto a cash purse.\n";
12702 
12703  return "";
12704 }
12705 
12706 //
12707 // Returns bool
12708 // Should handle duplicates. Should load, merge, and save.
12709 //
12710 bool OTAPI_Exec::Wallet_ImportPurse(const std::string& SERVER_ID,
12711  const std::string& ASSET_TYPE_ID,
12712  const std::string& USER_ID,
12713  const std::string& THE_PURSE) const
12714 {
12715  if (SERVER_ID.empty()) {
12716  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12717  OT_FAIL;
12718  }
12719  if (ASSET_TYPE_ID.empty()) {
12720  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12721  OT_FAIL;
12722  }
12723  if (USER_ID.empty()) {
12724  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
12725  OT_FAIL;
12726  }
12727  if (THE_PURSE.empty()) {
12728  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12729  OT_FAIL;
12730  }
12731 
12732  OTString strReason("Importing a cash purse into the wallet.");
12733  // OTPasswordData thePWData(strReason);
12734  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID),
12735  theUserID(USER_ID);
12736  const OTString strNewPurse(THE_PURSE);
12737  // THE_PURSE (the new purse) either is for a Nym, or a Symmetric Key.
12738  // If it's for a Nym, it either has a NymID, or the ID is left blank.
12739  //
12740  // This call already logs on failure, so I won't bother logging again here.
12741  //
12742  OTString strDisplay("");
12743 
12744  const bool& bImported = OTAPI()->Wallet_ImportPurse(
12745  theServerID, theAssetTypeID, theUserID, strNewPurse, &strDisplay);
12746  return bImported ? true : false;
12747 }
12748 
12749 // TODO:!!!!! NEW!!!!!
12750 
12751 // Messages the server. If failure, make sure you didn't lose that purse!!
12752 // If success, the new tokens will be returned shortly and saved into the
12753 // appropriate purse.
12754 // Note that an asset account isn't necessary to do this... just a nym operating
12755 // cash-only.
12756 // The same as exchanging a 20-dollar bill at the teller window for a
12757 // replacement bill.
12758 //
12759 // You could also have a webpage operated by the transaction server, where a
12760 // dummy nym
12761 // performs cash exchanges using a single page with a text area (for copying and
12762 // pasting
12763 // cash tokens.) This way all cash token exchanges can go through the same Nym.
12764 // (Although
12765 // it must be stressed, that the cash is untraceable whether you use your own
12766 // Nym or not.)
12767 //
12768 // Returns int32_t:
12769 // -1 means error; no message was sent.
12770 // -2 means the message was sent, but the request number must be passed as a
12771 // string, so call OTAPI_Exec::GetLargeRequestNum.
12772 // 0 means NO error, but also: no message was sent.
12773 // >0 means NO error, and the message was sent, and the request number fits into
12774 // an integer...
12775 // ...and in fact the requestNum IS the return value!
12776 // ===> In 99% of cases, this LAST option is what actually happens!!
12777 //
12778 int32_t OTAPI_Exec::exchangePurse(const std::string& SERVER_ID,
12779  const std::string& ASSET_TYPE_ID,
12780  const std::string& USER_ID,
12781  const std::string& THE_PURSE) const
12782 {
12783  if (SERVER_ID.empty()) {
12784  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12785  OT_FAIL;
12786  }
12787  if (ASSET_TYPE_ID.empty()) {
12788  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12789  OT_FAIL;
12790  }
12791  if (USER_ID.empty()) {
12792  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
12793  OT_FAIL;
12794  }
12795  if (THE_PURSE.empty()) {
12796  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
12797  OT_FAIL;
12798  }
12799 
12800  // todo: exchange message.
12801  otErr << __FUNCTION__
12802  << ": TODO (NOT CODED YET) OTAPI_Exec::exchangePurse: SERVER_ID: "
12803  << SERVER_ID << "\n ASSET_TYPE_ID: " << ASSET_TYPE_ID
12804  << "\n USER_ID: " << USER_ID << "\n ";
12805 
12806  return -1;
12807 }
12808 
12809 // the GUI needs to be able to export cash from one Nym to another,
12810 // so a function has been provided for doing so to the actual Token IDs (not
12811 // just the purse.
12812 // Understand that even when you decrypt a token out of a purse, the token ID
12813 // itself is still
12814 // encrypted within that token. That is what this function is for.
12815 //
12816 // returns: the updated token itself in string form.
12817 //
12818 
12819 //
12820 // ALLOW the caller to pass a symmetric key here, instead of either Nym ID.
12821 // We'll load it up and use it instead of a Nym. Update: make that a purse.
12822 // These tokens already beint64_t to specific purses, so just pass the purse
12823 // here
12824 //
12825 // Done: Also, add a key cache with a timeout (similar to Master Key) where we
12826 // can stash
12827 // any already-loaded symmetric keys, and a thread wipes them out later. That
12828 // way
12829 // even if we have to load the key each time this func is called, we still avoid
12830 // the
12831 // user having to enter the passphrase more than once per timeout period.
12832 //
12833 // Done also: allow a "Signer ID" to be passed in here, since either Nym could
12834 // potentially
12835 // now be a symmetric key.
12836 
12838  const std::string& SERVER_ID, const std::string& ASSET_TYPE_ID,
12839  const std::string& THE_TOKEN, const std::string& SIGNER_NYM_ID,
12840  const std::string& OLD_OWNER, // Pass a NymID here, or a purse.
12841  const std::string& NEW_OWNER) const // Pass a NymID here, or a purse.
12842 {
12843  if (SERVER_ID.empty()) {
12844  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12845  OT_FAIL;
12846  }
12847  if (ASSET_TYPE_ID.empty()) {
12848  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12849  OT_FAIL;
12850  }
12851  if (THE_TOKEN.empty()) {
12852  otErr << __FUNCTION__ << ": Null: THE_TOKEN passed in!\n";
12853  OT_FAIL;
12854  }
12855  if (SIGNER_NYM_ID.empty()) {
12856  otErr << __FUNCTION__ << ": Null: SIGNER_NYM_ID passed in!\n";
12857  OT_FAIL;
12858  }
12859  if (OLD_OWNER.empty()) {
12860  otErr << __FUNCTION__ << ": Null: OLD_OWNER passed in!\n";
12861  OT_FAIL;
12862  }
12863  if (NEW_OWNER.empty()) {
12864  otErr << __FUNCTION__ << ": Null: NEW_OWNER passed in!\n";
12865  OT_FAIL;
12866  }
12867 
12868  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID),
12869  theSignerNymID(SIGNER_NYM_ID);
12870  const OTString strOldOwner(OLD_OWNER), // Either of these MIGHT contain a
12871  // Nym ID, OR might contain a
12872  // purse...
12873  strNewOwner(NEW_OWNER); // (purse is passed in cases where the token is
12874  // encrypted with a passphrase aka symmetric
12875  // crypto, versus being encrypted to a Nym's
12876  // public key.)
12877  OTString strToken(THE_TOKEN);
12878  std::unique_ptr<Token> pToken(OTAPI()->Token_ChangeOwner(
12879  theServerID, theAssetTypeID, strToken, theSignerNymID,
12880  strOldOwner, // Pass a NymID here as a string, or a purse. (IF
12881  // symmetrically encrypted, the relevant key is in the
12882  // purse.)
12883  strNewOwner)); // Pass a NymID here as a string, or a purse. (IF
12884  // symmetrically encrypted, the relevant key is in the
12885  // purse.)
12886  if (nullptr != pToken) // Success!
12887  {
12888  const OTString strOutput(*pToken);
12889 
12890  std::string pBuf = strOutput.Get();
12891 
12892  return pBuf;
12893  }
12894 
12895  return "";
12896 }
12897 
12898 // Returns an encrypted form of the actual blinded token ID.
12899 // (There's no need to decrypt the ID until redeeming the token, when
12900 // you re-encrypt it to the server's public key, or until spending it,
12901 // when you re-encrypt it to the recipient's public key, or exporting
12902 // it, when you create a dummy recipient and attach it to the purse.)
12903 //
12904 std::string OTAPI_Exec::Token_GetID(const std::string& SERVER_ID,
12905  const std::string& ASSET_TYPE_ID,
12906  const std::string& THE_TOKEN) const
12907 {
12908  if (SERVER_ID.empty()) {
12909  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12910  OT_FAIL;
12911  }
12912  if (ASSET_TYPE_ID.empty()) {
12913  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12914  OT_FAIL;
12915  }
12916  if (THE_TOKEN.empty()) {
12917  otErr << __FUNCTION__ << ": Null: THE_TOKEN passed in!\n";
12918  OT_FAIL;
12919  }
12920 
12921  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID);
12922 
12923  OTString strOutput("0");
12924 
12925  OTString strToken(THE_TOKEN);
12926  std::unique_ptr<Token> pToken(
12927  Token::TokenFactory(strToken, theServerID, theAssetTypeID));
12928 
12929  if (nullptr != pToken) // TokenFactory instantiates AND loads from string.
12930  {
12931  const OTASCIIArmor& ascSpendable =
12932  pToken->GetSpendable(); // encrypted version of Token ID, used as an
12933  // "ID" on client side.
12934 
12935  strOutput.Format("%s", ascSpendable.Get());
12936  }
12937 
12938  std::string pBuf = strOutput.Get();
12939 
12940  return pBuf;
12941 }
12942 
12943 // The actual cash value of the token. Returns a int64_t int32_t as a string.
12944 //
12945 int64_t OTAPI_Exec::Token_GetDenomination(const std::string& SERVER_ID,
12946  const std::string& ASSET_TYPE_ID,
12947  const std::string& THE_TOKEN) const
12948 {
12949  if (SERVER_ID.empty()) {
12950  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12951  OT_FAIL;
12952  }
12953  if (ASSET_TYPE_ID.empty()) {
12954  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12955  OT_FAIL;
12956  }
12957  if (THE_TOKEN.empty()) {
12958  otErr << __FUNCTION__ << ": Null: THE_TOKEN passed in!\n";
12959  OT_FAIL;
12960  }
12961 
12962  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID);
12963 
12964  OTString strOutput("0");
12965 
12966  OTString strToken(THE_TOKEN);
12967  std::unique_ptr<Token> pToken(
12968  Token::TokenFactory(strToken, theServerID, theAssetTypeID));
12969 
12970  if (nullptr != pToken) // TokenFactory instantiates AND loads from string.
12971  {
12972  return pToken->GetDenomination();
12973  }
12974  else
12975  return -1;
12976 }
12977 
12978 // OTAPI_Exec::Token_GetSeries
12979 // Returns -1 for error.
12980 // Otherwise returns the series number of this token. (Int.)
12981 //
12982 int32_t OTAPI_Exec::Token_GetSeries(const std::string& SERVER_ID,
12983  const std::string& ASSET_TYPE_ID,
12984  const std::string& THE_TOKEN) const
12985 {
12986  if (SERVER_ID.empty()) {
12987  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
12988  OT_FAIL;
12989  }
12990  if (ASSET_TYPE_ID.empty()) {
12991  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
12992  OT_FAIL;
12993  }
12994  if (THE_TOKEN.empty()) {
12995  otErr << __FUNCTION__ << ": Null: THE_TOKEN passed in!\n";
12996  OT_FAIL;
12997  }
12998 
12999  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID);
13000 
13001  OTString strOutput;
13002 
13003  OTString strToken(THE_TOKEN);
13004  std::unique_ptr<Token> pToken(
13005  Token::TokenFactory(strToken, theServerID, theAssetTypeID));
13006 
13007  if (nullptr != pToken) // TokenFactory instantiates AND loads from string.
13008  return pToken->GetSeries();
13009 
13010  return -1;
13011 }
13012 
13013 // the date is seconds since Jan 1970, but returned as a string.
13014 //
13015 time64_t OTAPI_Exec::Token_GetValidFrom(const std::string& SERVER_ID,
13016  const std::string& ASSET_TYPE_ID,
13017  const std::string& THE_TOKEN) const
13018 {
13019  if (SERVER_ID.empty()) {
13020  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13021  OT_FAIL;
13022  }
13023  if (ASSET_TYPE_ID.empty()) {
13024  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
13025  OT_FAIL;
13026  }
13027  if (THE_TOKEN.empty()) {
13028  otErr << __FUNCTION__ << ": Null: THE_TOKEN passed in!\n";
13029  OT_FAIL;
13030  }
13031 
13032  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID);
13033 
13034  OTString strOutput;
13035 
13036  OTString strToken(THE_TOKEN);
13037  std::unique_ptr<Token> pToken(
13038  Token::TokenFactory(strToken, theServerID, theAssetTypeID));
13039 
13040  if (nullptr != pToken) // TokenFactory instantiates AND loads from string.
13041  {
13042  return pToken->GetValidFrom();
13043  }
13044  return OTTimeGetTimeFromSeconds(-1);
13045 }
13046 
13047 // the date is seconds since Jan 1970, but returned as a string.
13048 //
13049 time64_t OTAPI_Exec::Token_GetValidTo(const std::string& SERVER_ID,
13050  const std::string& ASSET_TYPE_ID,
13051  const std::string& THE_TOKEN) const
13052 {
13053  if (SERVER_ID.empty()) {
13054  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13055  OT_FAIL;
13056  }
13057  if (ASSET_TYPE_ID.empty()) {
13058  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
13059  OT_FAIL;
13060  }
13061  if (THE_TOKEN.empty()) {
13062  otErr << __FUNCTION__ << ": Null: THE_TOKEN passed in!\n";
13063  OT_FAIL;
13064  }
13065 
13066  const OTIdentifier theServerID(SERVER_ID), theAssetTypeID(ASSET_TYPE_ID);
13067 
13068  OTString strOutput;
13069 
13070  OTString strToken(THE_TOKEN);
13071  std::unique_ptr<Token> pToken(
13072  Token::TokenFactory(strToken, theServerID, theAssetTypeID));
13073 
13074  if (nullptr != pToken) // TokenFactory instantiates AND loads from string.
13075  {
13076  return pToken->GetValidTo();
13077  }
13078  return OTTimeGetTimeFromSeconds(-1);
13079 }
13080 
13081 std::string OTAPI_Exec::Token_GetAssetID(const std::string& THE_TOKEN) const
13082 {
13083  if (THE_TOKEN.empty()) {
13084  otErr << __FUNCTION__ << ": Null: THE_TOKEN passed in!\n";
13085  OT_FAIL;
13086  }
13087 
13088  OTString strOutput;
13089 
13090  OTString strToken(THE_TOKEN);
13091  std::unique_ptr<Token> pToken(Token::TokenFactory(strToken));
13092 
13093  if (nullptr != pToken) // TokenFactory instantiates AND loads from string.
13094  {
13095  const OTIdentifier& theID = pToken->GetAssetID();
13096  theID.GetString(strOutput);
13097  }
13098 
13099  std::string pBuf = strOutput.Get();
13100 
13101  return pBuf;
13102 }
13103 
13104 std::string OTAPI_Exec::Token_GetServerID(const std::string& THE_TOKEN) const
13105 {
13106  if (THE_TOKEN.empty()) {
13107  otErr << __FUNCTION__ << ": Null: THE_TOKEN passed in!\n";
13108  OT_FAIL;
13109  }
13110 
13111  OTString strOutput;
13112 
13113  OTString strToken(THE_TOKEN);
13114  std::unique_ptr<Token> pToken(Token::TokenFactory(strToken));
13115 
13116  if (nullptr != pToken) // TokenFactory instantiates AND loads from string.
13117  {
13118  const OTIdentifier& theID = pToken->GetServerID();
13119  theID.GetString(strOutput);
13120  }
13121 
13122  std::string pBuf = strOutput.Get();
13123 
13124  return pBuf;
13125 }
13126 
13127 // IS BASKET CURRENCY ?
13128 //
13129 // Tells you whether or not a given asset type is actually a basket currency.
13130 //
13131 // returns bool (true or false aka 1 or 0.)
13132 //
13133 bool OTAPI_Exec::IsBasketCurrency(const std::string& ASSET_TYPE_ID) const
13134 {
13135  if (ASSET_TYPE_ID.empty()) {
13136  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
13137  OT_FAIL;
13138  }
13139 
13140  const OTIdentifier theAssetTypeID(ASSET_TYPE_ID);
13141 
13142  if (OTAPI()->IsBasketCurrency(theAssetTypeID))
13143  return true;
13144  else
13145  return false;
13146 }
13147 
13148 // Get Basket Count (of backing asset types.)
13149 //
13150 // Returns the number of asset types that make up this basket.
13151 // (Or zero.)
13152 //
13154  const std::string& ASSET_TYPE_ID) const
13155 {
13156  if (ASSET_TYPE_ID.empty()) {
13157  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
13158  OT_FAIL;
13159  }
13160 
13161  const OTIdentifier theAssetTypeID(ASSET_TYPE_ID);
13162 
13163  return OTAPI()->GetBasketMemberCount(theAssetTypeID);
13164 }
13165 
13166 // Get Asset Type of a basket's member currency, by index.
13167 //
13168 // (Returns a string containing Asset Type ID, or "").
13169 //
13171  const std::string& BASKET_ASSET_TYPE_ID, const int32_t& nIndex) const
13172 {
13173  if (BASKET_ASSET_TYPE_ID.empty()) {
13174  otErr << __FUNCTION__ << ": Null: BASKET_ASSET_TYPE_ID passed in!\n";
13175  OT_FAIL;
13176  }
13177 
13178  if (0 > nIndex) {
13179  otErr << __FUNCTION__
13180  << ": nIndex is out of bounds (it's in the negative!)\n";
13181  OT_FAIL;
13182  }
13183 
13184  const OTIdentifier theAssetTypeID(BASKET_ASSET_TYPE_ID);
13185 
13186  OTIdentifier theOutputMemberType;
13187 
13188  bool bGotType = OTAPI()->GetBasketMemberType(theAssetTypeID, nIndex,
13189  theOutputMemberType);
13190  if (!bGotType) return "";
13191 
13192  OTString strOutput(theOutputMemberType);
13193 
13194  std::string pBuf = strOutput.Get();
13195 
13196  return pBuf;
13197 }
13198 
13199 // GET BASKET MINIMUM TRANSFER AMOUNT
13200 //
13201 // Returns a int64_t (as string) containing the minimum transfer
13202 // amount for the entire basket.
13203 //
13204 // FOR EXAMPLE:
13205 // If the basket is defined as 10 Rands == 2 Silver, 5 Gold, 8 Euro,
13206 // then the minimum transfer amount for the basket is 10. This function
13207 // would return a string containing "10", in that example.
13208 //
13210  const std::string& BASKET_ASSET_TYPE_ID) const
13211 {
13212  if (BASKET_ASSET_TYPE_ID.empty()) {
13213  otErr << __FUNCTION__ << ": Null: BASKET_ASSET_TYPE_ID passed in!\n";
13214  OT_FAIL;
13215  }
13216 
13217  const OTIdentifier theAssetTypeID(BASKET_ASSET_TYPE_ID);
13218 
13219  int64_t lMinTransAmount =
13220  OTAPI()->GetBasketMinimumTransferAmount(theAssetTypeID);
13221 
13222  if (0 >= lMinTransAmount) {
13223  otErr
13224  << __FUNCTION__
13225  << ": returned 0 (or negitive). Strange... what basket is this?\n";
13226  return OT_ERROR_AMOUNT;
13227  }
13228 
13229  return lMinTransAmount;
13230 }
13231 
13232 // GET BASKET MEMBER's MINIMUM TRANSFER AMOUNT
13233 //
13234 // Returns a int64_t (as string) containing the minimum transfer
13235 // amount for one of the member currencies in the basket.
13236 //
13237 // FOR EXAMPLE:
13238 // If the basket is defined as 10 Rands == 2 Silver, 5 Gold, 8 Euro,
13239 // then the minimum transfer amount for the member currency at index
13240 // 0 is 2, the minimum transfer amount for the member currency at
13241 // index 1 is 5, and the minimum transfer amount for the member
13242 // currency at index 2 is 8.
13243 //
13245  const std::string& BASKET_ASSET_TYPE_ID, const int32_t& nIndex) const
13246 {
13247  if (BASKET_ASSET_TYPE_ID.empty()) {
13248  otErr << __FUNCTION__ << ": Null: BASKET_ASSET_TYPE_ID passed in!\n";
13249  OT_FAIL;
13250  }
13251 
13252  if (0 > nIndex) {
13253  otErr << __FUNCTION__
13254  << ": nIndex is out of bounds (it's in the negative!)\n";
13255  OT_FAIL;
13256  }
13257 
13258  const OTIdentifier theAssetTypeID(BASKET_ASSET_TYPE_ID);
13259 
13260  int64_t lMinTransAmount =
13261  OTAPI()->GetBasketMemberMinimumTransferAmount(theAssetTypeID, nIndex);
13262 
13263  if (0 >= lMinTransAmount) {
13264  otErr
13265  << __FUNCTION__
13266  << ": returned 0 (or negitive). Strange... what basket is this?\n";
13267  return OT_ERROR_AMOUNT;
13268  }
13269 
13270  return lMinTransAmount;
13271 }
13272 
13273 // MESSAGES BEING SENT TO THE SERVER:
13274 
13275 // Returns int32_t:
13276 // -1 means error; no message was sent.
13277 // -2 means the message was sent, but the request number must be passed as a
13278 // string, so call OTAPI_Exec::GetLargeRequestNum.
13279 // 0 means NO error, but also: no message was sent.
13280 // >0 means NO error, and the message was sent, and the request number fits into
13281 // an integer...
13282 // ...and in fact the requestNum IS the return value!
13283 // ===> In 99% of cases, this LAST option is what actually happens!!
13284 //
13285 int32_t OTAPI_Exec::checkServerID(const std::string& SERVER_ID,
13286  const std::string& USER_ID) const
13287 {
13288  if (SERVER_ID.empty()) {
13289  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13290  OT_FAIL;
13291  }
13292  if (USER_ID.empty()) {
13293  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13294  OT_FAIL;
13295  }
13296 
13297  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
13298 
13299  return OTAPI()->checkServerID(theServerID, theUserID);
13300 }
13301 
13302 // Returns int32_t:
13303 // -1 means error; no message was sent.
13304 // -2 means the message was sent, but the request number must be passed as a
13305 // string, so call OTAPI_Exec::GetLargeRequestNum.
13306 // 0 means NO error, but also: no message was sent.
13307 // >0 means NO error, and the message was sent, and the request number fits into
13308 // an integer...
13309 // ...and in fact the requestNum IS the return value!
13310 // ===> In 99% of cases, this LAST option is what actually happens!!
13311 //
13312 int32_t OTAPI_Exec::createUserAccount(const std::string& SERVER_ID,
13313  const std::string& USER_ID) const
13314 {
13315  if (SERVER_ID.empty()) {
13316  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13317  OT_FAIL;
13318  }
13319  if (USER_ID.empty()) {
13320  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13321  OT_FAIL;
13322  }
13323 
13324  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
13325 
13326  return OTAPI()->createUserAccount(theServerID, theUserID);
13327 }
13328 
13329 // Returns int32_t:
13330 // -1 means error; no message was sent.
13331 // -2 means the message was sent, but the request number must be passed as a
13332 // string, so call OTAPI_Exec::GetLargeRequestNum.
13333 // 0 means NO error, but also: no message was sent.
13334 // >0 means NO error, and the message was sent, and the request number fits into
13335 // an integer...
13336 // ...and in fact the requestNum IS the return value!
13337 // ===> In 99% of cases, this LAST option is what actually happens!!
13338 //
13339 int32_t OTAPI_Exec::deleteUserAccount(const std::string& SERVER_ID,
13340  const std::string& USER_ID) const
13341 {
13342  if (SERVER_ID.empty()) {
13343  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13344  OT_FAIL;
13345  }
13346  if (USER_ID.empty()) {
13347  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13348  OT_FAIL;
13349  }
13350 
13351  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
13352 
13353  return OTAPI()->deleteUserAccount(theServerID, theUserID);
13354 }
13355 
13356 // If THE_MESSAGE is of command type @usageCredits, and IF it was a SUCCESS,
13357 // then this function returns the usage credits BALANCE (it's a int64_t int32_t,
13358 // but
13359 // passed as a string). If you adjusted the balance using the usageCredits
13360 // message (THE_MESSAGE being the server's reply to that) then you will see
13361 // the balance AFTER the adjustment. (The "Current" Usage Credits balance.)
13362 //
13363 // UPDATE: Notice that we now return -2 in the case of all errors.
13364 // This is because the lowest possible actual value is -1.
13365 //
13366 // - Basically a 0 or positive value means that usage credits are
13367 // actually turned on (on the server side) and that you are seeing
13368 // the actual usage credits value for that Nym.
13369 //
13370 // - Whereas a -2 value means there was an error.
13371 //
13372 // - Whereas a -1 value means that usage credits are turned off (on
13373 // the server side) OR that the Nym has been given the special -1
13374 // setting for usage credits, which enables him to operate as if he
13375 // has unlimited usage credits.
13376 //
13378  const std::string& THE_MESSAGE) const
13379 {
13380  if (THE_MESSAGE.empty()) {
13381  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
13382  OT_FAIL;
13383  }
13384 
13385  OTString strMessage(THE_MESSAGE);
13386  OTMessage theMessage;
13387 
13388  if (!strMessage.Exists()) {
13389  otErr << __FUNCTION__ << ": Error: THE_MESSAGE doesn't exist.\n";
13390  return -2;
13391  }
13392 
13393  if (!theMessage.LoadContractFromString(strMessage)) {
13394  otErr << __FUNCTION__ << ": Failed loading message from string.\n";
13395  return -2;
13396  }
13397 
13398  if (!theMessage.m_bSuccess) {
13399  otErr << __FUNCTION__ << ": Message success == false, thus unable to "
13400  "report Usage Credits balance. (Returning "
13401  "-2.)\n";
13402  return -2;
13403  }
13404 
13405  if (!theMessage.m_strCommand.Compare("@usageCredits")) {
13406  otErr << __FUNCTION__ << ": THE_MESSAGE is supposed to be of command "
13407  "type \"@usageCredits\", but instead it's a: "
13408  << theMessage.m_strCommand << "\n (Failure. Returning -2.)";
13409  return -2;
13410  }
13411 
13412  // By this point, we know the message was a successful @usageCredits, loaded
13413  // properly from the string that was passed in. Let's return the usage
13414  // credits
13415  // balance (a int64_t int32_t, returned in string format.)
13416 
13417  return theMessage.m_lDepth;
13418 }
13419 
13420 // Returns int32_t:
13421 // -1 means error; no message was sent.
13422 // -2 means the message was sent, but the request number must be passed as a
13423 // string, so call OTAPI_Exec::GetLargeRequestNum.
13424 // 0 means NO error, but also: no message was sent.
13425 // >0 means NO error, and the message was sent, and the request number fits into
13426 // an integer...
13427 // ...and in fact the requestNum IS the return value!
13428 // ===> In 99% of cases, this LAST option is what actually happens!!
13429 //
13430 int32_t OTAPI_Exec::usageCredits(const std::string& SERVER_ID,
13431  const std::string& USER_ID,
13432  const std::string& USER_ID_CHECK,
13433  const int64_t& ADJUSTMENT) const // can be "0",
13434  // or
13435 // "", if you just
13436 // want to check the
13437 // current balance
13438 // without adjusting
13439 // it.
13440 {
13441  if (SERVER_ID.empty()) {
13442  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13443  OT_FAIL;
13444  }
13445  if (USER_ID.empty()) {
13446  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13447  OT_FAIL;
13448  }
13449  if (USER_ID_CHECK.empty()) {
13450  otErr << __FUNCTION__ << ": Null: USER_ID_CHECK passed in!\n";
13451  OT_FAIL;
13452  }
13453 
13454  // OT_ASSERT_MSG("" != ADJUSTMENT, "OTAPI_Exec::usageCredits: Null
13455  // ADJUSTMENT passed in."); // "" is allowed here.
13456 
13457  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
13458  theOtherUserID(USER_ID_CHECK);
13459 
13460  const int64_t lAdjustment = ADJUSTMENT; // "" resolves as 0.
13461 
13462  return OTAPI()->usageCredits(theServerID, theUserID, theOtherUserID,
13463  static_cast<int64_t>(lAdjustment));
13464 }
13465 
13466 // Returns int32_t:
13467 // -1 means error; no message was sent.
13468 // -2 means the message was sent, but the request number must be passed as a
13469 // string, so call OTAPI_Exec::GetLargeRequestNum.
13470 // 0 means NO error, but also: no message was sent.
13471 // >0 means NO error, and the message was sent, and the request number fits into
13472 // an integer...
13473 // ...and in fact the requestNum IS the return value!
13474 // ===> In 99% of cases, this LAST option is what actually happens!!
13475 //
13476 int32_t OTAPI_Exec::checkUser(const std::string& SERVER_ID,
13477  const std::string& USER_ID,
13478  const std::string& USER_ID_CHECK) const
13479 {
13480  if (SERVER_ID.empty()) {
13481  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13482  OT_FAIL;
13483  }
13484  if (USER_ID.empty()) {
13485  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13486  OT_FAIL;
13487  }
13488  if (USER_ID_CHECK.empty()) {
13489  otErr << __FUNCTION__ << ": Null: USER_ID_CHECK passed in!\n";
13490  OT_FAIL;
13491  }
13492 
13493  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
13494  theOtherUserID(USER_ID_CHECK);
13495 
13496  return OTAPI()->checkUser(theServerID, theUserID, theOtherUserID);
13497 }
13498 
13499 // Returns int32_t:
13500 // -1 means error; no message was sent.
13501 // -2 means the message was sent, but the request number must be passed as a
13502 // string, so call OTAPI_Exec::GetLargeRequestNum.
13503 // 0 means NO error, but also: no message was sent.
13504 // >0 means NO error, and the message was sent, and the request number fits into
13505 // an integer...
13506 // ...and in fact the requestNum IS the return value!
13507 // ===> In 99% of cases, this LAST option is what actually happens!!
13508 //
13509 int32_t OTAPI_Exec::sendUserMessage(const std::string& SERVER_ID,
13510  const std::string& USER_ID,
13511  const std::string& USER_ID_RECIPIENT,
13512  const std::string& RECIPIENT_PUBKEY,
13513  const std::string& THE_MESSAGE) const
13514 {
13515  if (SERVER_ID.empty()) {
13516  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13517  OT_FAIL;
13518  }
13519  if (USER_ID.empty()) {
13520  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13521  OT_FAIL;
13522  }
13523  if (USER_ID_RECIPIENT.empty()) {
13524  otErr << __FUNCTION__ << ": Null: USER_ID_RECIPIENT passed in!\n";
13525  OT_FAIL;
13526  }
13527  if (RECIPIENT_PUBKEY.empty()) {
13528  otErr << __FUNCTION__ << ": Null: RECIPIENT_PUBKEY passed in!\n";
13529  OT_FAIL;
13530  }
13531  if (THE_MESSAGE.empty()) {
13532  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
13533  OT_FAIL;
13534  }
13535 
13536  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
13537  theOtherUserID(USER_ID_RECIPIENT);
13538  OTString strRecipPubkey(RECIPIENT_PUBKEY);
13539  OTString strMessage(THE_MESSAGE);
13540 
13541  return OTAPI()->sendUserMessage(theServerID, theUserID, theOtherUserID,
13542  strRecipPubkey, strMessage);
13543 }
13544 
13545 // Returns int32_t:
13546 // -1 means error; no message was sent.
13547 // -2 means the message was sent, but the request number must be passed as a
13548 // string, so call OTAPI_Exec::GetLargeRequestNum.
13549 // 0 means NO error, but also: no message was sent.
13550 // >0 means NO error, and the message was sent, and the request number fits into
13551 // an integer...
13552 // ...and in fact the requestNum IS the return value!
13553 // ===> In 99% of cases, this LAST option is what actually happens!!
13554 //
13556  const std::string& SERVER_ID, const std::string& USER_ID,
13557  const std::string& USER_ID_RECIPIENT, const std::string& RECIPIENT_PUBKEY,
13558  const std::string& THE_INSTRUMENT,
13559  const std::string& INSTRUMENT_FOR_SENDER) const // Can be empty. Special
13560  // version
13561 // for the sender's outpayments
13562 // box. Only used for cash:
13563 // THE_INSTRUMENT contains tokens
13564 // already encrypted to the
13565 // recipient's key. So this
13566 // version contains tokens
13567 // encrypted to the sender's key
13568 // instead.
13569 {
13570  if (SERVER_ID.empty()) {
13571  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13572  OT_FAIL;
13573  }
13574  if (USER_ID.empty()) {
13575  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13576  OT_FAIL;
13577  }
13578  if (USER_ID_RECIPIENT.empty()) {
13579  otErr << __FUNCTION__ << ": Null: USER_ID_RECIPIENT passed in!\n";
13580  OT_FAIL;
13581  }
13582  if (RECIPIENT_PUBKEY.empty()) {
13583  otErr << __FUNCTION__ << ": Null: RECIPIENT_PUBKEY passed in!\n";
13584  OT_FAIL;
13585  }
13586  if (THE_INSTRUMENT.empty()) {
13587  otErr << __FUNCTION__ << ": Null: THE_INSTRUMENT passed in!\n";
13588  OT_FAIL;
13589  }
13590  // if (INSTRUMENT_FOR_SENDER.empty()) { otErr << __FUNCTION__ << ": Null:
13591  // " << "INSTRUMENT_FOR_SENDER" << "
13592  // passed in!\n"; OT_FAIL; }
13593  // (INSTRUMENT_FOR_SENDER is optional, so we allow it to be empty.)
13594 
13595  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
13596  theOtherUserID(USER_ID_RECIPIENT);
13597  OTString strRecipPubkey(RECIPIENT_PUBKEY), strInstrument(THE_INSTRUMENT);
13598  // Note: this was removed and can be deleted from the code.
13599  //
13600  // Why? Because we pass the string version of the public key,
13601  // not the OTASCIIArmor version. The bookends are passed intact
13602  // into the OpenSSL call since the key is expected that way.
13603  // Whereas loading it into ascii-armor is just going to strip off
13604  // the bookends and pass the raw base64-encoded pubkey to OpenSSL
13605  // which is NOT what OpenSSL is expecting. FYI.
13606  //
13607  // Todo, security: Should we do this anyway, just purely for validation
13608  // purposes?
13609  //
13610  // OTASCIIArmor ascRecipPubkey;
13611  // const bool bLoadedArmor = OTASCIIArmor::LoadFromString(ascRecipPubkey,
13612  // strRecipPubkey); // str_bookend="-----BEGIN" by default
13613  //
13614  // if (!bLoadedArmor || !ascRecipPubkey.Exists())
13615  // {
13616  // otErr << __FUNCTION__ << ": Failure loading string into OTASCIIArmor
13617  // object:\n\n" << strRecipPubkey << "\n\n";
13618  // return OT_ERROR;
13619  // }
13620  OTPayment thePayment(strInstrument);
13621 
13622  if (!thePayment.IsValid() || !thePayment.SetTempValues()) {
13623  otOut << __FUNCTION__ << ": Failure loading payment instrument "
13624  "(intended for recipient) from string:\n\n"
13625  << strInstrument << "\n\n";
13626  return OT_ERROR;
13627  }
13628  const bool bSenderCopyIncluded = (INSTRUMENT_FOR_SENDER.size() > 0);
13629 
13630  if (bSenderCopyIncluded) {
13631  OTString strInstrumentForSender(INSTRUMENT_FOR_SENDER);
13632  OTPayment theSenderPayment(strInstrumentForSender);
13633 
13634  if (!theSenderPayment.IsValid() || !theSenderPayment.SetTempValues()) {
13635  otOut << __FUNCTION__
13636  << ": Failure loading payment instrument (copy intended for "
13637  "sender's records) from string:\n\n"
13638  << strInstrumentForSender << "\n\n";
13639  return OT_ERROR;
13640  }
13641  return OTAPI()->sendUserInstrument(theServerID, theUserID,
13642  theOtherUserID, strRecipPubkey,
13643  thePayment, &theSenderPayment);
13644  }
13645  return OTAPI()->sendUserInstrument(theServerID, theUserID, theOtherUserID,
13646  strRecipPubkey, thePayment);
13647 }
13648 
13649 // Returns int32_t:
13650 // -1 means error; no message was sent.
13651 // 0 means NO error, but also: no message was sent.
13652 // 1 means the "getRequest" message was successfully SENT.
13653 //
13654 int32_t OTAPI_Exec::getRequest(const std::string& SERVER_ID,
13655  const std::string& USER_ID) const
13656 {
13657  if (SERVER_ID.empty()) {
13658  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13659  OT_FAIL;
13660  }
13661  if (USER_ID.empty()) {
13662  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13663  OT_FAIL;
13664  }
13665 
13666  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
13667 
13668  return OTAPI()->getRequest(theServerID, theUserID);
13669 }
13670 
13671 // Returns int32_t:
13672 // -1 means error; no message was sent.
13673 // -2 means the message was sent, but the request number must be passed as a
13674 // string, so call OTAPI_Exec::GetLargeRequestNum.
13675 // 0 means NO error, but also: no message was sent.
13676 // >0 means NO error, and the message was sent, and the request number fits into
13677 // an integer...
13678 // ...and in fact the requestNum IS the return value!
13679 // ===> In 99% of cases, this LAST option is what actually happens!!
13680 //
13681 int32_t OTAPI_Exec::issueAssetType(const std::string& SERVER_ID,
13682  const std::string& USER_ID,
13683  const std::string& THE_CONTRACT) const
13684 {
13685  if (SERVER_ID.empty()) {
13686  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13687  OT_FAIL;
13688  }
13689  if (USER_ID.empty()) {
13690  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13691  OT_FAIL;
13692  }
13693  if (THE_CONTRACT.empty()) {
13694  otErr << __FUNCTION__ << ": Null: THE_CONTRACT passed in!\n";
13695  OT_FAIL;
13696  }
13697 
13698  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
13699 
13700  OTString strContract(THE_CONTRACT);
13701 
13702  return OTAPI()->issueAssetType(theServerID, theUserID, strContract);
13703 }
13704 
13705 // Returns int32_t:
13706 // -1 means error; no message was sent.
13707 // -2 means the message was sent, but the request number must be passed as a
13708 // string, so call OTAPI_Exec::GetLargeRequestNum.
13709 // 0 means NO error, but also: no message was sent.
13710 // >0 means NO error, and the message was sent, and the request number fits into
13711 // an integer...
13712 // ...and in fact the requestNum IS the return value!
13713 // ===> In 99% of cases, this LAST option is what actually happens!!
13714 //
13715 int32_t OTAPI_Exec::getContract(const std::string& SERVER_ID,
13716  const std::string& USER_ID,
13717  const std::string& ASSET_ID) const
13718 {
13719  if (SERVER_ID.empty()) {
13720  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13721  OT_FAIL;
13722  }
13723  if (USER_ID.empty()) {
13724  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13725  OT_FAIL;
13726  }
13727  if (ASSET_ID.empty()) {
13728  otErr << __FUNCTION__ << ": Null: ASSET_ID passed in!\n";
13729  OT_FAIL;
13730  }
13731 
13732  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
13733  theAssetID(ASSET_ID);
13734 
13735  return OTAPI()->getContract(theServerID, theUserID, theAssetID);
13736 }
13737 
13738 // Returns int32_t:
13739 // -1 means error; no message was sent.
13740 // -2 means the message was sent, but the request number must be passed as a
13741 // string, so call OTAPI_Exec::GetLargeRequestNum.
13742 // 0 means NO error, but also: no message was sent.
13743 // >0 means NO error, and the message was sent, and the request number fits into
13744 // an integer...
13745 // ...and in fact the requestNum IS the return value!
13746 // ===> In 99% of cases, this LAST option is what actually happens!!
13747 //
13748 int32_t OTAPI_Exec::getMint(const std::string& SERVER_ID,
13749  const std::string& USER_ID,
13750  const std::string& ASSET_ID) const
13751 {
13752  if (SERVER_ID.empty()) {
13753  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13754  OT_FAIL;
13755  }
13756  if (USER_ID.empty()) {
13757  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13758  OT_FAIL;
13759  }
13760  if (ASSET_ID.empty()) {
13761  otErr << __FUNCTION__ << ": Null: ASSET_ID passed in!\n";
13762  OT_FAIL;
13763  }
13764 
13765  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
13766  theAssetID(ASSET_ID);
13767 
13768  return OTAPI()->getMint(theServerID, theUserID, theAssetID);
13769 }
13770 
13771 // Returns int32_t:
13772 // -1 means error; no message was sent.
13773 // -2 means the message was sent, but the request number must be passed as a
13774 // string, so call OTAPI_Exec::GetLargeRequestNum.
13775 // 0 means NO error, but also: no message was sent.
13776 // >0 means NO error, and the message was sent, and the request number fits into
13777 // an integer...
13778 // ...and in fact the requestNum IS the return value!
13779 // ===> In 99% of cases, this LAST option is what actually happens!!
13780 //
13781 int32_t OTAPI_Exec::createAssetAccount(const std::string& SERVER_ID,
13782  const std::string& USER_ID,
13783  const std::string& ASSET_ID) const
13784 {
13785  if (SERVER_ID.empty()) {
13786  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13787  OT_FAIL;
13788  }
13789  if (USER_ID.empty()) {
13790  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13791  OT_FAIL;
13792  }
13793  if (ASSET_ID.empty()) {
13794  otErr << __FUNCTION__ << ": Null: ASSET_ID passed in!\n";
13795  OT_FAIL;
13796  }
13797 
13798  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
13799  theAssetID(ASSET_ID);
13800 
13801  return OTAPI()->createAssetAccount(theServerID, theUserID, theAssetID);
13802 }
13803 
13804 // Sends a message to the server to retrieve latest copy of an asset acct.
13805 // Returns int32_t:
13806 // -1 means error; no message was sent.
13807 // -2 means the message was sent, but the request number must be passed as a
13808 // string, so call OTAPI_Exec::GetLargeRequestNum.
13809 // 0 means NO error, but also: no message was sent.
13810 // >0 means NO error, and the message was sent, and the request number fits into
13811 // an integer...
13812 // ...and in fact the requestNum IS the return value!
13813 // ===> In 99% of cases, this LAST option is what actually happens!!
13814 //
13815 // NOTE: Deprecated. Replaced by getAccountFiles
13816 int32_t OTAPI_Exec::getAccount(const std::string& SERVER_ID,
13817  const std::string& USER_ID,
13818  const std::string& ACCT_ID) const
13819 {
13820  if (SERVER_ID.empty()) {
13821  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13822  OT_FAIL;
13823  }
13824  if (USER_ID.empty()) {
13825  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13826  OT_FAIL;
13827  }
13828  if (ACCT_ID.empty()) {
13829  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
13830  OT_FAIL;
13831  }
13832 
13833  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID);
13834 
13835  return OTAPI()->getAccount(theServerID, theUserID, theAcctID);
13836 }
13837 
13838 // Sends a message to the server to retrieve latest copy of an asset acct.
13839 // Returns int32_t:
13840 // -1 means error; no message was sent.
13841 // -2 means the message was sent, but the request number must be passed as a
13842 // string, so call OTAPI_Exec::GetLargeRequestNum.
13843 // 0 means NO error, but also: no message was sent.
13844 // >0 means NO error, and the message was sent, and the request number fits into
13845 // an integer...
13846 // ...and in fact the requestNum IS the return value!
13847 // ===> In 99% of cases, this LAST option is what actually happens!!
13848 //
13849 int32_t OTAPI_Exec::getAccountFiles(const std::string& SERVER_ID,
13850  const std::string& USER_ID,
13851  const std::string& ACCT_ID) const
13852 {
13853  if (SERVER_ID.empty()) {
13854  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
13855  OT_FAIL;
13856  }
13857  if (USER_ID.empty()) {
13858  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13859  OT_FAIL;
13860  }
13861  if (ACCT_ID.empty()) {
13862  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
13863  OT_FAIL;
13864  }
13865 
13866  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID);
13867 
13868  return OTAPI()->getAccountFiles(theServerID, theUserID, theAcctID);
13869 }
13870 
13871 // GENERATE BASKET CREATION REQUEST
13872 //
13873 // (returns the basket in string form.)
13874 //
13875 // Call OTAPI_Exec::AddBasketCreationItem multiple times to add
13876 // the various currencies to the basket, and then call
13877 // OTAPI_Exec::issueBasket to send the request to the server.
13878 //
13880  const std::string& USER_ID, const int64_t& MINIMUM_TRANSFER) const
13881 {
13882  if (USER_ID.empty()) {
13883  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13884  OT_FAIL;
13885  }
13886  if (0 > MINIMUM_TRANSFER) {
13887  otErr << __FUNCTION__ << ": Negative: MINIMUM_TRANSFER passed in!\n";
13888  OT_FAIL;
13889  }
13890 
13891  const OTIdentifier theUserID(USER_ID);
13892 
13893  int64_t lMinimumTransfer = MINIMUM_TRANSFER == 0 ? 10 : MINIMUM_TRANSFER;
13894 
13895  std::unique_ptr<Basket> pBasket(OTAPI()->GenerateBasketCreation(
13896  theUserID, static_cast<int64_t>(lMinimumTransfer))); // Must be above
13897  // zero. If <= 0,
13898  // defaults to 10.
13899  if (nullptr == pBasket) return "";
13900 
13901  // At this point, I know pBasket is good (and will be cleaned up
13902  // automatically.)
13903 
13904  OTString strOutput(*pBasket);
13905  // pBasket->SaveContract(strOutput); // Extract the basket to string
13906  // form.
13907 
13908  std::string pBuf = strOutput.Get();
13909 
13910  return pBuf;
13911 }
13912 
13913 // ADD BASKET CREATION ITEM
13914 //
13915 // (returns the updated basket in string form.)
13916 //
13917 // Call OTAPI_Exec::GenerateBasketCreation first (above), then
13918 // call this function multiple times to add the various
13919 // currencies to the basket, and then call OTAPI_Exec::issueBasket
13920 // to send the request to the server.
13921 //
13923  const std::string& USER_ID, // for signature.
13924  const std::string& THE_BASKET, // created in above call.
13925  const std::string& ASSET_TYPE_ID, // Adding an asset type to the new basket.
13926  const int64_t& MINIMUM_TRANSFER) const
13927 {
13928 
13929  if (USER_ID.empty()) {
13930  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
13931  OT_FAIL;
13932  }
13933  if (THE_BASKET.empty()) {
13934  otErr << __FUNCTION__ << ": Null: THE_BASKET passed in!\n";
13935  OT_FAIL;
13936  }
13937  if (ASSET_TYPE_ID.empty()) {
13938  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
13939  OT_FAIL;
13940  }
13941  if (0 > MINIMUM_TRANSFER) {
13942  otErr << __FUNCTION__ << ": Negative: MINIMUM_TRANSFER passed in!\n";
13943  OT_FAIL;
13944  }
13945 
13946  OTString strBasket(THE_BASKET);
13947  const OTIdentifier theUserID(USER_ID), theAssetTypeID(ASSET_TYPE_ID);
13948  int64_t lMinimumTransfer = MINIMUM_TRANSFER == 0 ? 10 : MINIMUM_TRANSFER;
13949  Basket theBasket;
13950 
13951  bool bAdded = false;
13952 
13953  // todo perhaps verify the basket here, even though I already verified the
13954  // asset contract itself...
13955  // Can't never be too sure.
13956  if (theBasket.LoadContractFromString(strBasket)) {
13957  bAdded = OTAPI()->AddBasketCreationItem(
13958  theUserID, // for signature.
13959  theBasket, // created in above call.
13960  theAssetTypeID, // Adding an asset type to the new basket.
13961  static_cast<int64_t>(lMinimumTransfer)); // The amount of the asset
13962  // type that is in the
13963  // basket (per).
13964  }
13965 
13966  if (!bAdded) return "";
13967  OTString strOutput(theBasket); // Extract the updated basket to string form.
13968 
13969  std::string pBuf = strOutput.Get();
13970 
13971  return pBuf;
13972 }
13973 
13974 // ISSUE BASKET CURRENCY
13975 //
13976 // Issue a new asset type based on a BASKET of other asset types!
13977 // You cannot call this function until you first set up the BASKET_INFO object.
13978 // I will provide functions for setting up that object, so that you can then
13979 // call this function to actually message the server with your request.
13980 //
13981 // ANYONE can issue a new basket type, but they will have no control over the
13982 // issuer account. Normally when issuing a currency, you therefore control the
13983 // issuer account. But with baskets, that is managed internally by the server.
13984 // This means anyone can define a basket, and all may use it -- but no one
13985 // controls it except the server.
13986 //
13987 // Returns int32_t:
13988 // -1 means error; no message was sent.
13989 // -2 means the message was sent, but the request number must be passed as a
13990 // string, so call OTAPI_Exec::GetLargeRequestNum.
13991 // 0 means NO error, but also: no message was sent.
13992 // >0 means NO error, and the message was sent, and the request number fits into
13993 // an integer...
13994 // ...and in fact the requestNum IS the return value!
13995 // ===> In 99% of cases, this LAST option is what actually happens!!
13996 //
13997 int32_t OTAPI_Exec::issueBasket(const std::string& SERVER_ID,
13998  const std::string& USER_ID,
13999  const std::string& THE_BASKET) const
14000 {
14001  if (SERVER_ID.empty()) {
14002  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14003  OT_FAIL;
14004  }
14005  if (USER_ID.empty()) {
14006  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14007  OT_FAIL;
14008  }
14009  if (THE_BASKET.empty()) {
14010  otErr << __FUNCTION__ << ": Null: THE_BASKET passed in!\n";
14011  OT_FAIL;
14012  }
14013 
14014  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
14015 
14016  OTString strBasketInfo(THE_BASKET);
14017 
14018  return OTAPI()->issueBasket(theServerID, theUserID, strBasketInfo);
14019 }
14020 
14021 // GENERATE BASKET EXCHANGE REQUEST
14022 //
14023 // (Returns the new basket exchange request in string form.)
14024 //
14025 // Call this function first. Then call OTAPI_Exec::AddBasketExchangeItem
14026 // multiple times, and then finally call OTAPI_Exec::exchangeBasket to
14027 // send the request to the server.
14028 //
14030  const std::string& SERVER_ID, const std::string& USER_ID,
14031  const std::string& BASKET_ASSET_TYPE_ID,
14032  const std::string& BASKET_ASSET_ACCT_ID,
14033  const int32_t& TRANSFER_MULTIPLE) const // 1 2 3
14034 // 5=2,3,4 OR 10=4,6,8 OR 15=6,9,12
14035 {
14036  if (SERVER_ID.empty()) {
14037  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14038  OT_FAIL;
14039  }
14040  if (USER_ID.empty()) {
14041  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14042  OT_FAIL;
14043  }
14044  if (BASKET_ASSET_TYPE_ID.empty()) {
14045  otErr << __FUNCTION__ << ": Null: BASKET_ASSET_TYPE_ID passed in!\n";
14046  OT_FAIL;
14047  }
14048  if (BASKET_ASSET_ACCT_ID.empty()) {
14049  otErr << __FUNCTION__ << ": Null: BASKET_ASSET_ACCT_ID passed in!\n";
14050  OT_FAIL;
14051  }
14052 
14053  const OTIdentifier theUserID(USER_ID), theServerID(SERVER_ID),
14054  theBasketAssetTypeID(BASKET_ASSET_TYPE_ID),
14055  theBasketAssetAcctID(BASKET_ASSET_ACCT_ID);
14056  int32_t nTransferMultiple = 1; // Just a default value.
14057 
14058  if (TRANSFER_MULTIPLE > 0) nTransferMultiple = TRANSFER_MULTIPLE;
14059  std::unique_ptr<Basket> pBasket(OTAPI()->GenerateBasketExchange(
14060  theServerID, theUserID, theBasketAssetTypeID, theBasketAssetAcctID,
14061  nTransferMultiple)); // 1 2 3
14062  // 5=2,3,4 OR 10=4,6,8 OR 15=6,9,12
14063 
14064  if (nullptr == pBasket) return "";
14065 
14066  // At this point, I know pBasket is good (and will be cleaned up
14067  // automatically.)
14068  OTString strOutput(*pBasket); // Extract the basket to string form.
14069 
14070  std::string pBuf = strOutput.Get();
14071 
14072  return pBuf;
14073 }
14074 
14075 // ADD BASKET EXCHANGE ITEM
14076 //
14077 // Returns the updated basket exchange request in string form.
14078 // (Or "".)
14079 //
14080 // Call the above function first. Then call this one multiple
14081 // times, and then finally call OTAPI_Exec::exchangeBasket to send
14082 // the request to the server.
14083 //
14085  const std::string& SERVER_ID, const std::string& USER_ID,
14086  const std::string& THE_BASKET, const std::string& ASSET_TYPE_ID,
14087  const std::string& ASSET_ACCT_ID) const
14088 {
14089  if (SERVER_ID.empty()) {
14090  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14091  OT_FAIL;
14092  }
14093  if (USER_ID.empty()) {
14094  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14095  OT_FAIL;
14096  }
14097  if (THE_BASKET.empty()) {
14098  otErr << __FUNCTION__ << ": Null: THE_BASKET passed in!\n";
14099  OT_FAIL;
14100  }
14101  if (ASSET_TYPE_ID.empty()) {
14102  otErr << __FUNCTION__ << ": Null: ASSET_TYPE_ID passed in!\n";
14103  OT_FAIL;
14104  }
14105  if (ASSET_ACCT_ID.empty()) {
14106  otErr << __FUNCTION__ << ": Null: ASSET_ACCT_ID passed in!\n";
14107  OT_FAIL;
14108  }
14109 
14110  OTString strBasket(THE_BASKET);
14111  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
14112  theAssetTypeID(ASSET_TYPE_ID), theAssetAcctID(ASSET_ACCT_ID);
14113  Basket theBasket;
14114 
14115  bool bAdded = false;
14116 
14117  // todo perhaps verify the basket here, even though I already verified the
14118  // asset contract itself...
14119  // Can't never be too sure.
14120  if (theBasket.LoadContractFromString(strBasket)) {
14121  bAdded = OTAPI()->AddBasketExchangeItem(
14122  theServerID, theUserID, theBasket, theAssetTypeID, theAssetAcctID);
14123  }
14124 
14125  if (!bAdded) return "";
14126 
14127  OTString strOutput(theBasket); // Extract the updated basket to string form.
14128 
14129  std::string pBuf = strOutput.Get();
14130 
14131  return pBuf;
14132 }
14133 
14134 // EXCHANGE BASKET
14135 //
14136 // Send a request to the server asking to exchange in or out of a basket
14137 // currency.
14138 //
14139 // For example, maybe you have 3 gold, 2 silver, and 5 dollars, and those are
14140 // the ingredients of the "Rand" basket currency. This message allows you to
14141 // ask the server to convert from your gold, silver, and dollar accounts into
14142 // your Rand account. (Or convert from your Rand account back into your gold,
14143 // silver, and dollar accounts.)
14144 //
14145 // Other than this conversion process, (with the reserves stored internally by
14146 // the server) basket accounts are identical to normal asset accounts -- they
14147 // are merely another asset type ID, and you can use them the same as you would
14148 // use any other asset type (open accounts, write cheques, withdraw cash, trade
14149 // on markets, etc.)
14150 //
14151 // Returns int32_t:
14152 // -1 means error; no message was sent.
14153 // -2 means the message was sent, but the request number must be passed as a
14154 // string, so call OTAPI_Exec::GetLargeRequestNum.
14155 // 0 means NO error, but also: no message was sent.
14156 // >0 means NO error, and the message was sent, and the request number fits into
14157 // an integer...
14158 // ...and in fact the requestNum IS the return value!
14159 // ===> In 99% of cases, this LAST option is what actually happens!!
14160 //
14161 
14163  const std::string& SERVER_ID, const std::string& USER_ID,
14164  const std::string& BASKET_ASSET_ID, const std::string& THE_BASKET,
14165  const bool& BOOL_EXCHANGE_IN_OR_OUT) const // exchanging in == true (1), out
14166  // ==
14167  // false (0).
14168 {
14169  if (SERVER_ID.empty()) {
14170  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14171  OT_FAIL;
14172  }
14173  if (USER_ID.empty()) {
14174  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14175  OT_FAIL;
14176  }
14177  if (BASKET_ASSET_ID.empty()) {
14178  otErr << __FUNCTION__ << ": Null: BASKET_ASSET_ID passed in!\n";
14179  OT_FAIL;
14180  }
14181  if (THE_BASKET.empty()) {
14182  otErr << __FUNCTION__ << ": Null: THE_BASKET passed in!\n";
14183  OT_FAIL;
14184  }
14185 
14186  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
14187  theBasketAssetID(BASKET_ASSET_ID);
14188 
14189  OTString strBasketInfo(THE_BASKET);
14190 
14191  // exchanging in == true, out == false.
14192  const bool& bExchangeInOrOut =
14193  ((true == BOOL_EXCHANGE_IN_OR_OUT) ? true : false);
14194 
14195  return OTAPI()->exchangeBasket(theServerID, theUserID, theBasketAssetID,
14196  strBasketInfo, bExchangeInOrOut);
14197 }
14198 
14199 // Returns int32_t:
14200 // -1 means error; no message was sent.
14201 // -2 means the message was sent, but the request number must be passed as a
14202 // string, so call OTAPI_Exec::GetLargeRequestNum.
14203 // 0 means NO error, but also: no message was sent.
14204 // >0 means NO error, and the message was sent, and the request number fits into
14205 // an integer...
14206 // ...and in fact the requestNum IS the return value!
14207 // ===> In 99% of cases, this LAST option is what actually happens!!
14208 //
14209 int32_t OTAPI_Exec::getTransactionNumber(const std::string& SERVER_ID,
14210  const std::string& USER_ID) const
14211 {
14212  if (SERVER_ID.empty()) {
14213  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14214  OT_FAIL;
14215  }
14216  if (USER_ID.empty()) {
14217  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14218  OT_FAIL;
14219  }
14220 
14221  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
14222 
14223  return OTAPI()->getTransactionNumber(theServerID, theUserID);
14224 }
14225 
14226 // Returns int32_t:
14227 // -1 means error; no message was sent.
14228 // -2 means the message was sent, but the request number must be passed as a
14229 // string, so call OTAPI_Exec::GetLargeRequestNum.
14230 // 0 means NO error, but also: no message was sent.
14231 // >0 means NO error, and the message was sent, and the request number fits into
14232 // an integer...
14233 // ...and in fact the requestNum IS the return value!
14234 // ===> In 99% of cases, this LAST option is what actually happens!!
14235 //
14236 int32_t OTAPI_Exec::notarizeWithdrawal(const std::string& SERVER_ID,
14237  const std::string& USER_ID,
14238  const std::string& ACCT_ID,
14239  const int64_t& AMOUNT) const
14240 {
14241  if (SERVER_ID.empty()) {
14242  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14243  OT_FAIL;
14244  }
14245  if (USER_ID.empty()) {
14246  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14247  OT_FAIL;
14248  }
14249  if (ACCT_ID.empty()) {
14250  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
14251  OT_FAIL;
14252  }
14253  if (0 > AMOUNT) {
14254  otErr << __FUNCTION__ << ": Negative: AMOUNT passed in!\n";
14255  OT_FAIL;
14256  }
14257 
14258  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID);
14259 
14260  return OTAPI()->notarizeWithdrawal(theServerID, theUserID, theAcctID,
14261  static_cast<int64_t>(AMOUNT));
14262 }
14263 
14264 // Returns int32_t:
14265 // -1 means error; no message was sent.
14266 // -2 means the message was sent, but the request number must be passed as a
14267 // string, so call OTAPI_Exec::GetLargeRequestNum.
14268 // 0 means NO error, but also: no message was sent.
14269 // >0 means NO error, and the message was sent, and the request number fits into
14270 // an integer...
14271 // ...and in fact the requestNum IS the return value!
14272 // ===> In 99% of cases, this LAST option is what actually happens!!
14273 //
14274 int32_t OTAPI_Exec::notarizeDeposit(const std::string& SERVER_ID,
14275  const std::string& USER_ID,
14276  const std::string& ACCT_ID,
14277  const std::string& THE_PURSE) const
14278 {
14279  if (SERVER_ID.empty()) {
14280  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14281  OT_FAIL;
14282  }
14283  if (USER_ID.empty()) {
14284  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14285  OT_FAIL;
14286  }
14287  if (ACCT_ID.empty()) {
14288  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
14289  OT_FAIL;
14290  }
14291  if (THE_PURSE.empty()) {
14292  otErr << __FUNCTION__ << ": Null: THE_PURSE passed in!\n";
14293  OT_FAIL;
14294  }
14295 
14296  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID);
14297  OTString strPurse(THE_PURSE);
14298 
14299  return OTAPI()->notarizeDeposit(theServerID, theUserID, theAcctID,
14300  strPurse);
14301 }
14302 
14303 // Returns int32_t:
14304 // -1 means error; no message was sent.
14305 // -2 means the message was sent, but the request number must be passed as a
14306 // string, so call OTAPI_Exec::GetLargeRequestNum.
14307 // 0 means NO error, but also: no message was sent.
14308 // >0 means NO error, and the message was sent, and the request number fits into
14309 // an integer...
14310 // ...and in fact the requestNum IS the return value!
14311 // ===> In 99% of cases, this LAST option is what actually happens!!
14312 //
14313 int32_t OTAPI_Exec::notarizeTransfer(const std::string& SERVER_ID,
14314  const std::string& USER_ID,
14315  const std::string& ACCT_FROM,
14316  const std::string& ACCT_TO,
14317  const int64_t& AMOUNT,
14318  const std::string& NOTE) const
14319 {
14320  if (SERVER_ID.empty()) {
14321  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14322  OT_FAIL;
14323  }
14324  if (USER_ID.empty()) {
14325  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14326  OT_FAIL;
14327  }
14328  if (ACCT_FROM.empty()) {
14329  otErr << __FUNCTION__ << ": Null: ACCT_FROM passed in!\n";
14330  OT_FAIL;
14331  }
14332  if (ACCT_TO.empty()) {
14333  otErr << __FUNCTION__ << ": Null: ACCT_TO passed in!\n";
14334  OT_FAIL;
14335  }
14336  if (0 > AMOUNT) {
14337  otErr << __FUNCTION__ << ": Negative: AMOUNT passed in!\n";
14338  OT_FAIL;
14339  }
14340 
14341  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
14342  OTIdentifier theFromAcct(ACCT_FROM), theToAcct(ACCT_TO);
14343 
14344  OTString strNote(NOTE.empty() ? "" : NOTE);
14345 
14346  int64_t lAmount = AMOUNT;
14347 
14348  return OTAPI()->notarizeTransfer(theServerID, theUserID, theFromAcct,
14349  theToAcct, static_cast<int64_t>(lAmount),
14350  strNote);
14351 }
14352 
14353 // Returns int32_t:
14354 // -1 means error; no message was sent.
14355 // -2 means the message was sent, but the request number must be passed as a
14356 // string, so call OTAPI_Exec::GetLargeRequestNum.
14357 // 0 means NO error, but also: no message was sent.
14358 // >0 means NO error, and the message was sent, and the request number fits into
14359 // an integer...
14360 // ...and in fact the requestNum IS the return value!
14361 // ===> In 99% of cases, this LAST option is what actually happens!!
14362 //
14363 int32_t OTAPI_Exec::getInbox(const std::string& SERVER_ID,
14364  const std::string& USER_ID,
14365  const std::string& ACCT_ID) const
14366 {
14367  if (SERVER_ID.empty()) {
14368  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14369  OT_FAIL;
14370  }
14371  if (USER_ID.empty()) {
14372  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14373  OT_FAIL;
14374  }
14375  if (ACCT_ID.empty()) {
14376  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
14377  OT_FAIL;
14378  }
14379 
14380  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID);
14381 
14382  return OTAPI()->getInbox(theServerID, theUserID, theAcctID);
14383 }
14384 
14385 // Returns int32_t:
14386 // -1 means error; no message was sent.
14387 // -2 means the message was sent, but the request number must be passed as a
14388 // string, so call OTAPI_Exec::GetLargeRequestNum.
14389 // 0 means NO error, but also: no message was sent.
14390 // >0 means NO error, and the message was sent, and the request number fits into
14391 // an integer...
14392 // ...and in fact the requestNum IS the return value!
14393 // ===> In 99% of cases, this LAST option is what actually happens!!
14394 //
14395 int32_t OTAPI_Exec::getNymbox(const std::string& SERVER_ID,
14396  const std::string& USER_ID) const
14397 {
14398  if (SERVER_ID.empty()) {
14399  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14400  OT_FAIL;
14401  }
14402  if (USER_ID.empty()) {
14403  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14404  OT_FAIL;
14405  }
14406 
14407  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
14408 
14409  return OTAPI()->getNymbox(theServerID, theUserID);
14410 }
14411 
14412 // Returns int32_t:
14413 // -1 means error; no message was sent.
14414 // -2 means the message was sent, but the request number must be passed as a
14415 // string, so call OTAPI_Exec::GetLargeRequestNum.
14416 // 0 means NO error, but also: no message was sent.
14417 // >0 means NO error, and the message was sent, and the request number fits into
14418 // an integer...
14419 // ...and in fact the requestNum IS the return value!
14420 // ===> In 99% of cases, this LAST option is what actually happens!!
14421 //
14422 int32_t OTAPI_Exec::getOutbox(const std::string& SERVER_ID,
14423  const std::string& USER_ID,
14424  const std::string& ACCT_ID) const
14425 {
14426  if (SERVER_ID.empty()) {
14427  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14428  OT_FAIL;
14429  }
14430  if (USER_ID.empty()) {
14431  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14432  OT_FAIL;
14433  }
14434  if (ACCT_ID.empty()) {
14435  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
14436  OT_FAIL;
14437  }
14438 
14439  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID);
14440 
14441  return OTAPI()->getOutbox(theServerID, theUserID, theAcctID);
14442 }
14443 
14444 // Returns int32_t:
14445 // -1 means error; no message was sent.
14446 // -2 means the message was sent, but the request number must be passed as a
14447 // string, so call OTAPI_Exec::GetLargeRequestNum.
14448 // 0 means NO error, but also: no message was sent.
14449 // >0 means NO error, and the message was sent, and the request number fits into
14450 // an integer...
14451 // ...and in fact the requestNum IS the return value!
14452 // ===> In 99% of cases, this LAST option is what actually happens!!
14453 //
14454 int32_t OTAPI_Exec::processInbox(const std::string& SERVER_ID,
14455  const std::string& USER_ID,
14456  const std::string& ACCT_ID,
14457  const std::string& ACCT_LEDGER) const
14458 {
14459  if (SERVER_ID.empty()) {
14460  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14461  OT_FAIL;
14462  }
14463  if (USER_ID.empty()) {
14464  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14465  OT_FAIL;
14466  }
14467  if (ACCT_ID.empty()) {
14468  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
14469  OT_FAIL;
14470  }
14471  if (ACCT_LEDGER.empty()) {
14472  otErr << __FUNCTION__ << ": Null: ACCT_LEDGER passed in!\n";
14473  OT_FAIL;
14474  }
14475 
14476  // otOut << __FUNCTION__ << ": \n"
14477  // "SERVER_ID: " << SERVER_ID << " \n"
14478  // "USER_ID: " << USER_ID << " \n"
14479  // "ACCT_ID: " << ACCT_ID << " \n"
14480  // "ACCT_LEDGER:\n" << ACCT_LEDGER << "\n\n";
14481 
14482  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID);
14483  OTString strLedger(ACCT_LEDGER);
14484 
14485  // OTString temp1(SERVER_ID), temp2(USER_ID), temp3(ACCT_ID),
14486  // temp4(ACCT_LEDGER);
14487  // otOut << __FUNCTION__ << ": \n"
14488  // "\n\nSERVER_ID: " << temp1 << " \n"
14489  // "USER_ID: " << temp2 << " \n"
14490  // "ACCT_ID: " << temp3 << " \n"
14491  // "ACCT_LEDGER:\n" << temp4 << "\n\n";
14492 
14493  return OTAPI()->processInbox(theServerID, theUserID, theAcctID, strLedger);
14494 }
14495 
14496 // Returns:
14497 // -1 if error.
14498 // 0 if Nymbox is empty.
14499 // 1 or more: (OLD: Count of items in Nymbox before processing.)
14500 // UPDATE: This now returns the request number of the message sent, if success.
14501 //
14502 int32_t OTAPI_Exec::processNymbox(const std::string& SERVER_ID,
14503  const std::string& USER_ID) const
14504 {
14505  if (SERVER_ID.empty()) {
14506  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14507  OT_FAIL;
14508  }
14509  if (USER_ID.empty()) {
14510  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14511  OT_FAIL;
14512  }
14513 
14514  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
14515 
14516  return OTAPI()->processNymbox(theServerID, theUserID);
14517 }
14518 
14519 // Returns int32_t:
14520 // -1 means error; no message was sent.
14521 // -2 means the message was sent, but the request number must be passed as a
14522 // string, so call OTAPI_Exec::GetLargeRequestNum.
14523 // 0 means NO error, but also: no message was sent.
14524 // >0 means NO error, and the message was sent, and the request number fits into
14525 // an integer...
14526 // ...and in fact the requestNum IS the return value!
14527 // ===> In 99% of cases, this LAST option is what actually happens!!
14528 //
14529 int32_t OTAPI_Exec::withdrawVoucher(const std::string& SERVER_ID,
14530  const std::string& USER_ID,
14531  const std::string& ACCT_ID,
14532  const std::string& RECIPIENT_USER_ID,
14533  const std::string& CHEQUE_MEMO,
14534  const int64_t& AMOUNT) const
14535 {
14536  if (SERVER_ID.empty()) {
14537  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14538  OT_FAIL;
14539  }
14540  if (USER_ID.empty()) {
14541  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14542  OT_FAIL;
14543  }
14544  if (ACCT_ID.empty()) {
14545  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
14546  OT_FAIL;
14547  }
14548  if (RECIPIENT_USER_ID.empty()) {
14549  otErr << __FUNCTION__ << ": Null: RECIPIENT_USER_ID passed in!\n";
14550  OT_FAIL;
14551  }
14552  // if (CHEQUE_MEMO.empty()) { otErr << __FUNCTION__ << ": Null:
14553  // CHEQUE_MEMO passed
14554  // in!\n"; OT_FAIL; }
14555  if (0 > AMOUNT) {
14556  otErr << __FUNCTION__ << ": Negative: AMOUNT passed in!\n";
14557  OT_FAIL;
14558  }
14559 
14560  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID),
14561  theRecipientUserID(RECIPIENT_USER_ID);
14562 
14563  OTString strMemo(CHEQUE_MEMO);
14564  int64_t lAmount = AMOUNT;
14565 
14566  return OTAPI()->withdrawVoucher(theServerID, theUserID, theAcctID,
14567  theRecipientUserID, strMemo,
14568  static_cast<int64_t>(lAmount));
14569 }
14570 
14571 // PAY DIVIDEND -- to shareholders
14572 //
14574  const std::string& SERVER_ID,
14575  const std::string& ISSUER_USER_ID, // must be issuer of SHARES_ASSET_TYPE_ID
14576  const std::string& DIVIDEND_FROM_ACCT_ID, // if dollars paid for pepsi
14577  // shares, then this is the
14578  // issuer's dollars account.
14579  const std::string& SHARES_ASSET_TYPE_ID, // if dollars paid for pepsi
14580  // shares, then this is the pepsi
14581  // shares asset type id.
14582  const std::string& DIVIDEND_MEMO, // user-configurable note that's added to
14583  // the payout request message.
14584  const int64_t& AMOUNT_PER_SHARE) const // number of dollars to be paid out
14585  // PER
14586 // SHARE (multiplied by total number of
14587 // shares issued.)
14588 {
14589  if (SERVER_ID.empty()) {
14590  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14591  OT_FAIL;
14592  }
14593  if (ISSUER_USER_ID.empty()) {
14594  otErr << __FUNCTION__ << ": Null: ISSUER_USER_ID passed in!\n";
14595  OT_FAIL;
14596  }
14597  if (DIVIDEND_FROM_ACCT_ID.empty()) {
14598  otErr << __FUNCTION__ << ": Null: DIVIDEND_FROM_ACCT_ID passed in!\n";
14599  OT_FAIL;
14600  }
14601  if (SHARES_ASSET_TYPE_ID.empty()) {
14602  otErr << __FUNCTION__ << ": Null: SHARES_ASSET_TYPE_ID passed in!\n";
14603  OT_FAIL;
14604  }
14605  // if (DIVIDEND_MEMO.empty()) { otErr << __FUNCTION__ << ":
14606  // Null: DIVIDEND_MEMO
14607  // passed in!\n"; OT_FAIL; }
14608  if (0 > AMOUNT_PER_SHARE) {
14609  otErr << __FUNCTION__ << ": Negative: AMOUNT_PER_SHARE passed in!\n";
14610  OT_FAIL;
14611  }
14612 
14613  OTIdentifier theServerID(SERVER_ID), theIssuerUserID(ISSUER_USER_ID),
14614  theDividendFromAcctID(DIVIDEND_FROM_ACCT_ID),
14615  theSharesAssetTypeID(SHARES_ASSET_TYPE_ID);
14616 
14617  OTString strMemo(DIVIDEND_MEMO);
14618  int64_t lAmount = AMOUNT_PER_SHARE;
14619 
14620  return OTAPI()->payDividend(theServerID, theIssuerUserID,
14621  theDividendFromAcctID, theSharesAssetTypeID,
14622  strMemo, static_cast<int64_t>(lAmount));
14623 }
14624 
14625 // Returns int32_t:
14626 // -1 means error; no message was sent.
14627 // -2 means the message was sent, but the request number must be passed as a
14628 // string, so call OTAPI_Exec::GetLargeRequestNum.
14629 // 0 means NO error, but also: no message was sent.
14630 // >0 means NO error, and the message was sent, and the request number fits into
14631 // an integer...
14632 // ...and in fact the requestNum IS the return value!
14633 // ===> In 99% of cases, this LAST option is what actually happens!!
14634 //
14635 int32_t OTAPI_Exec::depositCheque(const std::string& SERVER_ID,
14636  const std::string& USER_ID,
14637  const std::string& ACCT_ID,
14638  const std::string& THE_CHEQUE) const
14639 {
14640  if (SERVER_ID.empty()) {
14641  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14642  OT_FAIL;
14643  }
14644  if (USER_ID.empty()) {
14645  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14646  OT_FAIL;
14647  }
14648  if (ACCT_ID.empty()) {
14649  otErr << __FUNCTION__ << ": Null: ACCT_ID passed in!\n";
14650  OT_FAIL;
14651  }
14652  if (THE_CHEQUE.empty()) {
14653  otErr << __FUNCTION__ << ": Null: THE_CHEQUE passed in!\n";
14654  OT_FAIL;
14655  }
14656 
14657  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID), theAcctID(ACCT_ID);
14658 
14659  OTString strCheque(THE_CHEQUE);
14660 
14661  return OTAPI()->depositCheque(theServerID, theUserID, theAcctID, strCheque);
14662 }
14663 
14664 // DEPOSIT PAYMENT PLAN
14665 //
14666 // See OTAPI_Exec::WritePaymentPlan as well.
14667 //
14668 // Returns int32_t:
14669 // -1 means error; no message was sent.
14670 // -2 means the message was sent, but the request number must be passed as a
14671 // string, so call OTAPI_Exec::GetLargeRequestNum.
14672 // 0 means NO error, but also: no message was sent.
14673 // >0 means NO error, and the message was sent, and the request number fits into
14674 // an integer...
14675 // ...and in fact the requestNum IS the return value!
14676 // ===> In 99% of cases, this LAST option is what actually happens!!
14677 //
14679  const std::string& SERVER_ID, const std::string& USER_ID,
14680  const std::string& THE_PAYMENT_PLAN) const
14681 {
14682  if (SERVER_ID.empty()) {
14683  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14684  OT_FAIL;
14685  }
14686  if (USER_ID.empty()) {
14687  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14688  OT_FAIL;
14689  }
14690  if (THE_PAYMENT_PLAN.empty()) {
14691  otErr << __FUNCTION__ << ": Null: THE_PAYMENT_PLAN passed in!\n";
14692  OT_FAIL;
14693  }
14694 
14695  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
14696  const OTString strPlan(THE_PAYMENT_PLAN);
14697 
14698  return OTAPI()->depositPaymentPlan(theServerID, theUserID, strPlan);
14699 }
14700 
14701 // DONE: Remove Market ID.
14702 // DONE: Change inner call from cancelNymMarketOffer to cancelCronItem
14703 // DONE: Make a copy of this function called cancelPaymentPlan.
14704 //
14705 // Returns int32_t:
14706 // -1 means error; no message was sent.
14707 // -2 means the message was sent, but the request number must be passed as a
14708 // string, so call OTAPI_Exec::GetLargeRequestNum.
14709 // 0 means NO error, but also: no message was sent.
14710 // >0 means NO error, and the message was sent, and the request number fits into
14711 // an integer...
14712 // ...and in fact the requestNum IS the return value!
14713 // ===> In 99% of cases, this LAST option is what actually happens!!
14714 //
14715 int32_t OTAPI_Exec::killMarketOffer(const std::string& SERVER_ID,
14716  const std::string& USER_ID,
14717  const std::string& ASSET_ACCT_ID,
14718  const int64_t& TRANSACTION_NUMBER) const
14719 {
14720  if (SERVER_ID.empty()) {
14721  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14722  OT_FAIL;
14723  }
14724  if (USER_ID.empty()) {
14725  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14726  OT_FAIL;
14727  }
14728  if (ASSET_ACCT_ID.empty()) {
14729  otErr << __FUNCTION__ << ": Null: ASSET_ACCT_ID passed in!\n";
14730  OT_FAIL;
14731  }
14732  if (0 > TRANSACTION_NUMBER) {
14733  otErr << __FUNCTION__ << ": Negative: TRANSACTION_NUMBER passed in!\n";
14734  OT_FAIL;
14735  }
14736 
14737  const int64_t lTransactionNumber = TRANSACTION_NUMBER;
14738 
14739  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
14740  theAssetAcctID(ASSET_ACCT_ID);
14741 
14742  return OTAPI()->cancelCronItem(theServerID, theUserID, theAssetAcctID,
14743  static_cast<int64_t>(lTransactionNumber));
14744 }
14745 
14746 // OTAPI_Exec::cancelPaymentPlan
14747 // Cancel a payment plan by transaction number.
14748 //
14749 // Returns int32_t:
14750 // -1 means error; no message was sent.
14751 // -2 means the message was sent, but the request number must be passed as a
14752 // string, so call OTAPI_Exec::GetLargeRequestNum.
14753 // 0 means NO error, but also: no message was sent.
14754 // >0 means NO error, and the message was sent, and the request number fits into
14755 // an integer...
14756 // ...and in fact the requestNum IS the return value!
14757 // ===> In 99% of cases, this LAST option is what actually happens!!
14758 //
14759 int32_t OTAPI_Exec::killPaymentPlan(const std::string& SERVER_ID,
14760  const std::string& USER_ID,
14761  const std::string& FROM_ACCT_ID,
14762  const int64_t& TRANSACTION_NUMBER) const
14763 {
14764  if (SERVER_ID.empty()) {
14765  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14766  OT_FAIL;
14767  }
14768  if (USER_ID.empty()) {
14769  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14770  OT_FAIL;
14771  }
14772  if (FROM_ACCT_ID.empty()) {
14773  otErr << __FUNCTION__ << ": Null: FROM_ACCT_ID passed in!\n";
14774  OT_FAIL;
14775  }
14776  if (0 > TRANSACTION_NUMBER) {
14777  otErr << __FUNCTION__ << ": Negative: TRANSACTION_NUMBER passed in!\n";
14778  OT_FAIL;
14779  }
14780 
14781  const int64_t lTransactionNumber = TRANSACTION_NUMBER;
14782 
14783  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
14784  theFromAcctID(FROM_ACCT_ID);
14785 
14786  return OTAPI()->cancelCronItem(theServerID, theUserID, theFromAcctID,
14787  static_cast<int64_t>(lTransactionNumber));
14788 }
14789 
14790 // ISSUE MARKET OFFER
14791 //
14792 // Returns int32_t:
14793 // -1 means error; no message was sent.
14794 // -2 means the message was sent, but the request number must be passed as a
14795 // string, so call OTAPI_Exec::GetLargeRequestNum.
14796 // 0 means NO error, but also: no message was sent.
14797 // >0 means NO error, and the message was sent, and the request number fits into
14798 // an integer...
14799 // ...and in fact the requestNum IS the return value!
14800 // ===> In 99% of cases, this LAST option is what actually happens!!
14801 //
14803  const std::string& ASSET_ACCT_ID, // Perhaps this is the wheat market.
14804  const std::string& CURRENCY_ACCT_ID, // Perhaps I'm buying the wheat with
14805  // rubles.
14806  const int64_t& MARKET_SCALE, // Defaults to minimum of 1. Market
14807  // granularity.
14808  const int64_t& MINIMUM_INCREMENT, // This will be multiplied by the Scale.
14809  // Min 1.
14810  const int64_t& TOTAL_ASSETS_ON_OFFER, // Total assets available for sale or
14811  // purchase. Will be multiplied by
14812  // minimum increment.
14813  const int64_t& PRICE_LIMIT, // Per Minimum Increment...
14814  const bool& bBuyingOrSelling, // SELLING == true, BUYING == false.
14815  const time64_t& LIFESPAN_IN_SECONDS, // Pass 0 for the default behavior:
14816  // 86400 seconds aka 1 day.
14817  const std::string& STOP_SIGN, // Must be "" (for market/limit orders) or "<"
14818  // or ">" (for stop orders.)
14819  const int64_t& ACTIVATION_PRICE) const // Must be provided if STOP_SIGN is
14820  // also
14821 // set. Determines the price threshold for
14822 // stop orders.
14823 {
14824  if (ASSET_ACCT_ID.empty()) {
14825  otErr << __FUNCTION__ << ": Null: ASSET_ACCT_ID passed in!\n";
14826  OT_FAIL;
14827  }
14828  if (CURRENCY_ACCT_ID.empty()) {
14829  otErr << __FUNCTION__ << ": Null: CURRENCY_ACCT_ID passed in!\n";
14830  OT_FAIL;
14831  }
14832  if (0 > MARKET_SCALE) {
14833  otErr << __FUNCTION__ << ": Negative: MARKET_SCALE passed in!\n";
14834  OT_FAIL;
14835  }
14836  if (0 > MINIMUM_INCREMENT) {
14837  otErr << __FUNCTION__ << ": Negative: MINIMUM_INCREMENT passed in!\n";
14838  OT_FAIL;
14839  }
14840  if (0 > TOTAL_ASSETS_ON_OFFER) {
14841  otErr << __FUNCTION__
14842  << ": Negative: TOTAL_ASSETS_ON_OFFER passed in!\n";
14843  OT_FAIL;
14844  }
14845  if (0 > PRICE_LIMIT) {
14846  otErr << __FUNCTION__ << ": Negative: PRICE_LIMIT passed in!\n";
14847  OT_FAIL;
14848  }
14849  if (0 > ACTIVATION_PRICE) {
14850  otErr << __FUNCTION__ << ": Negative: ACTIVATION_PRICE passed in!\n";
14851  OT_FAIL;
14852  }
14853  char cStopSign = 0;
14854 
14855  if (0 == STOP_SIGN.compare("<"))
14856  cStopSign = '<';
14857  else if (0 == STOP_SIGN.compare(">"))
14858  cStopSign = '>';
14859  if (!STOP_SIGN.empty() && ((ACTIVATION_PRICE == 0) ||
14860  ((cStopSign != '<') && (cStopSign != '>')))) {
14861  otErr << __FUNCTION__ << ": If STOP_SIGN is provided, it must be \"<\" "
14862  "or \">\", and in that case ACTIVATION_PRICE "
14863  "must be non-zero.\n";
14864  OT_FAIL;
14865  }
14866  const OTIdentifier theAssetAcctID(ASSET_ACCT_ID),
14867  theCurrencyAcctID(CURRENCY_ACCT_ID);
14868  const std::string str_asset_server_id =
14870  const std::string str_currency_server_id =
14871  OTAPI_Exec::GetAccountWallet_ServerID(CURRENCY_ACCT_ID);
14872  const std::string str_asset_nym_id =
14873  OTAPI_Exec::GetAccountWallet_NymID(ASSET_ACCT_ID);
14874  const std::string str_currency_nym_id =
14875  OTAPI_Exec::GetAccountWallet_NymID(CURRENCY_ACCT_ID);
14876  if (str_asset_server_id.empty() || str_currency_server_id.empty() ||
14877  str_asset_nym_id.empty() || str_currency_nym_id.empty()) {
14878  otErr << __FUNCTION__ << ": Failed determining server or nym ID for "
14879  "either asset or currency account.\n";
14880  OT_FAIL;
14881  }
14882  const OTIdentifier theAssetServerID(str_asset_server_id),
14883  theAssetUserID(str_asset_nym_id),
14884  theCurrencyServerID(str_currency_server_id),
14885  theCurrencyUserID(str_currency_nym_id);
14886  if (theAssetServerID != theCurrencyServerID) {
14887  otErr << __FUNCTION__
14888  << ": The accounts provided are on two different servers.\n";
14889  OT_FAIL;
14890  }
14891  if (theAssetUserID != theCurrencyUserID) {
14892  otErr << __FUNCTION__
14893  << ": The accounts provided are owned by two different nyms.\n";
14894  OT_FAIL;
14895  }
14896  // 1 is the minimum value here.
14897  //
14898  int64_t lMarketScale = (0 == MARKET_SCALE) ? 1 : MARKET_SCALE;
14899  int64_t lMinIncrement = (0 == MINIMUM_INCREMENT) ? 1 : MINIMUM_INCREMENT;
14900  int64_t lTotalAssetsOnOffer =
14901  (0 == TOTAL_ASSETS_ON_OFFER) ? 1 : TOTAL_ASSETS_ON_OFFER;
14902  int64_t lPriceLimit = PRICE_LIMIT; // 0 is allowed now, for market orders.
14903  return OTAPI()->issueMarketOffer(
14904  theAssetServerID, theAssetUserID, theAssetAcctID, theCurrencyAcctID,
14905  static_cast<int64_t>(lMarketScale), static_cast<int64_t>(lMinIncrement),
14906  static_cast<int64_t>(lTotalAssetsOnOffer),
14907  static_cast<int64_t>(lPriceLimit), bBuyingOrSelling,
14908  LIFESPAN_IN_SECONDS, cStopSign, static_cast<int64_t>(ACTIVATION_PRICE));
14909 }
14910 
14911 // Returns int32_t:
14912 // -1 means error; no message was sent.
14913 // -2 means the message was sent, but the request number must be passed as a
14914 // string, so call OTAPI_Exec::GetLargeRequestNum.
14915 // 0 means NO error, but also: no message was sent.
14916 // >0 means NO error, and the message was sent, and the request number fits into
14917 // an integer...
14918 // ...and in fact the requestNum IS the return value!
14919 // ===> In 99% of cases, this LAST option is what actually happens!!
14920 //
14921 int32_t OTAPI_Exec::getMarketList(const std::string& SERVER_ID,
14922  const std::string& USER_ID) const
14923 {
14924  if (SERVER_ID.empty()) {
14925  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14926  OT_FAIL;
14927  }
14928  if (USER_ID.empty()) {
14929  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14930  OT_FAIL;
14931  }
14932 
14933  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
14934 
14935  return OTAPI()->getMarketList(theServerID, theUserID);
14936 }
14937 
14938 // Returns int32_t:
14939 // -1 means error; no message was sent.
14940 // -2 means the message was sent, but the request number must be passed as a
14941 // string, so call OTAPI_Exec::GetLargeRequestNum.
14942 // 0 means NO error, but also: no message was sent.
14943 // >0 means NO error, and the message was sent, and the request number fits into
14944 // an integer...
14945 // ...and in fact the requestNum IS the return value!
14946 // ===> In 99% of cases, this LAST option is what actually happens!!
14947 //
14948 int32_t OTAPI_Exec::getMarketOffers(const std::string& SERVER_ID,
14949  const std::string& USER_ID,
14950  const std::string& MARKET_ID,
14951  const int64_t& MAX_DEPTH) const
14952 {
14953  if (SERVER_ID.empty()) {
14954  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14955  OT_FAIL;
14956  }
14957  if (USER_ID.empty()) {
14958  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
14959  OT_FAIL;
14960  }
14961  if (0 > MAX_DEPTH) {
14962  otErr << __FUNCTION__ << ": Negative: MAX_DEPTH passed in!\n";
14963  OT_FAIL;
14964  }
14965 
14966  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
14967  theMarketID(MARKET_ID);
14968 
14969  const int64_t lDepth = MAX_DEPTH;
14970  if (0 > lDepth) {
14971  otErr << __FUNCTION__
14972  << ": lDepth is out of bounds (it's in the negative!)\n";
14973  OT_FAIL;
14974  }
14975 
14976  return OTAPI()->getMarketOffers(theServerID, theUserID, theMarketID,
14977  static_cast<int64_t>(lDepth));
14978 }
14979 
14980 // Returns int32_t:
14981 // -1 means error; no message was sent.
14982 // -2 means the message was sent, but the request number must be passed as a
14983 // string, so call OTAPI_Exec::GetLargeRequestNum.
14984 // 0 means NO error, but also: no message was sent.
14985 // >0 means NO error, and the message was sent, and the request number fits into
14986 // an integer...
14987 // ...and in fact the requestNum IS the return value!
14988 // ===> In 99% of cases, this LAST option is what actually happens!!
14989 //
14990 int32_t OTAPI_Exec::getMarketRecentTrades(const std::string& SERVER_ID,
14991  const std::string& USER_ID,
14992  const std::string& MARKET_ID) const
14993 {
14994  if (SERVER_ID.empty()) {
14995  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
14996  OT_FAIL;
14997  }
14998  if (USER_ID.empty()) {
14999  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15000  OT_FAIL;
15001  }
15002  if (MARKET_ID.empty()) {
15003  otErr << __FUNCTION__ << ": Null: MARKET_ID passed in!\n";
15004  OT_FAIL;
15005  }
15006 
15007  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
15008  theMarketID(MARKET_ID);
15009 
15010  return OTAPI()->getMarketRecentTrades(theServerID, theUserID, theMarketID);
15011 }
15012 
15013 // Returns int32_t:
15014 // -1 means error; no message was sent.
15015 // -2 means the message was sent, but the request number must be passed as a
15016 // string, so call OTAPI_Exec::GetLargeRequestNum.
15017 // 0 means NO error, but also: no message was sent.
15018 // >0 means NO error, and the message was sent, and the request number fits into
15019 // an integer...
15020 // ...and in fact the requestNum IS the return value!
15021 // ===> In 99% of cases, this LAST option is what actually happens!!
15022 //
15023 int32_t OTAPI_Exec::getNym_MarketOffers(const std::string& SERVER_ID,
15024  const std::string& USER_ID) const
15025 {
15026  if (SERVER_ID.empty()) {
15027  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
15028  OT_FAIL;
15029  }
15030  if (USER_ID.empty()) {
15031  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15032  OT_FAIL;
15033  }
15034 
15035  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
15036 
15037  return OTAPI()->getNym_MarketOffers(theServerID, theUserID);
15038 }
15039 
15040 // POP MESSAGE BUFFER
15041 //
15042 // If there are any replies from the server, they are stored in
15043 // the message buffer. This function will return those messages
15044 // (and remove them from the list) one-by-one, newest first.
15045 //
15046 // Returns the message as a string.
15047 //
15048 // Update: added arguments for: ServerID AND NymID AND request number
15049 // NOTE: Any messages, when popping, which have the CORRECT serverID
15050 // and the CORRECT NymID, but the wrong Request number, will be discarded.
15051 //
15052 // (Why? Because the client using the OT API will have already treated
15053 // that message as "dropped" by now, if it's already on to the next one,
15054 // and the protocol is designed to move forward properly based specifically
15055 // on this function returning the one EXPECTED... outgoing messages flush
15056 // the incoming buffer anyway, so the client will have assumed the wrong
15057 // reply was flushed by now anyway.)
15058 //
15059 // However, if the Server ID and the User ID are wrong, this just means that
15060 // some other code is still expecting that reply, and hasn't even popped yet!
15061 // Therefore, we do NOT want to discard THOSE replies, but put them back if
15062 // necessary -- only discarding the ones where the IDs match.
15063 //
15064 //
15065 std::string OTAPI_Exec::PopMessageBuffer(const int64_t& REQUEST_NUMBER,
15066  const std::string& SERVER_ID,
15067  const std::string& USER_ID) const
15068 {
15069  if (0 > REQUEST_NUMBER) {
15070  otErr << __FUNCTION__ << ": Negative: REQUEST_NUMBER passed in!\n";
15071  OT_FAIL;
15072  }
15073  if (SERVER_ID.empty()) {
15074  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
15075  OT_FAIL;
15076  }
15077  if (USER_ID.empty()) {
15078  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15079  OT_FAIL;
15080  }
15081 
15082  const int64_t lRequestNum = REQUEST_NUMBER;
15083  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
15084  std::unique_ptr<OTMessage> pMsg(OTAPI()->PopMessageBuffer(
15085  static_cast<int64_t>(lRequestNum), theServerID,
15086  theUserID)); // caller responsible to delete.
15087 
15088  if (nullptr == pMsg) // The buffer was empty.
15089  {
15090  otErr << __FUNCTION__ << ": Reply not found, sorry.\n";
15091  return "";
15092  }
15093 
15094  const OTString strOutput(*pMsg);
15095 
15096  std::string pBuf = strOutput.Get();
15097  return pBuf;
15098 }
15099 
15100 // Just flat-out empties the thing.
15101 //
15103 {
15105 }
15106 
15107 // Message OUT-BUFFER
15108 //
15109 // (for messages I--the client--have sent the server.)
15110 /*
15111 class OTMessageOutbuffer:
15112 void Clear();
15113 void AddSentMessage (OTMessage& theMessage); // Allocate theMsg
15114 on the heap (takes ownership.) Mapped by request num.
15115 OTMessage * GetSentMessage (const int64_t& lRequestNum); // null == not
15116 found. caller NOT responsible to delete.
15117 bool RemoveSentMessage (const int64_t& lRequestNum); // true == it was
15118 removed. false == it wasn't found.
15119 */
15120 
15121 // GET SENT MESSAGE
15122 //
15123 // If there were any messages sent to the server, copies are
15124 // stored here, so the developer using the OT API can access
15125 // them by request number.
15126 //
15127 // Returns the message as a string.
15128 //
15129 std::string OTAPI_Exec::GetSentMessage(const int64_t& REQUEST_NUMBER,
15130  const std::string& SERVER_ID,
15131  const std::string& USER_ID) const
15132 {
15133  if (0 > REQUEST_NUMBER) {
15134  otErr << __FUNCTION__ << ": Negative: REQUEST_NUMBER passed in!\n";
15135  OT_FAIL;
15136  }
15137  if (SERVER_ID.empty()) {
15138  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
15139  OT_FAIL;
15140  }
15141  if (USER_ID.empty()) {
15142  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15143  OT_FAIL;
15144  }
15145  const int64_t lRequestNum = REQUEST_NUMBER;
15146  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
15147  OTMessage* pMsg = OTAPI()->GetSentMessage(static_cast<int64_t>(lRequestNum),
15148  theServerID, theUserID);
15149 
15150  if (nullptr == pMsg) // The message wasn't found with that request number.
15151  {
15152  otWarn << __FUNCTION__ << ": Message not found with request number "
15153  << lRequestNum << ", sorry.\n";
15154  return "";
15155  }
15156  const OTString strOutput(*pMsg); // No need to cleanup the message since
15157  // it's still in the buffer until
15158  // explicitly removed.
15159 
15160  std::string pBuf = strOutput.Get();
15161 
15162  return pBuf;
15163 }
15164 
15165 // REMOVE SENT MESSAGE
15166 //
15167 // If there were any messages sent to the server, copies are
15168 // stored until removed via this function.
15169 //
15170 // Returns bool based on whether message was found (and removed.)
15171 //
15172 bool OTAPI_Exec::RemoveSentMessage(const int64_t& REQUEST_NUMBER,
15173  const std::string& SERVER_ID,
15174  const std::string& USER_ID) const
15175 {
15176  if (0 > REQUEST_NUMBER) {
15177  otErr << __FUNCTION__ << ": Negative: REQUEST_NUMBER passed in!\n";
15178  OT_FAIL;
15179  }
15180  if (SERVER_ID.empty()) {
15181  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
15182  OT_FAIL;
15183  }
15184  if (USER_ID.empty()) {
15185  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15186  OT_FAIL;
15187  }
15188  const int64_t lRequestNum = REQUEST_NUMBER;
15189  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
15190  const bool& bSuccess = OTAPI()->RemoveSentMessage(
15191  static_cast<int64_t>(lRequestNum), theServerID, theUserID);
15192 
15193  return bSuccess;
15194 }
15195 
15196 // OTAPI_Exec::FlushSentMessages
15197 //
15198 // Make sure to call this directly after a successful @getNymbox.
15199 // (And ONLY at that time.)
15200 //
15201 // This empties the buffer of sent messages.
15202 // (Harvesting any transaction numbers that are still there.)
15203 //
15204 // NOTE: You normally ONLY call this immediately after receiving
15205 // a successful @getNymbox. It's only then that you can see which
15206 // messages a server actually received or not -- which transactions
15207 // it processed (success or fail) vs which transactions did NOT
15208 // process (and thus did NOT leave any success/fail receipt in the
15209 // nymbox.)
15210 //
15211 // I COULD have just flushed myself IN the @getNymbox code (where
15212 // the reply is processed.) But then the developer using the OT API
15213 // would never have the opportunity to see whether a message was
15214 // replied to, and harvest it for himself (say, just before attempting
15215 // a re-try, which I plan to do in the high-level Java API, which is
15216 // why I'm coding it this way.)
15217 //
15218 // This way, he can do that if he wishes, THEN call this function,
15219 // and harvesting will still occur properly, and he will also thus have
15220 // his chance to check for his own replies to harvest before then.
15221 // This all depends on the developer using the API being smart enough
15222 // to call this function after a successful @getNymbox!
15223 //
15224 void OTAPI_Exec::FlushSentMessages(const bool& bHarvestingForRetry,
15225  const std::string& SERVER_ID,
15226  const std::string& USER_ID,
15227  const std::string& THE_NYMBOX) const
15228 {
15229  if (SERVER_ID.empty()) {
15230  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
15231  OT_FAIL;
15232  return;
15233  }
15234  if (USER_ID.empty()) {
15235  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15236  OT_FAIL;
15237  return;
15238  }
15239  if (THE_NYMBOX.empty()) {
15240  otErr << __FUNCTION__ << ": Null: THE_NYMBOX passed in!\n";
15241  OT_FAIL;
15242  return;
15243  }
15244 
15245  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
15246  const OTString strLedger(THE_NYMBOX);
15247  OTLedger theLedger(theUserID, theUserID, theServerID);
15248  if (strLedger.Exists() && theLedger.LoadContractFromString(strLedger))
15249  OTAPI()->FlushSentMessages(bHarvestingForRetry, theServerID, theUserID,
15250  theLedger);
15251  else
15252  otErr << __FUNCTION__
15253  << ": Failure: Unable to load Nymbox from string:\n\n"
15254  << strLedger << "\n\n";
15255 }
15256 
15257 // Sometimes you just need a quick nap between messages.
15258 //
15259 void OTAPI_Exec::Sleep(const int64_t& MILLISECONDS) const
15260 {
15261  bool bIsInitialized = OTAPI()->IsInitialized();
15262  if (!bIsInitialized) {
15263  otErr << __FUNCTION__
15264  << ": Not initialized; call OT_API::Init first.\n";
15265  OT_FAIL;
15266  return;
15267  }
15268 
15269  if (0 > MILLISECONDS) {
15270  otErr << __FUNCTION__ << ": Negative: MILLISECONDS passed in!\n";
15271  OT_FAIL;
15272  return;
15273  }
15274 
15275  const int64_t lMilliseconds = MILLISECONDS;
15276 
15277  OTLog::SleepMilliseconds(static_cast<int64_t>(lMilliseconds));
15278 }
15279 
15280 // Make sure you download your Nymbox (getNymbox) before calling this,
15281 // so when it loads the Nymbox it will have the latest version of it.
15282 //
15283 // Also, call createUserAccount() and pass the server reply message in
15284 // here, so that it can read theMessageNym (to sync the transaction
15285 // numbers.)
15286 //
15287 bool OTAPI_Exec::ResyncNymWithServer(const std::string& SERVER_ID,
15288  const std::string& USER_ID,
15289  const std::string& THE_MESSAGE) const
15290 {
15291  bool bIsInitialized = OTAPI()->IsInitialized();
15292  if (!bIsInitialized) {
15293  otErr << __FUNCTION__
15294  << ": Not initialized; call OT_API::Init first.\n";
15295  OT_FAIL;
15296  }
15297 
15298  if (SERVER_ID.empty()) {
15299  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
15300  OT_FAIL;
15301  }
15302  if (USER_ID.empty()) {
15303  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15304  OT_FAIL;
15305  }
15306  if (THE_MESSAGE.empty()) {
15307  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15308  OT_FAIL;
15309  }
15310 
15311  OTIdentifier theServerID(SERVER_ID), theNymID(USER_ID);
15312  const OTString strMessage(THE_MESSAGE), strNymID(theNymID);
15313 
15314  OTPseudonym* pNym = OTAPI()->GetOrLoadPrivateNym(theNymID, false);
15315  if (nullptr == pNym) return false;
15316  OTMessage theMessage;
15317 
15318  if (!theMessage.LoadContractFromString(strMessage)) {
15319  otErr << __FUNCTION__ << ": Failed trying to load @createUserAccount() "
15320  "message from string (it's a server reply.) "
15321  "Contents:\n\n" << strMessage << "\n\n";
15322  return false;
15323  }
15324  if (!strNymID.Compare(theMessage.m_strNymID)) {
15325  otErr << __FUNCTION__
15326  << ": Failed. Though success loading message from string, it had "
15327  "the wrong NymID. (Expected " << strNymID << ", but found "
15328  << theMessage.m_strNymID << ".) Message contents:\n\n"
15329  << strMessage << "\n\n";
15330  return false;
15331  }
15332  if (!theMessage.m_strCommand.Compare("@createUserAccount")) {
15333  otErr << __FUNCTION__ << ": Failed. Though success loading message "
15334  "from string, it had the wrong command type. "
15335  "(Expected @createUserAccount, but found "
15336  << theMessage.m_strCommand << ".) Message contents:\n\n"
15337  << strMessage << "\n\n";
15338  return false;
15339  }
15340  if (!theMessage.m_ascPayload.Exists()) {
15341  otErr << __FUNCTION__
15342  << ": Failed. Though success loading @createUserAccount() "
15343  "message, the payload was empty. (Expected theMessageNym to "
15344  "be there, so I could re-sync client side to server.) Message "
15345  "contents:\n\n" << strMessage << "\n\n";
15346  return false;
15347  }
15348  OTString strMessageNym;
15349 
15350  if (!theMessage.m_ascPayload.GetString(strMessageNym)) {
15351  otErr << __FUNCTION__ << ": Failed decoding message payload in server "
15352  "reply: @createUserAccount(). (Expected "
15353  "theMessageNym to be there, so I could "
15354  "re-sync client side to server.) Message "
15355  "contents:\n\n" << strMessage << "\n\n";
15356  return false;
15357  }
15358  OTPseudonym theMessageNym; // <====================
15359 
15360  if (!theMessageNym.LoadFromString(strMessageNym)) {
15361  otErr << __FUNCTION__ << ": Failed loading theMessageNym from a "
15362  "string. String contents:\n\n" << strMessageNym
15363  << "\n\n";
15364  return false;
15365  }
15366  // Based on serverID and UserID, load the Nymbox.
15367  //
15368  OTLedger theNymbox(theNymID, theNymID, theServerID); // <===========
15369 
15370  bool bSynced = false;
15371  bool bLoadedNymbox =
15372  (theNymbox.LoadNymbox() && theNymbox.VerifyAccount(*pNym));
15373 
15374  if (bLoadedNymbox)
15375  bSynced = OTAPI()->ResyncNymWithServer(*pNym, theNymbox, theMessageNym);
15376  else
15377  otErr << __FUNCTION__
15378  << ": Failed while loading or verifying Nymbox for User "
15379  << strNymID << ", on Server " << SERVER_ID << " \n";
15380 
15381  return bSynced;
15382 }
15383 
15384 // QUERY ASSET TYPES (server message)
15385 //
15386 // This way you can ask the server to confirm whether various
15387 // asset types are issued there. You must prepare the encoded
15388 // StringMap in advance of calling this function.
15389 //
15390 
15391 // Returns int32_t:
15392 // -1 means error; no message was sent.
15393 // -2 means the message was sent, but the request number must be passed as a
15394 // string, so call OTAPI_Exec::GetLargeRequestNum.
15395 // 0 means NO error, but also: no message was sent.
15396 // >0 means NO error, and the message was sent, and the request number fits into
15397 // an integer...
15398 // ...and in fact the requestNum IS the return value!
15399 // ===> In 99% of cases, this LAST option is what actually happens!!
15400 //
15401 int32_t OTAPI_Exec::queryAssetTypes(const std::string& SERVER_ID,
15402  const std::string& USER_ID,
15403  const std::string& ENCODED_MAP) const
15404 {
15405  if (SERVER_ID.empty()) {
15406  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
15407  OT_FAIL;
15408  }
15409  if (USER_ID.empty()) {
15410  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15411  OT_FAIL;
15412  }
15413  if (ENCODED_MAP.empty()) {
15414  otErr << __FUNCTION__ << ": Null: ENCODED_MAP passed in!\n";
15415  OT_FAIL;
15416  }
15417 
15418  OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID);
15419  OTASCIIArmor theArmor(ENCODED_MAP);
15420 
15421  return OTAPI()->queryAssetTypes(theServerID, theUserID, theArmor);
15422 }
15423 
15424 // GET MESSAGE PAYLOAD
15425 //
15426 // This way you can retrieve the payload from any message.
15427 // Useful, for example, for getting the encoded StringMap object
15428 // from the queryAssetTypes and @queryAssetTypes messages, which both
15429 // use the m_ascPayload field to transport it.
15430 //
15431 std::string OTAPI_Exec::Message_GetPayload(const std::string& THE_MESSAGE) const
15432 {
15433  if (THE_MESSAGE.empty()) {
15434  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15435  OT_FAIL;
15436  }
15437 
15438  OTString strMessage(THE_MESSAGE);
15439  OTMessage theMessage;
15440 
15441  if (!strMessage.Exists() || !theMessage.LoadContractFromString(strMessage))
15442  return "";
15443 
15444  std::string pBuf = theMessage.m_ascPayload.Get();
15445 
15446  return pBuf;
15447 }
15448 
15449 // GET MESSAGE COMMAND TYPE
15450 //
15451 // This way you can discover what kind of command it was.
15452 // All server replies are pre-pended with the @ sign. For example, if
15453 // you send a "getAccount" message, the server reply is "@getAccount",
15454 // and if you send "getMint" the reply is "@getMint", and so on.
15455 //
15456 std::string OTAPI_Exec::Message_GetCommand(const std::string& THE_MESSAGE) const
15457 {
15458  if (THE_MESSAGE.empty()) {
15459  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15460  OT_FAIL;
15461  }
15462 
15463  OTString strMessage(THE_MESSAGE);
15464 
15465  OTMessage theMessage;
15466 
15467  if (!strMessage.Exists() || !theMessage.LoadContractFromString(strMessage))
15468  return "";
15469 
15470  OTString strOutput(theMessage.m_strCommand);
15471 
15472  std::string pBuf = strOutput.Get();
15473 
15474  return pBuf;
15475 }
15476 
15477 // GET MESSAGE LEDGER
15478 //
15479 // If you just received a server response to a transaction, and
15480 // you want to actually iterate through the transactions in the
15481 // response ledger for that transaction, this function will retrieve
15482 // that ledger for you.
15483 //
15484 std::string OTAPI_Exec::Message_GetLedger(const std::string& THE_MESSAGE) const
15485 {
15486  if (THE_MESSAGE.empty()) {
15487  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15488  OT_FAIL;
15489  }
15490 
15491  OTString strMessage(THE_MESSAGE);
15492 
15493  OTMessage theMessage;
15494 
15495  if (!strMessage.Exists() ||
15496  !theMessage.LoadContractFromString(strMessage)) {
15497  otOut << __FUNCTION__ << ": Unable to load message.\n";
15498  return "";
15499  }
15500 
15501  // It's not a transaction request or response, so the Payload wouldn't
15502  // contain a ledger. (Don't want to pass back whatever it DOES contain
15503  // in that case, now do I?)
15504  //
15505  if ((false == theMessage.m_strCommand.Compare("notarizeTransactions")) &&
15506  (false == theMessage.m_strCommand.Compare("@notarizeTransactions"))) {
15507  otOut << __FUNCTION__
15508  << ": Wrong message type: " << theMessage.m_strCommand << "\n";
15509  return "";
15510  }
15511 
15512  // The ledger is stored in the Payload, we'll grab it into the String.
15513  OTString strOutput(theMessage.m_ascPayload);
15514 
15515  if (!strOutput.Exists()) {
15516  otOut << __FUNCTION__ << ": No ledger found on message.\n";
15517  return "";
15518  }
15519 
15520  std::string pBuf = strOutput.Get();
15521 
15522  return pBuf;
15523 }
15524 
15525 // GET NEW ASSET TYPE ID
15526 //
15527 // If you just issued a new asset type, you'll want to read the
15528 // server reply and get the new asset type ID out of it.
15529 // Otherwise how will you ever open accounts in that new type?
15530 //
15532  const std::string& THE_MESSAGE) const
15533 {
15534  if (THE_MESSAGE.empty()) {
15535  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15536  OT_FAIL;
15537  }
15538 
15539  OTString strMessage(THE_MESSAGE);
15540 
15541  OTMessage theMessage;
15542 
15543  if (!strMessage.Exists() ||
15544  !theMessage.LoadContractFromString(strMessage)) {
15545  otOut << __FUNCTION__ << ": Unable to load message.\n";
15546  return "";
15547  }
15548 
15549  // It's not a transaction request or response, so the Payload wouldn't
15550  // contain a ledger. (Don't want to pass back whatever it DOES contain
15551  // in that case, now do I?)
15552  //
15553  if ((false == theMessage.m_strCommand.Compare("@issueAssetType")) &&
15554  (false == theMessage.m_strCommand.Compare("@issueBasket"))) {
15555  otOut << __FUNCTION__
15556  << ": Wrong message type: " << theMessage.m_strCommand << "\n";
15557  return "";
15558  }
15559 
15560  OTString strOutput(theMessage.m_strAssetID);
15561 
15562  if (!strOutput.Exists()) {
15563  otOut << __FUNCTION__ << ": No new asset type ID found on message.\n";
15564  return "";
15565  }
15566 
15567  std::string pBuf = strOutput.Get();
15568 
15569  return pBuf;
15570 }
15571 
15572 // GET NEW ISSUER ACCOUNT ID
15573 //
15574 // If you just issued a new asset type, you'll want to read the
15575 // server reply and get the new issuer acct ID out of it.
15576 // Otherwise how will you ever issue anything with it?
15577 //
15579  const std::string& THE_MESSAGE) const
15580 {
15581  if (THE_MESSAGE.empty()) {
15582  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15583  OT_FAIL;
15584  }
15585 
15586  OTString strMessage(THE_MESSAGE);
15587 
15588  OTMessage theMessage;
15589 
15590  if (!strMessage.Exists() ||
15591  !theMessage.LoadContractFromString(strMessage)) {
15592  otOut << __FUNCTION__ << ": Unable to load message.\n";
15593  return "";
15594  }
15595 
15596  // It's not an issue asset type response, so the m_strAcctID wouldn't
15597  // contain an issuer account ID. (Don't want to pass back whatever it DOES
15598  // contain
15599  // in that case, now do I?)
15600  //
15601  if (!theMessage.m_strCommand.Compare("@issueAssetType")) {
15602  otOut << __FUNCTION__
15603  << ": Wrong message type: " << theMessage.m_strCommand << "\n";
15604  return "";
15605  }
15606 
15607  OTString strOutput(theMessage.m_strAcctID);
15608 
15609  if (!strOutput.Exists()) {
15610  otOut << __FUNCTION__ << ": No issuer account ID found on message.\n";
15611  return "";
15612  }
15613 
15614  std::string pBuf = strOutput.Get();
15615 
15616  return pBuf;
15617 }
15618 
15619 // GET NEW ACCOUNT ID
15620 //
15621 // If you just created a new asset account, you'll want to read the
15622 // server reply and get the new acct ID out of it.
15623 // Otherwise how will you ever use it?
15624 // This function allows you to get the new account ID out of the
15625 // server reply message.
15626 //
15628  const std::string& THE_MESSAGE) const
15629 {
15630  if (THE_MESSAGE.empty()) {
15631  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15632  OT_FAIL;
15633  }
15634 
15635  OTString strMessage(THE_MESSAGE);
15636 
15637  OTMessage theMessage;
15638 
15639  if (!strMessage.Exists() ||
15640  !theMessage.LoadContractFromString(strMessage)) {
15641  otOut << __FUNCTION__ << ": Unable to load message.\n";
15642  return "";
15643  }
15644 
15645  // It's not a response to createAccount, so the m_strAcctID wouldn't
15646  // contain a new account ID anyway, right? (Don't want to pass back whatever
15647  // it DOES contain in that case, now do I?)
15648  //
15649  if (!theMessage.m_strCommand.Compare("@createAccount")) {
15650  otOut << __FUNCTION__
15651  << ": Wrong message type: " << theMessage.m_strCommand << "\n";
15652  return "";
15653  }
15654 
15655  OTString strOutput(theMessage.m_strAcctID);
15656 
15657  if (!strOutput.Exists()) {
15658  otOut << __FUNCTION__ << ": No asset account ID found on message.\n";
15659  return "";
15660  }
15661 
15662  std::string pBuf = strOutput.Get();
15663 
15664  return pBuf;
15665 }
15666 
15667 // GET NYMBOX HASH
15668 //
15669 // Some messages include a copy of the Nymbox Hash. This helps the
15670 // server to quickly ascertain whether some messages will fail, and
15671 // also allows the client to query the server for this information
15672 // for syncronicity purposes.
15673 //
15675  const std::string& THE_MESSAGE) const
15676 {
15677  if (THE_MESSAGE.empty()) {
15678  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15679  OT_FAIL;
15680  }
15681 
15682  OTString strMessage(THE_MESSAGE);
15683 
15684  OTMessage theMessage;
15685 
15686  if (!strMessage.Exists() ||
15687  !theMessage.LoadContractFromString(strMessage)) {
15688  otOut << __FUNCTION__ << ": Unable to load message.\n";
15689  return "";
15690  }
15691 
15692  // So far these are the only messages that use m_strNymboxHash:
15693  if ((false == theMessage.m_strCommand.Compare("processNymbox")) &&
15694  (false == theMessage.m_strCommand.Compare("notarizeTransactions")) &&
15695  (false == theMessage.m_strCommand.Compare("getTransactionNum")) &&
15696  (false == theMessage.m_strCommand.Compare("processInbox")) &&
15697  (false == theMessage.m_strCommand.Compare("triggerClause")) &&
15698  (false == theMessage.m_strCommand.Compare("@getNymbox")) &&
15699  (false == theMessage.m_strCommand.Compare("@getRequest")) &&
15700  (false == theMessage.m_strCommand.Compare("@getTransactionNum"))) {
15701  otOut << __FUNCTION__
15702  << ": Wrong message type : " << theMessage.m_strCommand
15703  << " \nFYI, with m_strNymboxHash : " << theMessage.m_strNymboxHash
15704  << "\n";
15705  return "";
15706  }
15707 
15708  if (!theMessage.m_strNymboxHash.Exists()) {
15709  otOut << __FUNCTION__
15710  << ": No NymboxHash found on message: " << strMessage << "\n";
15711  return "";
15712  }
15713 
15714  OTString strOutput(theMessage.m_strNymboxHash);
15715  std::string pBuf = strOutput.Get();
15716 
15717  return pBuf;
15718 }
15719 
15720 // GET MESSAGE SUCCESS (True or False)
15721 //
15722 // Returns true (1) for Success and false (0) for Failure.
15723 //
15724 // NEW: returns (-1) for error!
15725 //
15726 int32_t OTAPI_Exec::Message_GetSuccess(const std::string& THE_MESSAGE) const
15727 {
15728  if (THE_MESSAGE.empty()) {
15729  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15730  OT_FAIL;
15731  }
15732 
15733  OTMessage theMessage;
15734  OTString strMessage(THE_MESSAGE);
15735 
15736  if (!strMessage.Exists()) {
15737  otErr << __FUNCTION__ << ": Error: THE_MESSAGE doesn't exist.\n";
15738  return OT_ERROR;
15739  }
15740 
15741  if (!theMessage.LoadContractFromString(strMessage)) {
15742  otErr << __FUNCTION__
15743  << ": Error: Failed loading message from string:\n\n"
15744  << THE_MESSAGE << "\n\n";
15745  return OT_ERROR;
15746  }
15747  if (true == theMessage.m_bSuccess) {
15748  otInfo << __FUNCTION__ << ": Server reply for RequestNum "
15749  << StringToLong(theMessage.m_strRequestNum.Get())
15750  << "(Message_GetSuccess was successful, but any transaction "
15751  "inside could have failed OR succeeded. Use "
15752  "Message_GetTransactionSuccess for that.)\n"; // Contents:
15753  // \n\n" <<
15754  // THE_MESSAGE
15755  // << "\n\n"
15756  return OT_TRUE;
15757  }
15758  else {
15759  otWarn << __FUNCTION__ << ": ** FYI, server reply was received, and it "
15760  "said 'No.' (Status = failed). RequestNum: "
15761  << StringToLong(theMessage.m_strRequestNum.Get())
15762  << "\n"; // Contents:\n\n" << THE_MESSAGE << "\n\n"
15763  }
15764  return OT_FALSE;
15765 }
15766 
15767 // GET MESSAGE "DEPTH" (USED FOR MARKET-SPECIFIC MESSAGES.)
15768 //
15769 // Returns the count of relevant items, so you know whether to bother reading
15770 // the payload.
15771 // Returns -1 if error.
15772 //
15773 // The "depth" variable stores the count of items being returned.
15774 // For example, if I call getMarketList, and 10 markets are returned,
15775 // then depth will be set to 10. OR, if I call getNym_MarketOffers, and
15776 // the Nym has 16 offers on the various markets, then the depth will be 16.
15777 //
15778 // This value is important when processing server replies to market inquiries.
15779 // If the depth is 0, then you are done. End. BUT! if it contains a number, such
15780 // as 10,
15781 // then that means you will want to next READ those 10 markets (or offers, or
15782 // trades, etc)
15783 // out of the server reply's payload.
15784 //
15785 // Whereas if success is TRUE, but depth is 0, that means while the message
15786 // processed
15787 // successfully, the list was simply empty (and thus it would be a waste of time
15788 // trying
15789 // to unpack the non-existent, empty list of data items from the payload of your
15790 // successful
15791 // reply.)
15792 //
15793 int32_t OTAPI_Exec::Message_GetDepth(const std::string& THE_MESSAGE) const
15794 {
15795  if (THE_MESSAGE.empty()) {
15796  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15797  OT_FAIL;
15798  }
15799 
15800  OTString strMessage(THE_MESSAGE);
15801 
15802  OTMessage theMessage;
15803 
15804  if (!strMessage.Exists() || !theMessage.LoadContractFromString(strMessage))
15805  return OT_ERROR;
15806 
15807  return static_cast<int32_t>(theMessage.m_lDepth);
15808 }
15809 
15810 // GET MESSAGE TRANSACTION "IS CANCELLED" (True or False)
15811 //
15812 // Returns true (1) for Success and false (0) for Failure.
15813 // also returns (-1) for Error
15814 //
15816  const std::string& SERVER_ID, const std::string& USER_ID,
15817  const std::string& ACCOUNT_ID, const std::string& THE_MESSAGE) const
15818 {
15819  if (SERVER_ID.empty()) {
15820  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
15821  OT_FAIL;
15822  }
15823  if (USER_ID.empty()) {
15824  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15825  OT_FAIL;
15826  }
15827  if (ACCOUNT_ID.empty()) {
15828  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
15829  OT_FAIL;
15830  }
15831  if (THE_MESSAGE.empty()) {
15832  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15833  OT_FAIL;
15834  }
15835 
15836  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
15837  theAccountID(ACCOUNT_ID);
15838 
15839  OTString strMessage(THE_MESSAGE);
15840 
15841  OTMessage theMessage;
15842 
15843  if (!strMessage.Exists() ||
15844  !theMessage.LoadContractFromString(strMessage)) {
15845  otOut << __FUNCTION__ << ": Unable to load message.\n";
15846  return OT_ERROR;
15847  }
15848 
15849  // It's not a transaction request or response, so the Payload wouldn't
15850  // contain a ledger. (Don't want to pass back whatever it DOES contain
15851  // in that case, now do I?)
15852  //
15853  if ((false == theMessage.m_strCommand.Compare("@notarizeTransactions")) &&
15854  (false == theMessage.m_strCommand.Compare("@processInbox")) &&
15855  (false == theMessage.m_strCommand.Compare("@processNymbox"))) {
15856  otOut << __FUNCTION__
15857  << ": Wrong message type: " << theMessage.m_strCommand << "\n";
15858  return OT_ERROR;
15859  }
15860 
15861  // The ledger is stored in the Payload, we'll grab it into the String.
15862  OTString strLedger(theMessage.m_ascPayload);
15863 
15864  if (!strLedger.Exists()) {
15865  otOut << __FUNCTION__ << ": No ledger found on message.\n";
15866  return OT_ERROR;
15867  }
15868 
15869  OTLedger theLedger(theUserID, theAccountID, theServerID);
15870 
15871  if (!theLedger.LoadContractFromString(strLedger)) {
15872  OTString strAcctID(theAccountID);
15873  otErr << __FUNCTION__
15874  << ": Error loading ledger from string. Acct ID: " << strAcctID
15875  << "\n";
15876  return OT_ERROR;
15877  }
15878 
15879  // At this point, I know theLedger loaded successfully.
15880 
15881  if (theLedger.GetTransactionCount() <= 0) {
15882  otErr << __FUNCTION__ << ": bad count in message ledger: "
15883  << theLedger.GetTransactionCount() << "\n";
15884  return OT_ERROR; // out of bounds. I'm saving from an OT_ASSERT_MSG()
15885  // happening here. (Maybe I shouldn't.)
15886  }
15887 
15888  OTTransaction* pTransaction = theLedger.GetTransactionByIndex(
15889  0); // Right now this is a defacto standard. (only 1 transaction per
15890  // message ledger, excepting process inbox.)
15891 
15892  if (nullptr == pTransaction) {
15893  otErr << __FUNCTION__
15894  << ": good index but uncovered \"\" pointer: " << 0 << "\n";
15895  return OT_ERROR; // Weird.
15896  }
15897 
15898  // At this point, I actually have the transaction pointer, so let's return
15899  // its 'canceled' status
15900  //
15901  if (pTransaction->IsCancelled()) return OT_TRUE;
15902 
15903  return OT_FALSE;
15904 }
15905 
15906 // GET MESSAGE TRANSACTION SUCCESS (True or False)
15907 //
15908 // Returns true (1) for Success and false (0) for Failure.
15909 // also returns (-1) for Error
15910 //
15912  const std::string& SERVER_ID, const std::string& USER_ID,
15913  const std::string& ACCOUNT_ID, const std::string& THE_MESSAGE) const
15914 {
15915  if (SERVER_ID.empty()) {
15916  otErr << __FUNCTION__ << ": Null: SERVER_ID passed in!\n";
15917  OT_FAIL;
15918  }
15919  if (USER_ID.empty()) {
15920  otErr << __FUNCTION__ << ": Null: USER_ID passed in!\n";
15921  OT_FAIL;
15922  }
15923  if (ACCOUNT_ID.empty()) {
15924  otErr << __FUNCTION__ << ": Null: ACCOUNT_ID passed in!\n";
15925  OT_FAIL;
15926  }
15927  if (THE_MESSAGE.empty()) {
15928  otErr << __FUNCTION__ << ": Null: THE_MESSAGE passed in!\n";
15929  OT_FAIL;
15930  }
15931 
15932  const OTIdentifier theServerID(SERVER_ID), theUserID(USER_ID),
15933  theAccountID(ACCOUNT_ID);
15934 
15935  OTString strMessage(THE_MESSAGE);
15936 
15937  OTMessage theMessage;
15938 
15939  if (!strMessage.Exists() ||
15940  !theMessage.LoadContractFromString(strMessage)) {
15941  otOut << __FUNCTION__ << ": Unable to load message.\n";
15942  return OT_ERROR;
15943  }
15944 
15945  // It's not a transaction request or response, so the Payload wouldn't
15946  // contain a ledger. (Don't want to pass back whatever it DOES contain
15947  // in that case, now do I?)
15948  //
15949  if ((false == theMessage.m_strCommand.Compare("@notarizeTransactions")) &&
15950  (false == theMessage.m_strCommand.Compare("@processInbox")) &&
15951  (false == theMessage.m_strCommand.Compare("@processNymbox"))) {
15952  otOut << __FUNCTION__
15953  << ": Wrong message type: " << theMessage.m_strCommand << "\n";
15954  return OT_ERROR;
15955  }
15956 
15957  // The ledger is stored in the Payload, we'll grab it into the String.
15958  OTString strLedger(theMessage.m_ascPayload);
15959 
15960  if (!strLedger.Exists()) {
15961  otOut << __FUNCTION__ << ": No ledger found on message.\n";
15962  return OT_ERROR;
15963  }
15964 
15965  OTLedger theLedger(theUserID, theAccountID, theServerID);
15966 
15967  if (!theLedger.LoadContractFromString(strLedger)) {
15968  OTString strAcctID(theAccountID);
15969  otErr << __FUNCTION__
15970  << ": Error loading ledger from string. Acct ID: " << strAcctID
15971  << "\n";
15972  return OT_ERROR;
15973  }
15974 
15975  // At this point, I know theLedger loaded successfully.
15976 
15977  if (theLedger.GetTransactionCount() <= 0) {
15978  otErr << __FUNCTION__ << ": bad count in message ledger: "
15979  << theLedger.GetTransactionCount() << "\n";
15980  return OT_ERROR; // out of bounds. I'm saving from an OT_ASSERT_MSG()
15981  // happening here. (Maybe I shouldn't.)
15982  }
15983 
15984  OTTransaction* pTransaction = theLedger.GetTransactionByIndex(
15985  0); // Right now this is a defacto standard. (only 1 transaction per
15986  // message ledger, excepting process inbox.)
15987 
15988  if (nullptr == pTransaction) {
15989  otErr << __FUNCTION__
15990  << ": good index but uncovered \"\" pointer: " << 0 << "\n";
15991  return OT_ERROR; // Weird.
15992  }
15993 
15994  // At this point, I actually have the transaction pointer, so let's return
15995  // its success status
15996  //
15997  if (pTransaction->GetSuccess())
15998  return OT_TRUE;
15999  else {
16000  const int64_t lRequestNum =
16001  StringToLong(theMessage.m_strRequestNum.Get());
16002  const int64_t lTransactionNum = pTransaction->GetTransactionNum();
16003 
16004  otWarn << __FUNCTION__
16005  << ": ** FYI, server reply was received, and it said 'No.' "
16006  "(Status = failed). RequestNum: " << lRequestNum
16007  << ", TransNum: " << lTransactionNum
16008  << "\n"; // Contents: \n\n" << THE_MESSAGE << "\n\n"
16009  }
16010 
16011  return OT_FALSE;
16012 }
16013 
16014 } // namespace opentxs
EXPORT bool ResyncNymWithServer(OTPseudonym &theNym, const OTLedger &theNymbox, const OTPseudonym &theMessageNym) const
EXPORT bool GetAmount(int64_t &lOutput) const
Definition: OTPayment.cpp:502
EXPORT int32_t NumList_Count(const OTNumList &theList) const
EXPORT bool Nym_RemoveMailByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT int32_t GetIssuedNumCount(const OTIdentifier &theServerID) const
EXPORT std::string Message_GetNewAcctID(const std::string &THE_MESSAGE) const
EXPORT int32_t deleteUserAccount(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT void GetReferenceString(OTString &theStr) const
EXPORT int32_t GetServerCount() const
EXPORT bool ResyncNymWithServer(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &THE_MESSAGE) const
EXPORT std::string AddSignature(const std::string &SIGNER_NYM_ID, const std::string &THE_CONTRACT) const
EXPORT bool VerifyAccountReceipt(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID) const
EXPORT bool AddSignature(const OTIdentifier &theSignerNymID, const OTString &strContract, OTString &strOutput) const
EXPORT bool RemoveTransaction(int64_t lTransactionNum, bool bDeleteIt=true)
Definition: OTLedger.cpp:1168
OTLOG_IMPORT OTLogStream otLog4
EXPORT std::string SymmetricEncrypt(const std::string &SYMMETRIC_KEY, const std::string &PLAINTEXT) const
EXPORT std::string NumList_Add(const std::string &strNumList, const std::string &strNumbers) const
Definition: OTAPI_Exec.cpp:429
EXPORT std::string Transaction_GetSenderUserID(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
void SetAmount(int64_t lAmount)
Definition: OTItem.hpp:479
EXPORT int32_t AddAssetContract(const std::string &strContract) const
EXPORT OTItem * GenerateBalanceStatement(int64_t lAdjustment, const OTTransaction &theOwner, OTPseudonym &theNym, const OTAccount &theAccount, OTLedger &theOutbox)
Definition: OTLedger.cpp:1532
EXPORT bool GetServerID(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:993
EXPORT bool SetAccount_Name(const OTIdentifier &ACCT_ID, const OTIdentifier &SIGNER_NYM_ID, const OTString &ACCT_NEW_NAME) const
EXPORT bool Encrypt(const OTIdentifier &theRecipientNymID, const OTString &strPlaintext, OTString &strOutput) const
EXPORT std::string Party_GetAcctNameByIndex(const std::string &THE_CONTRACT, const std::string &PARTY_NAME, const int32_t &nIndex) const
EXPORT int32_t notarizeDeposit(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID, const std::string &THE_PURSE) const
EXPORT int32_t issueAssetType(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &THE_CONTRACT) const
EXPORT int32_t triggerClause(const std::string &SERVER_ID, const std::string &USER_ID, const int64_t &TRANSACTION_NUMBER, const std::string &CLAUSE_NAME, const std::string &STR_PARAM) const
static EXPORT int64_t StringToLong(const std::string &number)
Definition: OTString.cpp:677
int32_t GetTransactionCount() const
Definition: OTLedger.hpp:332
EXPORT int32_t issueBasket(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTString &BASKET_INFO) const
EXPORT std::string SmartContract_ConfirmAccount(const std::string &THE_CONTRACT, const std::string &SIGNER_NYM_ID, const std::string &PARTY_NAME, const std::string &ACCT_NAME, const std::string &AGENT_NAME, const std::string &ACCT_ID) const
EXPORT int32_t getBoxReceipt(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const int32_t &nBoxType, const int64_t &TRANSACTION_NUMBER) const
EXPORT int32_t GetHookCount() const
Definition: OTBylaw.hpp:238
EXPORT OTAgent * GetAgentByIndex(int32_t nIndex) const
Definition: OTParty.cpp:630
EXPORT std::string Bylaw_GetLanguage(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME) const
EXPORT time64_t Instrmnt_GetValidFrom(const std::string &THE_INSTRUMENT) const
EXPORT int32_t GetNymCount() const
EXPORT bool GetSenderAcctIDForDisplay(OTIdentifier &theReturnID)
EXPORT std::string Pending_GetNote(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
static EXPORT bool InitOTApp()
bool IsString() const
Definition: OTVariable.hpp:241
EXPORT bool GetRemitterAcctID(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:1050
static EXPORT OTTransaction * GenerateTransaction(const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, transactionType theType, int64_t lTransactionNum=0)
EXPORT bool AddBasketExchangeItem(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, Basket &theBasket, const OTIdentifier &ASSET_TYPE_ID, const OTIdentifier &ASSET_ACCT_ID) const
EXPORT int32_t Transaction_IsCanceled(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
EXPORT std::string Create_SmartContract(const std::string &SIGNER_NYM_ID, const time64_t &VALID_FROM, const time64_t &VALID_TO) const
const OTIdentifier & GetRequestAccountID()
Definition: Basket.hpp:283
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
EXPORT int32_t Party_GetAgentCount(const std::string &THE_CONTRACT, const std::string &PARTY_NAME) const
static EXPORT void Output(int32_t nVerbosity, const char *szOutput)
Definition: OTLog.cpp:710
EXPORT std::string LoadRecordBox(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID) const
NOTE: Sometimes the user ID is also passed in the &quot;account ID&quot; field,.
EXPORT void SetNumberOfOrigin(int64_t lTransactionNum)
EXPORT const OTSubcredential * GetSubcredential(const OTString &strSubID, const OTString::List *plistRevokedIDs=nullptr) const
static EXPORT bool CleanupOTApp()
EXPORT int32_t getMarketOffers(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &MARKET_ID, const int64_t &lDepth) const
EXPORT std::string SmartContract_AddBylaw(const std::string &THE_CONTRACT, const std::string &SIGNER_NYM_ID, const std::string &BYLAW_NAME) const
EXPORT bool LoadBoxReceipt(const int64_t &lTransactionNum)
Definition: OTLedger.cpp:393
EXPORT std::string GetAccountWallet_OutboxHash(const std::string &ACCOUNT_ID) const
OTVariable_Type GetType() const
Definition: OTVariable.hpp:224
EXPORT std::string SmartContract_AddParty(const std::string &THE_CONTRACT, const std::string &SIGNER_NYM_ID, const std::string &PARTY_NAME, const std::string &AGENT_NAME) const
EXPORT int32_t cancelCronItem(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ASSET_ACCT_ID, const int64_t &lTransactionNum) const
EXPORT std::string GetPartyName(bool *pBoolSuccess=nullptr) const
Definition: OTParty.cpp:489
EXPORT int32_t createAssetAccount(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ASSET_ID) const
EXPORT bool GetValidFrom(time64_t &tOutput) const
Definition: OTPayment.cpp:867
EXPORT std::string Purse_Pop(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &OWNER_OR_SIGNER_ID, const std::string &THE_PURSE) const
EXPORT int32_t Count() const
Definition: Purse.cpp:1641
EXPORT int32_t GetNym_SubcredentialCount(const std::string &NYM_ID, const std::string &MASTER_CRED_ID) const
Definition: OTAPI_Exec.cpp:820
EXPORT OTPseudonym * GetOrLoadNym(const OTIdentifier &NYM_ID, bool bChecking=false, const char *szFuncName=nullptr, const OTPasswordData *pPWData=nullptr) const
EXPORT std::string GetActiveCronItem(const std::string &SERVER_ID, int64_t lTransNum) const
Definition: OTAPI_Exec.cpp:631
EXPORT OTClause * GetClauseByIndex(int32_t nIndex)
Definition: OTBylaw.cpp:642
EXPORT std::string CreateAssetContract(const std::string &NYM_ID, const std::string &strXMLcontents) const
EXPORT bool DiscardCheque(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID, const std::string &THE_CHEQUE) const
EXPORT std::string CalculateServerContractID(const std::string &str_Contract) const
EXPORT std::string GetAssetType_Name(const std::string &ASSET_TYPE_ID) const
EXPORT bool Smart_AreAllPartiesConfirmed(const std::string &THE_CONTRACT) const
static EXPORT uint64_t StringToUlong(const std::string &number)
Definition: OTString.cpp:662
EXPORT std::string CreateServerContract(const std::string &NYM_ID, const std::string &strXMLcontents) const
EXPORT bool SetServer_Name(const std::string &SERVER_ID, const std::string &STR_NEW_NAME) const
OTString m_strAcctID
Definition: OTMessage.hpp:205
EXPORT bool LoadFromString(const OTString &strNym, OTString::Map *pMapCredentials=nullptr, OTString *pstrReason=nullptr, const OTPassword *pImportPassword=nullptr)
EXPORT int32_t killMarketOffer(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ASSET_ACCT_ID, const int64_t &TRANSACTION_NUMBER) const
const int32_t OT_FALSE
Definition: OTAPI_Exec.cpp:180
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
Definition: OTMessage.cpp:3898
EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
EXPORT int32_t sendUserMessage(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &USER_ID_RECIPIENT, const std::string &RECIPIENT_PUBKEY, const std::string &THE_MESSAGE) const
EXPORT std::string CreateSymmetricKey() const
EXPORT bool IsPasswordProtected() const
Definition: Purse.hpp:272
EXPORT bool VerifyThisAgainstAllPartiesSignedCopies()
EXPORT void SetHomeFolder(const std::string &strFolder) const
Definition: OTAPI_Exec.cpp:276
EXPORT void GetAttachment(OTString &theStr) const
Definition: OTItem.cpp:1397
EXPORT bool RecordPayment(const std::string &SERVER_ID, const std::string &USER_ID, const bool &bIsInbox, const int32_t &nIndex, const bool &bSaveCopy) const
EXPORT std::string PeekMemlogFront() const
Definition: OTAPI_Exec.cpp:383
EXPORT int32_t Transaction_GetBalanceAgreementSuccess(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
EXPORT bool ClearExpired(const std::string &SERVER_ID, const std::string &USER_ID, const int32_t &nIndex, const bool &bClearAll) const
EXPORT OTAgent * GetAgent(const std::string &str_agent_name) const
Definition: OTParty.cpp:609
EXPORT int64_t GetBasketMinimumTransferAmount(const OTIdentifier &BASKET_ASSET_TYPE_ID) const
EXPORT std::string Party_GetAgentID(const std::string &THE_CONTRACT, const std::string &PARTY_NAME, const std::string &AGENT_NAME) const
EXPORT std::string Instrmnt_GetAssetID(const std::string &THE_INSTRUMENT) const
EXPORT std::string GetMemlogAtIndex(const int32_t &nIndex) const
Definition: OTAPI_Exec.cpp:378
EXPORT std::string GetServer_ID(const int32_t &nIndex) const
EXPORT std::string GetNym_MailContentsByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT std::string Purse_Push(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &SIGNER_ID, const std::string &OWNER_ID, const std::string &THE_PURSE, const std::string &THE_TOKEN) const
EXPORT int32_t issueBasket(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &THE_BASKET) const
EXPORT int32_t queryAssetTypes(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTASCIIArmor &ENCODED_MAP) const
virtual EXPORT bool VerifyAccount(const OTPseudonym &theNym)
Definition: OTLedger.cpp:187
EXPORT bool Decode(const OTString &strEncoded, OTString &strOutput, bool bLineBreaks=true) const
EXPORT OT_API * OTAPI() const
Definition: OTAPI_Exec.cpp:281
EXPORT int32_t issueMarketOffer(const std::string &ASSET_ACCT_ID, const std::string &CURRENCY_ACCT_ID, const int64_t &MARKET_SCALE, const int64_t &MINIMUM_INCREMENT, const int64_t &TOTAL_ASSETS_ON_OFFER, const int64_t &PRICE_LIMIT, const bool &bBuyingOrSelling, const time64_t &LIFESPAN_IN_SECONDS, const std::string &STOP_SIGN, const int64_t &ACTIVATION_PRICE) const
EXPORT const OTIdentifier & GetAssetTypeID() const
Definition: OTAccount.cpp:449
EXPORT int32_t checkServerID(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
int64_t GetTransactionNum() const
bool IsImportant() const
Definition: OTVariable.hpp:208
EXPORT std::string GetNym_OutmailContentsByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT std::string LoadPubkey_Encryption(const std::string &USER_ID) const
EXPORT std::string Transaction_GetType(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
Get Transaction Type (internally uses GetTransactionTypeString().)
EXPORT int32_t AddServerContract(const std::string &strContract) const
EXPORT int32_t GetServerCount() const
EXPORT time64_t GetTime() const
EXPORT char const * GetTypeString() const
Definition: OTAccount.hpp:271
EXPORT bool GetNymID(OTIdentifier &theOutput) const
Definition: OTAgent.cpp:473
static EXPORT bool PopMemlogBack()
Definition: OTLog.cpp:592
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 int64_t GetBalance() const
Definition: OTAccount.cpp:664
EXPORT OTCredential * GetMasterCredential(const OTString &strID)
EXPORT int32_t GetNym_RevokedCredCount(const std::string &NYM_ID) const
Definition: OTAPI_Exec.cpp:755
EXPORT std::string GetAssetType_TLA(const std::string &THE_ID) const
EXPORT bool SetNym_Name(const OTIdentifier &NYM_ID, const OTIdentifier &SIGNER_NYM_ID, const OTString &NYM_NEW_NAME) const
EXPORT bool ClearRecord(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const int32_t &nIndex, const bool &bClearAll) const
EXPORT std::string Wallet_GetServerIDFromPartial(const std::string &PARTIAL_ID) 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
EXPORT std::string GetServer_Contract(const std::string &SERVER_ID) const
EXPORT int64_t GetBasketMemberMinimumTransferAmount(const OTIdentifier &BASKET_ASSET_TYPE_ID, int32_t nIndex) const
EXPORT std::string Party_GetAcctAssetID(const std::string &THE_CONTRACT, const std::string &PARTY_NAME, const std::string &ACCT_NAME) const
EXPORT int32_t notarizeTransfer(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_FROM, const OTIdentifier &ACCT_TO, const int64_t &AMOUNT, const OTString &NOTE) const
EXPORT bool SaveContract()
static EXPORT OTScriptable * InstantiateScriptable(const OTString &strInput)
EXPORT time64_t Token_GetValidTo(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &THE_TOKEN) const
EXPORT bool VerifyIssuedNum(const OTString &strServerID, const int64_t &lTransNum) const
EXPORT int32_t getNym_MarketOffers(const std::string &SERVER_ID, const std::string &USER_ID) const
This &quot;Market Offer&quot; data is a lot more detailed than the.
EXPORT std::string Variable_GetNameByIndex(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const int32_t &nIndex) const
EXPORT bool GetRecipientAcctIDForDisplay(OTIdentifier &theReturnID)
EXPORT int32_t getAccountFiles(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID) const
EXPORT int64_t Basket_GetMinimumTransferAmount(const std::string &BASKET_ASSET_TYPE_ID) const
EXPORT std::string GetAccountWallet_InboxHash(const std::string &ACCOUNT_ID) const
EXPORT int32_t getMarketRecentTrades(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &MARKET_ID) const
EXPORT void FlushMessageBuffer() const
EXPORT bool AllPartiesHaveSupposedlyConfirmed()
#define OT_ERROR_AMOUNT
Definition: Common.hpp:166
EXPORT const OTString & GetName() const
EXPORT OTBylaw * GetBylaw(std::string str_bylaw_name) const
virtual bool VerifyAccount(const OTPseudonym &theNym)
EXPORT std::string GetNym_RevokedCredID(const std::string &NYM_ID, const int32_t &nIndex) const
Definition: OTAPI_Exec.cpp:773
EXPORT bool GetNextTransactionNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, int64_t &lTransNum, bool bSave=true)
EXPORT std::string Clause_GetNameByIndex(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const int32_t &nIndex) const
EXPORT int32_t getMint(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ASSET_ID) const
EXPORT std::string Hook_GetClauseAtIndex(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const std::string &HOOK_NAME, const int32_t &nIndex) const
EXPORT int32_t Message_GetDepth(const std::string &THE_MESSAGE) const
EXPORT bool LoadInbox()
Definition: OTLedger.cpp:463
EXPORT std::string VerifyAndRetrieveXMLContents(const std::string &THE_CONTRACT, const std::string &SIGNER_ID) const
EXPORT std::string SignContract(const std::string &SIGNER_NYM_ID, const std::string &THE_CONTRACT) const
EXPORT int32_t getInbox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID) const
EXPORT OTClause * GetCallback(std::string str_CallbackName)
Definition: OTBylaw.cpp:468
EXPORT std::string GetNym_Name(const std::string &NYM_ID) const
Returns Nym Name (based on NymID)
EXPORT std::string LoadPurse(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &USER_ID) const
EXPORT int32_t notarizeWithdrawal(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID, const int64_t &AMOUNT) const
EXPORT int32_t processInbox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID, const OTString &ACCT_LEDGER) const
EXPORT std::string Message_GetPayload(const std::string &THE_MESSAGE) const
EXPORT int64_t Token_GetDenomination(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &THE_TOKEN) const
The actual cash value of the token. Returns a int64_t.
EXPORT void AddServerContract(const OTServerContract &theContract)
Definition: OTWallet.cpp:725
EXPORT std::string EasyProposePlan(const std::string &SERVER_ID, const std::string &DATE_RANGE, const std::string &SENDER_ACCT_ID, const std::string &SENDER_USER_ID, const std::string &PLAN_CONSIDERATION, const std::string &RECIPIENT_ACCT_ID, const std::string &RECIPIENT_USER_ID, const std::string &INITIAL_PAYMENT, const std::string &PAYMENT_PLAN, const std::string &PLAN_EXPIRY) const
EXPORT int32_t getMint(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ASSET_ID) const
EXPORT std::string LoadOutbox(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID) const
EXPORT int32_t GetNym_OutmailCount(const std::string &NYM_ID) const
EXPORT void GetName(OTString &strName) const
Definition: OTContract.hpp:360
EXPORT int32_t Token_GetSeries(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &THE_TOKEN) const
EXPORT bool RemoveOutmailByIndex(int32_t nIndex)
EXPORT bool VerifySignature(const OTString &strContract, const OTIdentifier &theSignerNymID, OTContract **ppContract=nullptr) const
EXPORT bool GetTransactionNum(int64_t &lOutput) const
Definition: OTPayment.cpp:832
EXPORT bool SetServer_Name(const OTIdentifier &SERVER_ID, const OTString &STR_NEW_NAME) const
EXPORT int32_t SmartContract_CountNumsNeeded(const std::string &THE_CONTRACT, const std::string &AGENT_NAME) const
EXPORT bool DoesBoxReceiptExist(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID, int32_t nBoxType, const int64_t &lTransactionNum) const
EXPORT int32_t usageCredits(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &USER_ID_CHECK, const int64_t &ADJUSTMENT) const
EXPORT uint64_t StringToUlong(const std::string &strNumber) const
Definition: OTAPI_Exec.cpp:302
EXPORT const OTAsymmetricKey & GetPublicEncrKey() const
EXPORT const OTString & GetCurrencyTLA() const
static EXPORT void SetAppBinaryFolder(OTString strLocation)
Definition: OTPaths.cpp:235
EXPORT bool PopMemlogFront() const
Definition: OTAPI_Exec.cpp:393
EXPORT OTWallet * GetWallet(const char *szFuncName=nullptr) const
EXPORT int32_t activateSmartContract(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTString &THE_SMART_CONTRACT) const
EXPORT std::string GetAssetType_ID(const int32_t &nIndex) const
EXPORT bool AddBasketCreationItem(const OTIdentifier &USER_ID, Basket &theBasket, const OTIdentifier &ASSET_TYPE_ID, int64_t MINIMUM_TRANSFER) const
static EXPORT OTString GetMemlogAtIndex(int32_t nIndex)
Definition: OTLog.cpp:499
EXPORT bool GetInboxHash(const std::string &acct_id, OTIdentifier &theOutput) const
EXPORT bool AddTransaction(OTTransaction &theTransaction)
Definition: OTLedger.cpp:1194
EXPORT std::string Message_GetLedger(const std::string &THE_MESSAGE) const
EXPORT bool SetWallet(const std::string &strWalletFilename) const
Definition: OTAPI_Exec.cpp:330
EXPORT bool SetAccountWallet_Name(const std::string &ACCT_ID, const std::string &SIGNER_NYM_ID, const std::string &ACCT_NEW_NAME) const
EXPORT std::string NumList_Remove(const std::string &strNumList, const std::string &strNumbers) const
Definition: OTAPI_Exec.cpp:466
OTLOG_IMPORT OTLogStream otOut
EXPORT int64_t Basket_GetMemberMinimumTransferAmount(const std::string &BASKET_ASSET_TYPE_ID, const int32_t &nIndex) const
EXPORT int32_t getAccount(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID) const
EXPORT void AddAssetContract(const OTAssetContract &theContract)
Definition: OTWallet.cpp:752
EXPORT int32_t GetBasketMemberCount(const OTIdentifier &BASKET_ASSET_TYPE_ID) const
EXPORT bool AppInit()
Definition: OTAPI_Exec.cpp:203
EXPORT bool Wallet_ChangePassphrase() const
EXPORT void GetNote(OTString &theStr) const
Definition: OTItem.cpp:1430
EXPORT bool LoadWallet() const
Definition: OTAPI_Exec.cpp:363
EXPORT bool LoadOutbox()
Definition: OTLedger.cpp:477
EXPORT std::string Basket_GetMemberType(const std::string &BASKET_ASSET_TYPE_ID, const int32_t &nIndex) const
EXPORT std::string LoadExpiredBox(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT int32_t depositCheque(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID, const OTString &THE_CHEQUE) const
virtual EXPORT bool Compare(OTScriptable &rhs) const
EXPORT bool Wallet_ImportNym(const OTString &FILE_CONTENTS, OTIdentifier *pNymID=nullptr) const
OTString m_strAssetID
Definition: OTMessage.hpp:203
EXPORT int32_t getInbox(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID) const
EXPORT int32_t killPaymentPlan(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &FROM_ACCT_ID, const int64_t &TRANSACTION_NUMBER) const
EXPORT std::string Ledger_AddTransaction(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_LEDGER, const std::string &THE_TRANSACTION) const
Add a transaction to a ledger.
EXPORT time64_t Transaction_GetDateSigned(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
EXPORT int32_t processNymbox(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT bool Nym_VerifyOutpaymentsByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
int32_t GetAgentCount() const
Definition: OTParty.hpp:347
EXPORT std::string Instrmnt_GetSenderUserID(const std::string &THE_INSTRUMENT) const
EXPORT std::string Message_GetNewIssuerAcctID(const std::string &THE_MESSAGE) const
EXPORT std::string Message_GetNewAssetTypeID(const std::string &THE_MESSAGE) const
EXPORT bool GetSenderUserIDForDisplay(OTIdentifier &theReturnID)
EXPORT int32_t getContract(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ASSET_ID) const
EXPORT int32_t getMarketList(const std::string &SERVER_ID, const std::string &USER_ID) const
Retrieves details for each market.
const OTIdentifier & GetAssetID() const
Definition: Purse.hpp:335
EXPORT bool Wallet_ExportCert(const OTIdentifier &NYM_ID, OTString &strOutput) const
EXPORT bool GetHooks(std::string str_HookName, mapOfClauses &theResults)
Definition: OTBylaw.cpp:686
EXPORT int32_t GetClauseCount() const
Definition: OTBylaw.hpp:230
EXPORT int32_t withdrawVoucher(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID, const OTIdentifier &RECIPIENT_USER_ID, const OTString &CHEQUE_MEMO, const int64_t &AMOUNT) const
EXPORT std::string ConfirmPaymentPlan(const std::string &SERVER_ID, const std::string &SENDER_USER_ID, const std::string &SENDER_ACCT_ID, const std::string &RECIPIENT_USER_ID, const std::string &PAYMENT_PLAN) const
EXPORT std::string Wallet_ExportCert(const std::string &NYM_ID) const
Returns the exported cert, if successful. Else nullptr.
EXPORT bool SaveContractRaw(OTString &strOutput) const
EXPORT bool FormatAmount(int64_t amount, std::string &str_output) const
static EXPORT int32_t GetMemlogSize()
Definition: OTLog.cpp:526
EXPORT std::string LoadNymbox(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT bool Peek(int64_t &lPeek) const
Definition: OTNumList.cpp:285
EXPORT uint32_t GetLength() const
Definition: OTString.cpp:1040
bool IsExchanging() const
Definition: Basket.hpp:235
OTString & GetNymName()
EXPORT bool StringToAmount(int64_t &amount, const std::string &str_input) const
std::map< std::string, OTClause * > mapOfClauses
Definition: OTBylaw.hpp:145
EXPORT std::string LoadMint(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID) const
EXPORT int32_t withdrawVoucher(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID, const std::string &RECIPIENT_USER_ID, const std::string &CHEQUE_MEMO, const int64_t &AMOUNT) const
EXPORT bool GetAssetType(int32_t iIndex, OTIdentifier &THE_ID, OTString &THE_NAME) const
EXPORT bool GetRecentHash(const std::string &server_id, OTIdentifier &theOutput) const
EXPORT std::string Transaction_GetRecipientUserID(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
EXPORT std::string Instrmnt_GetRecipientAcctID(const std::string &THE_INSTRUMENT) const
EXPORT bool AddNewSubkey(const OTIdentifier &idMasterCredential, int32_t nBits=1024, const OTString::Map *pmapPrivate=nullptr, const OTPasswordData *pPWData=nullptr, OTString *pstrNewID=nullptr)
EXPORT void Sleep(const int64_t &MILLISECONDS) const
EXPORT bool SetAsciiArmoredData(const OTASCIIArmor &theArmoredText, bool bLineBreaks=true)
Definition: OTEnvelope.cpp:178
EXPORT int64_t Message_GetUsageCredits(const std::string &THE_MESSAGE) const
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
Definition: Common.hpp:215
EXPORT std::string ProposePaymentPlan(const std::string &SERVER_ID, const time64_t &VALID_FROM, const time64_t &VALID_TO, const std::string &SENDER_ACCT_ID, const std::string &SENDER_USER_ID, const std::string &PLAN_CONSIDERATION, const std::string &RECIPIENT_ACCT_ID, const std::string &RECIPIENT_USER_ID, const int64_t &INITIAL_PAYMENT_AMOUNT, const time64_t &INITIAL_PAYMENT_DELAY, const int64_t &PAYMENT_PLAN_AMOUNT, const time64_t &PAYMENT_PLAN_DELAY, const time64_t &PAYMENT_PLAN_PERIOD, const time64_t &PAYMENT_PLAN_LENGTH, const int32_t &PAYMENT_PLAN_MAX_PAYMENTS) const
EXPORT std::string LoadAssetContract(const std::string &ASSET_TYPE_ID) const
EXPORT std::string LoadOutboxNoVerify(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID) const
EXPORT bool Wallet_CanRemoveAccount(const std::string &ACCOUNT_ID) const
const int32_t OT_ERROR
Definition: OTAPI_Exec.cpp:188
EXPORT bool GetAssetTypeID(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:963
EXPORT bool VerifyAccountReceipt(const std::string &SERVER_ID, const std::string &NYM_ID, const std::string &ACCT_ID) const
EXPORT int32_t sendUserInstrument(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &USER_ID_RECIPIENT, const std::string &RECIPIENT_PUBKEY, const std::string &THE_INSTRUMENT, const std::string &INSTRUMENT_FOR_SENDER) const
EXPORT std::string GetNym_MailSenderIDByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT const OTString & GetName() const
Definition: OTClause.hpp:155
EXPORT bool IsInitialized() const
EXPORT bool GetInboxHash(OTIdentifier &output)
Definition: OTAccount.cpp:317
EXPORT std::string GetNym_OutmailServerIDByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT bool Open(const OTPseudonym &theRecipient, OTString &theOutput, const OTPasswordData *pPWData=nullptr)
Definition: OTEnvelope.cpp:581
EXPORT std::string Transaction_GetSenderAcctID(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
EXPORT bool NumList_Remove(OTNumList &theList, const OTNumList &theOldNumbers) const
EXPORT int64_t Transaction_GetDisplayReferenceToNum(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
EXPORT std::string Instrmnt_GetRemitterUserID(const std::string &THE_INSTRUMENT) const
EXPORT bool Wallet_CanRemoveServer(const std::string &SERVER_ID) const
EXPORT int64_t StringToLong(const std::string &strNumber) const
Definition: OTAPI_Exec.cpp:286
EXPORT OTPseudonym * GetOrLoadPrivateNym(const OTIdentifier &NYM_ID, bool bChecking=false, const char *szFuncName=nullptr, const OTPasswordData *pPWData=nullptr, const OTPassword *pImportPassword=nullptr) const
EXPORT bool DiscardCheque(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID, const OTString &THE_CHEQUE) const
bool IsInteger() const
Definition: OTVariable.hpp:233
int64_t time64_t
Definition: Common.hpp:209
EXPORT std::string AddSubcredential(const std::string &NYM_ID, const std::string &MASTER_CRED_ID, const int32_t &nKeySize) const
Definition: OTAPI_Exec.cpp:917
EXPORT int32_t GetTransactionCountInRefTo(int64_t lReferenceNum) const
Definition: OTLedger.cpp:1272
const int64_t & GetRequestNum() const
EXPORT bool WalletExists() const
Definition: OTAPI_Exec.cpp:358
EXPORT int32_t GetTransactionNumCount(const OTIdentifier &theServerID) const
EXPORT bool VerifySignature(const std::string &SIGNER_NYM_ID, const std::string &THE_CONTRACT) const
EXPORT int32_t GetCallbackCount() const
Definition: OTBylaw.hpp:234
EXPORT std::string GetNym_SourceForID(const std::string &NYM_ID) const
Definition: OTAPI_Exec.cpp:656
EXPORT std::string Callback_GetNameByIndex(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const int32_t &nIndex) const
EXPORT bool LoadNymbox()
Definition: OTLedger.cpp:482
EXPORT std::string Ledger_GetInstrument(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_LEDGER, const int32_t &nIndex) const
EXPORT int32_t getRequest(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT bool RemoveSentMessage(const int64_t &lRequestNumber, const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT bool HarvestAllNumbers(const OTIdentifier &SERVER_ID, const OTIdentifier &NYM_ID, const OTString &THE_CRON_ITEM) const
EXPORT bool HaveAlreadySeenReply(const std::string &SERVER_ID, const std::string &USER_ID, const int64_t &REQUEST_NUMBER) const
EXPORT std::string Instrmnt_GetRemitterAcctID(const std::string &THE_INSTRUMENT) const
EXPORT std::string LoadServerContract(const std::string &SERVER_ID) const
static EXPORT OTItem * CreateItemFromTransaction(const OTTransaction &theOwner, OTItem::itemType theType, const OTIdentifier *pDestinationAcctID=nullptr)
Definition: OTItem.cpp:1451
EXPORT std::string LoadPubkey_Signing(const std::string &USER_ID) const
EXPORT std::string LoadRecordBoxNoVerify(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID) const
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT const std::string GetHookNameByIndex(int32_t nIndex)
Definition: OTBylaw.cpp:663
EXPORT std::string SmartContract_AddCallback(const std::string &THE_CONTRACT, const std::string &SIGNER_NYM_ID, const std::string &BYLAW_NAME, const std::string &CALLBACK_NAME, const std::string &CLAUSE_NAME) const
EXPORT std::string SmartContract_AddAccount(const std::string &THE_CONTRACT, const std::string &SIGNER_NYM_ID, const std::string &PARTY_NAME, const std::string &ACCT_NAME, const std::string &ASSET_TYPE_ID) const
EXPORT bool RemoveAssetContract(const OTIdentifier &theTargetID)
Definition: OTWallet.cpp:1131
EXPORT OTClause * GetClause(std::string str_Name) const
Definition: OTBylaw.cpp:623
EXPORT void SetString(const char *szString)
EXPORT bool GetAccount(int32_t iIndex, OTIdentifier &THE_ID, OTString &THE_NAME) const
EXPORT std::string GenerateBasketExchange(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &BASKET_ASSET_TYPE_ID, const std::string &BASKET_ASSET_ACCT_ID, const int32_t &TRANSFER_MULTIPLE) const
EXPORT int32_t GetMailCount() const
return the number of mail items available for this Nym.
EXPORT bool GetServer(int32_t iIndex, OTIdentifier &THE_ID, OTString &THE_NAME) const
EXPORT bool GetBasketMemberType(const OTIdentifier &BASKET_ASSET_TYPE_ID, int32_t nIndex, OTIdentifier &theOutputMemberType) const
EXPORT int32_t SmartContract_CountNumsNeeded(const OTString &THE_CONTRACT, const OTString &AGENT_NAME) const
EXPORT const OTCredential * GetRevokedCredentialByIndex(int32_t nIndex) const
EXPORT std::string Ledger_GetTransactionByID(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_LEDGER, const int64_t &TRANSACTION_NUMBER) const
EXPORT std::string Instrmnt_GetServerID(const std::string &THE_INSTRUMENT) const
EXPORT std::string Party_GetAcctAgentName(const std::string &THE_CONTRACT, const std::string &PARTY_NAME, const std::string &ACCT_NAME) const
static EXPORT bool PopMemlogFront()
Definition: OTLog.cpp:575
EXPORT int32_t depositPaymentPlan(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTString &THE_PAYMENT_PLAN) const
const char * GetTypeString() const
EXPORT bool GetRecipientAcctID(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:1182
EXPORT bool RemoveNym(const OTIdentifier &theTargetID)
Definition: OTWallet.cpp:1101
EXPORT int32_t Purse_Count(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &THE_PURSE) const
returns a count of the number of cash tokens inside this purse.
EXPORT bool SetNym_Name(const std::string &NYM_ID, const std::string &SIGNER_NYM_ID, const std::string &NYM_NEW_NAME) const
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
EXPORT OTTransaction * GetReplyNotice(const int64_t &lRequestNum)
Definition: OTLedger.cpp:1312
EXPORT bool Msg_HarvestTransactionNumbers(const std::string &THE_MESSAGE, const std::string &USER_ID, const bool &bHarvestingForRetry, const bool &bReplyWasSuccess, const bool &bReplyWasFailure, const bool &bTransactionWasSuccess, const bool &bTransactionWasFailure) const
EXPORT std::string Purse_Empty(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &SIGNER_ID, const std::string &THE_PURSE) const
EXPORT std::string Party_GetAcctID(const std::string &THE_CONTRACT, const std::string &PARTY_NAME, const std::string &ACCT_NAME) const
EXPORT const std::string GetCallbackNameByIndex(int32_t nIndex)
Definition: OTBylaw.cpp:450
EXPORT const OTString & GetName() const
Definition: OTVariable.hpp:220
EXPORT bool SwitchWallet() const
Definition: OTAPI_Exec.cpp:368
static EXPORT bool Decrypt(const OTString &strKey, OTString &strCiphertext, OTString &strOutput, const OTString *pstrDisplay=nullptr, const OTPassword *pAlreadyHavePW=nullptr)
EXPORT int32_t GetOutpaymentsCount() const
return the number of payments items available for this Nym.
EXPORT std::string LoadExpiredBoxNoVerify(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT int32_t GetAccountCount() const
EXPORT std::string GetNym_ActiveCronItemIDs(const std::string &NYM_ID, const std::string &SERVER_ID) const
Definition: OTAPI_Exec.cpp:607
EXPORT const OTPseudonym * GetContractPublicNym() const
Definition: OTContract.cpp:413
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
EXPORT const OTString & GetName()
Definition: OTAgent.hpp:388
EXPORT int32_t depositPaymentPlan(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &THE_PAYMENT_PLAN) const
EXPORT std::string Clause_GetContents(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const std::string &CLAUSE_NAME) const
EXPORT std::string LoadInbox(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID) const
EXPORT OTItem * GetItem(OTItem::itemType theType)
EXPORT std::string LongToString(const int64_t &lNumber) const
Definition: OTAPI_Exec.cpp:291
EXPORT std::string GetNym_RecentHash(const std::string &SERVER_ID, const std::string &NYM_ID) const
EXPORT bool LoadWallet() const
EXPORT std::string Variable_GetType(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const std::string &VARIABLE_NAME) const
EXPORT bool Nym_VerifyOutmailByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT int64_t Instrmnt_GetTransNum(const std::string &THE_INSTRUMENT) const
const OTIdentifier & GetPurportedServerID() const
EXPORT std::string Token_GetServerID(const std::string &THE_TOKEN) const
EXPORT const OTString & GetMasterCredID() const
EXPORT std::string Instrmnt_GetRecipientUserID(const std::string &THE_INSTRUMENT) const
EXPORT int32_t Ledger_GetCount(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_LEDGER) const
Find out how many pending transactions (and receipts) are in this inbox.
EXPORT int32_t Party_GetAcctCount(const std::string &THE_CONTRACT, const std::string &PARTY_NAME) const
EXPORT bool GetPaymentContents(OTString &strOutput) const
Definition: OTPayment.hpp:323
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
EXPORT bool AppCleanup()
Definition: OTAPI_Exec.cpp:228
EXPORT bool SetTransportCallback(TransportCallback *pTransportCallback)
EXPORT std::string GetNym_SubCredentialID(const std::string &NYM_ID, const std::string &MASTER_CRED_ID, const int32_t &nIndex) const
Definition: OTAPI_Exec.cpp:852
EXPORT int32_t deleteAssetAccount(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID) const
EXPORT std::string Wallet_GetAssetIDFromPartial(const std::string &PARTIAL_ID) const
EXPORT std::string SmartContract_AddHook(const std::string &THE_CONTRACT, const std::string &SIGNER_NYM_ID, const std::string &BYLAW_NAME, const std::string &HOOK_NAME, const std::string &CLAUSE_NAME) const
EXPORT bool GetSenderUserID(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:1087
EXPORT bool LoadLedgerFromString(const OTString &theStr)
Definition: OTLedger.cpp:1752
EXPORT bool Mint_IsStillGood(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID) const
EXPORT std::string GetNym_ID(const int32_t &nIndex) const
based on Index this returns the Nym&#39;s ID
EXPORT bool GetMemo(OTString &strOutput) const
Definition: OTPayment.cpp:468
EXPORT bool AddTransactionNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, int64_t lTransNum, bool bSave)
OTTransaction * LoadBoxReceipt(OTTransaction &theAbbrev, OTLedger &theLedger)
Definition: Helpers.cpp:399
EXPORT int32_t getTransactionNumber(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT bool Wallet_ImportCert(const OTString &DISPLAY_NAME, const OTString &FILE_CONTENTS, OTIdentifier *pNymID=nullptr) const
EXPORT bool Wallet_CanRemoveNym(const std::string &NYM_ID) const
EXPORT int64_t ReplyNotice_GetRequestNum(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &THE_TRANSACTION) const
Transactions do not have request numbers. However, if you have a.
EXPORT std::string FlatSign(const std::string &SIGNER_NYM_ID, const std::string &THE_INPUT, const std::string &CONTRACT_TYPE) const
EXPORT std::string GetNym_OutpaymentsServerIDByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT bool GetPublicKey(OTASCIIArmor &strKey) const
EXPORT bool Wallet_CanRemoveAssetType(const std::string &ASSET_ID) const
EXPORT const char * GetCode() const
Definition: OTClause.cpp:177
bool IsBool() const
Definition: OTVariable.hpp:237
static EXPORT bool Encrypt(const OTString &strKey, const OTString &strPlaintext, OTString &strOutput, const OTString *pstrDisplay=nullptr, bool bBookends=true, const OTPassword *pAlreadyHavePW=nullptr)
EXPORT OTPseudonym * GetNymByIDPartialMatch(const std::string PARTIAL_ID, const char *szFuncName=nullptr) const
static EXPORT OTString PeekMemlogBack()
Definition: OTLog.cpp:554
EXPORT bool Msg_HarvestTransactionNumbers(const OTMessage &theMsg, const OTIdentifier &USER_ID, bool bHarvestingForRetry, bool bReplyWasSuccess, bool bReplyWasFailure, bool bTransactionWasSuccess, bool bTransactionWasFailure) const
static EXPORT void SetHomeFolder(OTString strLocation)
Definition: OTPaths.cpp:245
OTString m_strNymID2
Definition: OTMessage.hpp:200
EXPORT int32_t GetAccountCount() const
EXPORT bool Output(std::set< int64_t > &theOutput) const
Definition: OTNumList.cpp:430
EXPORT int64_t GetClosingNum() const
EXPORT std::string Wallet_GetNymIDFromPartial(const std::string &PARTIAL_ID) const
Attempts to find a full ID in the wallet, based on a partial of the same.
EXPORT std::string GetServer_Name(const std::string &SERVER_ID) const
EXPORT bool RemoveIssuedNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lTransNum, bool bSave)
bool FlatSign(const OTIdentifier &theSignerNymID, const OTString &strInput, const OTString &strContractType, OTString &strOutput) const
EXPORT std::string LoadNymboxNoVerify(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT std::string Decrypt(const std::string &RECIPIENT_NYM_ID, const std::string &strCiphertext) const
EXPORT std::string Decode(const std::string &strEncoded, const bool &bLineBreaks) const
#define OT_PW_DISPLAY
Definition: OTCallback.hpp:164
EXPORT std::string GetNym_OutboxHash(const std::string &ACCOUNT_ID, const std::string &NYM_ID) const
EXPORT int32_t GetOutmailCount() const
return the number of mail items available for this Nym.
EXPORT int32_t GetNym_OutpaymentsCount(const std::string &NYM_ID) const
EXPORT std::string SmartContract_ConfirmParty(const std::string &THE_CONTRACT, const std::string &PARTY_NAME, const std::string &NYM_ID) const
EXPORT int32_t checkServerID(const std::string &SERVER_ID, const std::string &USER_ID) const
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT OTMessage * GetOutmailByIndex(int32_t nIndex) const
int64_t GetTotalValue() const
Definition: Purse.hpp:292
EXPORT int32_t depositCheque(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID, const std::string &THE_CHEQUE) const
EXPORT std::string SmartContract_AddClause(const std::string &THE_CONTRACT, const std::string &SIGNER_NYM_ID, const std::string &BYLAW_NAME, const std::string &CLAUSE_NAME, const std::string &SOURCE_CODE) const
EXPORT bool RemoveSentMessage(const int64_t &REQUEST_NUMBER, const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT int32_t checkUser(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &USER_ID_CHECK) const
EXPORT std::string LoadUserPubkey_Encryption(const std::string &USER_ID) const
EXPORT std::string GetAccountWallet_ServerID(const std::string &ACCOUNT_ID) const
EXPORT bool RemoveMailByIndex(int32_t nIndex)
EXPORT std::string LoadPaymentInbox(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT bool RevokeSubcredential(const std::string &NYM_ID, const std::string &MASTER_CRED_ID, const std::string &SUB_CRED_ID) const
Definition: OTAPI_Exec.cpp:967
EXPORT int32_t getMarketList(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT int32_t getMarketOffers(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &MARKET_ID, const int64_t &MAX_DEPTH) const
Gets all offers for a specific market and their details (up until.
EXPORT bool Purse_HasPassword(const std::string &SERVER_ID, const std::string &THE_PURSE) const
OTPayment * GetInstrument(const OTPseudonym &theNym, const int32_t &nIndex, OTLedger &ledger)
Definition: Helpers.cpp:149
EXPORT std::string Wallet_ExportNym(const std::string &NYM_ID) const
Returns the exported Nym, if success. (Else nullptr.)
EXPORT int32_t getOutbox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID) const
EXPORT bool Wallet_RemoveServer(const std::string &SERVER_ID) const
EXPORT std::string GetNym_AltSourceLocation(const std::string &NYM_ID) const
Definition: OTAPI_Exec.cpp:673
static EXPORT OTLedger * GenerateLedger(const OTIdentifier &theUserID, const OTIdentifier &theAcctID, const OTIdentifier &theServerID, ledgerType theType, bool bCreateFile=false)
Definition: OTLedger.cpp:946
EXPORT bool Nym_RemoveOutpaymentsByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT bool NumList_VerifyAll(const OTNumList &theList, const OTNumList &theQueryNumbers) const
OTLOG_IMPORT OTLogStream otInfo
EXPORT int32_t NumList_Count(const std::string &strNumList) const
Definition: OTAPI_Exec.cpp:554
EXPORT OTParty * GetParty(std::string str_party_name) const
EXPORT bool CompareID(const OTIdentifier &theIdentifier) const
static EXPORT bool SleepMilliseconds(int64_t lMilliseconds)
Definition: OTLog.cpp:651
EXPORT std::string CalculateAssetContractID(const std::string &str_Contract) const
EXPORT OTTransaction * GetTransactionByIndex(int32_t nIndex) const
Definition: OTLedger.cpp:1288
EXPORT std::string CreateNym(const int32_t &nKeySize, const std::string &NYM_ID_SOURCE, const std::string &ALT_LOCATION) const
Definition: OTAPI_Exec.cpp:583
EXPORT int32_t Count() const
Definition: OTNumList.cpp:460
EXPORT bool IsRegisteredAtServer(const OTString &strServerID) const
const OTString & GetAgentName() const
EXPORT const OTString & GetPubCredential() const
EXPORT bool Wallet_ChangePassphrase() const
EXPORT bool SaveWallet(const char *szFilename=nullptr)
Definition: OTWallet.cpp:1566
EXPORT std::string AddBasketCreationItem(const std::string &USER_ID, const std::string &THE_BASKET, const std::string &ASSET_TYPE_ID, const int64_t &MINIMUM_TRANSFER) const
EXPORT std::string CreatePurse(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &OWNER_ID, const std::string &SIGNER_ID) const
EXPORT const OTString & GetAltLocation() const
virtual EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
Definition: OTContract.cpp:317
EXPORT int32_t notarizeWithdrawal(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID, const int64_t &AMOUNT) const
EXPORT bool Smart_IsPartyConfirmed(const std::string &THE_CONTRACT, const std::string &PARTY_NAME) const
EXPORT std::string GetPartyID(bool *pBoolSuccess=nullptr) const
Definition: OTParty.cpp:571
EXPORT int32_t GetNym_CredentialCount(const std::string &NYM_ID) const
Definition: OTAPI_Exec.cpp:691
static EXPORT bool GetActiveCronTransNums(OTNumList &output, const OTIdentifier &nymID, const OTIdentifier &serverID)
Definition: OTCronItem.cpp:303
#define OT_FAIL
Definition: Assert.hpp:139
EXPORT std::string CreatePurse_Passphrase(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &SIGNER_ID) const
EXPORT int32_t Bylaw_GetCallbackCount(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME) const
EXPORT bool GetSenderAcctID(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:1117
EXPORT OTCredential * GetRevokedCredential(const OTString &strID)
EXPORT bool SetAssetType_Name(const std::string &ASSET_ID, const std::string &STR_NEW_NAME) const
EXPORT time64_t Instrmnt_GetValidTo(const std::string &THE_INSTRUMENT) const
EXPORT std::string Hook_GetNameByIndex(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const int32_t &nIndex) const
EXPORT std::string LoadPaymentInboxNoVerify(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT int32_t activateSmartContract(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &THE_SMART_CONTRACT) const
EXPORT bool IsNym_RegisteredAtServer(const OTIdentifier &NYM_ID, const OTIdentifier &SERVER_ID) const
EXPORT bool DoesBoxReceiptExist(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const int32_t &nBoxType, const int64_t &TRANSACTION_NUMBER) const
EXPORT OTVariable * GetVariable(std::string str_Name)
Definition: OTBylaw.cpp:579
EXPORT std::string Instrmnt_GetSenderAcctID(const std::string &THE_INSTRUMENT) const
EXPORT int32_t GetNym_TransactionNumCount(const std::string &SERVER_ID, const std::string &NYM_ID) const
OTString m_strServerID
Definition: OTMessage.hpp:191
EXPORT std::string GetNym_CredentialContents(const std::string &NYM_ID, const std::string &CREDENTIAL_ID) const
Definition: OTAPI_Exec.cpp:732
EXPORT std::string GetNym_NymboxHash(const std::string &SERVER_ID, const std::string &NYM_ID) const
EXPORT std::string Smart_GetBylawByIndex(const std::string &THE_CONTRACT, const int32_t &nIndex) const
returns the name of the bylaw.
time64_t GetDateSigned() const
EXPORT int64_t Instrmnt_GetAmount(const std::string &THE_INSTRUMENT) const
EXPORT int32_t Message_GetTransactionSuccess(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_MESSAGE) const
static EXPORT OTCronItem * LoadActiveCronReceipt(const int64_t &lTransactionNum, const OTIdentifier &serverID)
Definition: OTCronItem.cpp:262
EXPORT void SetNote(const OTString &theStr)
Definition: OTItem.cpp:1413
EXPORT std::string Token_GetAssetID(const std::string &THE_TOKEN) const
EXPORT const OTAsymmetricKey & GetPublicSignKey() const
EXPORT bool GetNymboxHash(const std::string &server_id, OTIdentifier &theOutput) const
EXPORT int32_t notarizeDeposit(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID, const OTString &THE_PURSE) const
EXPORT int64_t GetReferenceToNum() const
EXPORT bool SetTempValues()
Definition: OTPayment.cpp:196
EXPORT std::string AddBasketExchangeItem(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &THE_BASKET, const std::string &ASSET_TYPE_ID, const std::string &ASSET_ACCT_ID) const
EXPORT bool Nym_RemoveOutmailByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT std::string Purse_Peek(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &OWNER_ID, const std::string &THE_PURSE) const
EXPORT bool GetOutboxHash(OTIdentifier &output)
Definition: OTAccount.cpp:343
EXPORT bool GetOutboxHash(const std::string &acct_id, OTIdentifier &theOutput) const
EXPORT OTMessage * GetSentMessage(const int64_t &lRequestNumber, const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT size_t GetSubcredentialCount() const
EXPORT std::string Wallet_ImportNym(const std::string &FILE_CONTENTS) const
returns NymID if success, else nullptr.
EXPORT std::string Token_ChangeOwner(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &THE_TOKEN, const std::string &SIGNER_NYM_ID, const std::string &OLD_OWNER, const std::string &NEW_OWNER) const
EXPORT std::string LoadUserPubkey_Signing(const std::string &USER_ID) const
EXPORT const char * GetTypeString() const
Definition: OTPayment.hpp:387
EXPORT int32_t getAccountFiles(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID) const
EXPORT void FlushSentMessages(bool bHarvestingForRetry, const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTLedger &THE_NYMBOX) const
OTLOG_IMPORT OTLogStream otWarn
EXPORT int64_t GetReferenceNumForDisplay()
EXPORT bool WalletExists() const
OTString m_strNymboxHash
Definition: OTMessage.hpp:194
EXPORT int32_t getRequest(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT void HarvestClosingNumbers(OTPseudonym &theNym, const OTIdentifier &theServerID, bool bSave=true)
Definition: Basket.cpp:187
EXPORT bool NumList_VerifyQuery(const OTNumList &theList, const OTNumList &theQueryNumbers) const
EXPORT std::string LoadInboxNoVerify(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID) const
These versions don&#39;t verify the ledger, they just load it up.
EXPORT const char * Get() const
Definition: OTString.cpp:1045
EXPORT int32_t Message_IsTransactionCanceled(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_MESSAGE) const
EXPORT std::string GetAccountWallet_Name(const std::string &ACCOUNT_ID) const
EXPORT int32_t createUserAccount(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
transactionType GetType() const
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTContract.cpp:484
EXPORT bool SavePurse(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &USER_ID, const std::string &THE_PURSE) const
EXPORT bool Wallet_ImportPurse(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &USER_ID, const std::string &THE_PURSE) const
Should handle duplicates. Should load, merge, and save.
EXPORT bool IsAnIndividual() const
Definition: OTAgent.cpp:390
OTLOG_IMPORT OTLogStream otErr
OTItem::itemStatus GetStatus() const
Definition: OTItem.hpp:459
EXPORT std::string GetNym_MailServerIDByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT int64_t GetReceiptAmount()
EXPORT bool Decrypt(const OTIdentifier &theRecipientNymID, const OTString &strCiphertext, OTString &strOutput) const
EXPORT int32_t exchangeBasket(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &BASKET_ASSET_ID, const std::string &THE_BASKET, const bool &BOOL_EXCHANGE_IN_OR_OUT) const
EXPORT OTPartyAccount * GetAccount(const std::string &str_acct_name) const
Definition: OTParty.cpp:653
EXPORT int64_t GetTransactionNum() const
EXPORT int32_t Message_GetBalanceAgreementSuccess(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_MESSAGE) const
EXPORT int32_t notarizeTransfer(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_FROM, const std::string &ACCT_TO, const int64_t &AMOUNT, const std::string &NOTE) const
EXPORT void DisplayStatistics(OTString &strOutput)
EXPORT bool IsNym_RegisteredAtServer(const std::string &NYM_ID, const std::string &SERVER_ID) const
EXPORT bool SetWalletFilename(const OTString &strPath)
EXPORT std::string Nymbox_GetReplyNotice(const std::string &SERVER_ID, const std::string &USER_ID, const int64_t &REQUEST_NUMBER) 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 void SetAppBinaryFolder(const std::string &strFolder) const
Definition: OTAPI_Exec.cpp:257
EXPORT bool Wallet_RemoveNym(const std::string &NYM_ID) const
EXPORT bool GetValidTo(time64_t &tOutput) const
Definition: OTPayment.cpp:894
EXPORT std::string Variable_GetAccess(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const std::string &VARIABLE_NAME) const
EXPORT bool ConfirmPaymentPlan(const OTIdentifier &SERVER_ID, const OTIdentifier &SENDER_USER_ID, const OTIdentifier &SENDER_ACCT_ID, const OTIdentifier &RECIPIENT_USER_ID, OTPaymentPlan &thePlan) const
const OTString & GetAcctID() const
const int32_t OT_TRUE
Definition: OTAPI_Exec.cpp:184
EXPORT void SetReferenceToNum(int64_t lTransactionNum)
EXPORT int32_t getNymbox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT const OTCredential * GetMasterCredentialByIndex(int32_t nIndex) const
EXPORT void zeroMemory() const
Definition: OTString.cpp:744
EXPORT bool IsValid() const
Definition: OTPayment.hpp:301
EXPORT std::string Party_GetAgentNameByIndex(const std::string &THE_CONTRACT, const std::string &PARTY_NAME, const int32_t &nIndex) const
EXPORT std::string PopMessageBuffer(const int64_t &REQUEST_NUMBER, const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT int32_t Bylaw_GetHookCount(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME) const
OTString m_strRequestNum
Definition: OTMessage.hpp:207
OTASCIIArmor m_ascPayload
Definition: OTMessage.hpp:214
EXPORT const OTString & GetName() const
Definition: OTBylaw.hpp:177
EXPORT size_t GetRevokedCredentialCount() const
const OTString & GetAssetTypeID() const
bool IsAbbreviated() const
EXPORT std::string GetNym_CredentialID(const std::string &NYM_ID, const int32_t &nIndex) const
Definition: OTAPI_Exec.cpp:709
EXPORT int32_t createUserAccount(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT const char * GetLanguage() const
Definition: OTBylaw.cpp:916
EXPORT int32_t Bylaw_GetVariableCount(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME) const
EXPORT bool RemoveOutpaymentsByIndex(int32_t nIndex, bool bDeleteIt=true)
EXPORT int32_t getOutbox(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID) const
EXPORT const OTString & GetPubCredential() const
static bool bInitOTApp
EXPORT int64_t Purse_GetTotalValue(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &THE_PURSE) const
Get Purse Total Value (internally uses GetTotalValue().)
EXPORT bool SetAssetType_Name(const OTIdentifier &ASSET_ID, const OTString &STR_NEW_NAME) const
EXPORT void GetString(OTString &theStr) const
OTString m_strCommand
Definition: OTMessage.hpp:189
EXPORT time64_t GetTime() const
EXPORT std::string GetAccountWallet_NymID(const std::string &ACCOUNT_ID) const
EXPORT int32_t GetVariableCount() const
Definition: OTBylaw.hpp:226
EXPORT std::string FormatAmount(const std::string &ASSET_TYPE_ID, const int64_t &THE_AMOUNT) const
EXPORT bool Pop()
Definition: OTNumList.cpp:297
EXPORT int32_t Message_GetSuccess(const std::string &THE_MESSAGE) const
EXPORT std::string LoadAssetAccount(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID) const
EXPORT std::string Message_GetNymboxHash(const std::string &THE_MESSAGE) const
bool Wallet_ImportPurse(const OTIdentifier &SERVER_ID, const OTIdentifier &ASSET_TYPE_ID, const OTIdentifier &SIGNER_ID, const OTString &THE_PURSE, const OTString *pstrDisplay=nullptr)
EXPORT std::string GetNym_OutmailRecipientIDByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT int32_t getNymbox(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT std::string Token_GetID(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &THE_TOKEN) const
const OTString & GetMySignedCopy()
Definition: OTParty.hpp:291
EXPORT bool SignContract(const OTIdentifier &theSignerNymID, const OTString &strContract, OTString &strOutput) const
EXPORT void FlushSentMessages(const bool &bHarvestingForRetry, const std::string &SERVER_ID, const std::string &USER_ID, const std::string &THE_NYMBOX) const
EXPORT int32_t payDividend(const std::string &SERVER_ID, const std::string &ISSUER_USER_ID, const std::string &DIVIDEND_FROM_ACCT_ID, const std::string &SHARES_ASSET_TYPE_ID, const std::string &DIVIDEND_MEMO, const int64_t &AMOUNT_PER_SHARE) const
PAY DIVIDEND – to shareholders.
EXPORT std::string Transaction_GetRecipientAcctID(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
EXPORT const OTString & GetNymIDSource() const
int32_t GetAccountCount() const
Definition: OTParty.hpp:400
bool IsConstant() const
Definition: OTVariable.hpp:200
EXPORT int32_t Transaction_GetSuccess(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
EXPORT std::string SymmetricDecrypt(const std::string &SYMMETRIC_KEY, const std::string &CIPHERTEXT_ENVELOPE) const
EXPORT int32_t getMarketRecentTrades(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &MARKET_ID) const
Gets all recent trades (up until maximum depth)
EXPORT bool Contains(const char *compare) const
Definition: OTString.cpp:1137
EXPORT OTAssetContract * GetAssetContractPartialMatch(const std::string PARTIAL_ID, const char *szFuncName=nullptr) const
static EXPORT Token * TokenFactory(OTString strInput)
Definition: Token.cpp:518
EXPORT int32_t GetMemlogSize() const
Definition: OTAPI_Exec.cpp:373
EXPORT int32_t createAssetAccount(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ASSET_ID) const
EXPORT bool NumList_VerifyAll(const std::string &strNumList, const std::string &strNumbers) const
Definition: OTAPI_Exec.cpp:530
EXPORT int32_t GetAssetTypeCount() const
EXPORT int64_t GetAccountWallet_Balance(const std::string &ACCOUNT_ID) const
EXPORT bool NumList_VerifyQuery(const std::string &strNumList, const std::string &strNumbers) const
Definition: OTAPI_Exec.cpp:501
EXPORT std::string WriteCheque(const std::string &SERVER_ID, const int64_t &CHEQUE_AMOUNT, const time64_t &VALID_FROM, const time64_t &VALID_TO, const std::string &SENDER_ACCT_ID, const std::string &SENDER_USER_ID, const std::string &CHEQUE_MEMO, const std::string &RECIPIENT_USER_ID) const
EXPORT int32_t getBoxReceipt(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID, int32_t nBoxType, const int64_t &lTransactionNum) const
EXPORT int32_t GetNym_MailCount(const std::string &NYM_ID) const
OTItem::itemType GetType() const
Definition: OTItem.hpp:467
EXPORT int64_t StringToAmount(const std::string &ASSET_TYPE_ID, const std::string &str_input) const
EXPORT int32_t checkUser(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &USER_ID_CHECK) const
static EXPORT std::string & trim(std::string &str)
Definition: OTString.cpp:398
EXPORT std::string GetNym_RevokedCredContents(const std::string &NYM_ID, const std::string &CREDENTIAL_ID) const
Definition: OTAPI_Exec.cpp:797
EXPORT std::string Message_GetCommand(const std::string &THE_MESSAGE) const
const OTIdentifier & GetUserID() const
EXPORT std::string Instrmnt_GetMemo(const std::string &THE_INSTRUMENT) const
EXPORT std::string Instrmnt_GetType(const std::string &THE_INSTRUMENT) const
bool Contains(const OTString &strContains)
EXPORT bool GetString(OTString &theData, bool bLineBreaks=true) const
EXPORT int32_t getNym_MarketOffers(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT bool LoadContractFromString(const OTString &theStr)
std::string & GetValueString()
Definition: OTVariable.hpp:267
EXPORT int32_t processNymbox(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT int32_t deleteUserAccount(const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT OTPartyAccount * GetAccountByIndex(int32_t nIndex)
Definition: OTParty.cpp:677
EXPORT std::string GetNym_Stats(const std::string &NYM_ID) const
EXPORT bool GetNym(int32_t iIndex, OTIdentifier &NYM_ID, OTString &NYM_NAME) const
EXPORT std::string Encode(const std::string &strPlaintext, const bool &bLineBreaks) const
#define OT_TIME_ZERO
Definition: Common.hpp:180
int32_t & GetValueInteger()
Definition: OTVariable.hpp:259
EXPORT int64_t GetIssuedNum(const OTIdentifier &theServerID, int32_t nIndex) const
EXPORT int32_t GetNymCount() const
EXPORT OTAccount * GetAccountPartialMatch(const std::string PARTIAL_ID, const char *szFuncName=nullptr) const
EXPORT std::string GetAssetType_Contract(const std::string &ASSET_TYPE_ID) const
EXPORT OTMessage * GetOutpaymentsByIndex(int32_t nIndex) const
EXPORT int32_t deleteAssetAccount(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID) const
EXPORT OTVariable * GetVariableByIndex(int32_t nIndex)
Definition: OTBylaw.cpp:602
EXPORT int32_t Bylaw_GetClauseCount(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME) const
void GetTypeString(OTString &strType) const
Definition: OTItem.hpp:504
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
Definition: OTContract.cpp:367
EXPORT OTServerContract * GetServerContractPartialMatch(const std::string PARTIAL_ID, const char *szFuncName=nullptr) const
EXPORT std::string GetAccountWallet_ID(const int32_t &nIndex) const
EXPORT bool Wallet_RemoveAssetType(const std::string &ASSET_ID) const
EXPORT std::string GetAccountWallet_Type(const std::string &ACCOUNT_ID) const
EXPORT int64_t Ledger_GetTransactionIDByIndex(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_LEDGER, const int32_t &nIndex) const
EXPORT size_t GetMasterCredentialCount() const
EXPORT bool NumList_Add(OTNumList &theList, const OTNumList &theNewNumbers) const
EXPORT bool AddIssuedNum(const OTString &strServerID, const int64_t &lTransNum)
EXPORT int32_t Basket_GetMemberCount(const std::string &BASKET_ASSET_TYPE_ID) const
listOfItems & GetItemList()
virtual EXPORT int64_t GetNumberOfOrigin()
Definition: OTItem.cpp:1132
EXPORT std::string Callback_GetClause(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const std::string &CALLBACK_NAME) const
EXPORT bool GetRecipientUserID(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:1147
EXPORT std::string GetNym_InboxHash(const std::string &ACCOUNT_ID, const std::string &NYM_ID) const
EXPORT bool GetRemitterUserID(OTIdentifier &theOutput) const
Definition: OTPayment.cpp:1023
EXPORT int32_t Hook_GetClauseCount(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const std::string &HOOK_NAME) const
Returns the number of clauses attached to a specific hook.
EXPORT std::string SmartContract_AddVariable(const std::string &THE_CONTRACT, const std::string &SIGNER_NYM_ID, const std::string &BYLAW_NAME, const std::string &VAR_NAME, const std::string &VAR_ACCESS, const std::string &VAR_TYPE, const std::string &VAR_VALUE) const
bool IsPersistent() const
Definition: OTVariable.hpp:204
EXPORT int32_t processInbox(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCT_ID, const std::string &ACCT_LEDGER) const
static EXPORT bool CreateNewKey(OTString &strOutput, const OTString *pstrDisplay=nullptr, const OTPassword *pAlreadyHavePW=nullptr)
EXPORT std::string Ledger_GetTransactionByIndex(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_LEDGER, const int32_t &nIndex) const
EXPORT int32_t Smart_GetBylawCount(const std::string &THE_CONTRACT) const
virtual EXPORT void Release()
Definition: OTString.cpp:765
EXPORT std::string GetSentMessage(const int64_t &REQUEST_NUMBER, const std::string &SERVER_ID, const std::string &USER_ID) const
EXPORT std::string GetAccountWallet_AssetTypeID(const std::string &ACCOUNT_ID) const
EXPORT int32_t getContract(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ASSET_ID) const
EXPORT int32_t GetAssetTypeCount() const
EXPORT int32_t Smart_GetPartyCount(const std::string &THE_CONTRACT) const
EXPORT const std::string GetSubcredentialIDByIndex(size_t nIndex) const
EXPORT std::string PeekMemlogBack() const
Definition: OTAPI_Exec.cpp:388
EXPORT std::string GetNym_OutpaymentsRecipientIDByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT std::string GenerateBasketCreation(const std::string &USER_ID, const int64_t &MINIMUM_TRANSFER) const
EXPORT bool Nym_VerifyMailByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT std::string Wallet_ImportCert(const std::string &DISPLAY_NAME, const std::string &FILE_CONTENTS) const
Returns the imported cert&#39;s NymID, if successful. Else nullptr.
static EXPORT OTCronItem * NewCronItem(const OTString &strCronItem)
Definition: OTCronItem.cpp:165
EXPORT OTMessage * GetMailByIndex(int32_t nIndex) const
EXPORT time64_t Token_GetValidFrom(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &THE_TOKEN) const
the date is seconds since Jan 1970.
EXPORT void AddItem(OTItem &theItem)
EXPORT std::string GetNym_SubCredentialContents(const std::string &NYM_ID, const std::string &MASTER_CRED_ID, const std::string &SUB_CRED_ID) const
Definition: OTAPI_Exec.cpp:881
EXPORT bool SaveSignedNymfile(OTPseudonym &SIGNER_NYM)
EXPORT int32_t queryAssetTypes(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ENCODED_MAP) const
EXPORT int32_t getTransactionNumber(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID) const
EXPORT int32_t sendUserMessage(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &USER_ID_RECIPIENT, const OTString &RECIPIENT_PUBKEY, const OTString &THE_MESSAGE) const
EXPORT bool IsBasketCurrency(const std::string &ASSET_TYPE_ID) const
EXPORT bool RemoveServerContract(const OTIdentifier &theTargetID)
Definition: OTWallet.cpp:1155
EXPORT std::string GetNym_OutpaymentsContentsByIndex(const std::string &NYM_ID, const int32_t &nIndex) const
EXPORT std::string UlongToString(const uint64_t &lNumber) const
Definition: OTAPI_Exec.cpp:307
EXPORT int64_t Transaction_GetAmount(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
EXPORT std::string Party_GetID(const std::string &THE_CONTRACT, const std::string &PARTY_NAME) const
EXPORT std::string Encrypt(const std::string &RECIPIENT_NYM_ID, const std::string &strPlaintext) const
EXPORT OTTransaction * GetTransaction(OTTransaction::transactionType theType)
Definition: OTLedger.cpp:1215
static EXPORT OTString PeekMemlogFront()
Definition: OTLog.cpp:534
EXPORT int32_t exchangePurse(const std::string &SERVER_ID, const std::string &ASSET_TYPE_ID, const std::string &USER_ID, const std::string &THE_PURSE) const
EXPORT int32_t issueAssetType(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTString &THE_CONTRACT) const
static bool bCleanupOTApp
EXPORT bool GetRecipientUserIDForDisplay(OTIdentifier &theReturnID)
EXPORT std::string Variable_GetContents(const std::string &THE_CONTRACT, const std::string &BYLAW_NAME, const std::string &VARIABLE_NAME) const
EXPORT std::string Smart_GetPartyByIndex(const std::string &THE_CONTRACT, const int32_t &nIndex) const
returns the name of the party.
EXPORT bool PopMemlogBack() const
Definition: OTAPI_Exec.cpp:398
EXPORT bool Wallet_ExportNym(const OTIdentifier &NYM_ID, OTString &strOutput) const
EXPORT void Output(const int32_t &nLogLevel, const std::string &strOutput) const
Definition: OTAPI_Exec.cpp:322
EXPORT bool VerifyUserPrivateKey(const std::string &USER_ID) const
EXPORT int32_t getAccount(const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const OTIdentifier &ACCT_ID) const
EXPORT std::string Transaction_GetVoucher(const std::string &SERVER_ID, const std::string &USER_ID, const std::string &ACCOUNT_ID, const std::string &THE_TRANSACTION) const
const OTIdentifier & GetServerID() const
Definition: Purse.hpp:331
EXPORT std::string Wallet_GetAccountIDFromPartial(const std::string &PARTIAL_ID) const