Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTTrade.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTTrade.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 "stdafx.hpp"
134 
135 #include "trade/OTTrade.hpp"
136 #include "trade/OTMarket.hpp"
137 #include "trade/OTOffer.hpp"
138 #include "OTAccount.hpp"
139 #include "OTLog.hpp"
140 #include "OTPseudonym.hpp"
141 
142 #include <irrxml/irrXML.hpp>
143 
144 #include <memory>
145 
146 namespace opentxs
147 {
148 
150 
151 // This class is like: you are placing an order to do a trade.
152 // Your order will continue processing until it is complete.
153 // PART of that process is putting an offer on the market. See OTOffer for that.
154 //
155 // Trades are like cron items, they can expire, they can have rules.
156 //
157 // An OTTrade is derived from OTCronItem. OTCron has a list of those items.
158 
159 // Used to be I could just call pTrade->VerifySignature(nym), which is what
160 // I still call here, inside this function. But that's a special case -- an
161 // override
162 // from the OTScriptable / OTSmartContract version, which verifies parties and
163 // agents, etc.
164 //
166  OTPseudonym&, // Not needed in this version of
167  // the override.
168  mapOfNyms*) const
169 {
170  return VerifySignature(nym);
171 }
172 
173 // This is an override. See note above.
174 //
176  OTAccount& account) const
177 {
178  return account.VerifyOwner(nym);
179 }
180 
181 // return -1 if error, 0 if nothing, and 1 if the node was processed.
183 {
184  int32_t returnVal = 0;
185 
186  // Here we call the parent class first.
187  // If the node is found there, or there is some error,
188  // then we just return either way. But if it comes back
189  // as '0', then nothing happened, and we'll continue executing.
190  //
191  // -- Note you can choose not to call the parent if
192  // you don't want to use any of those xml tags.
193  // As I do below, in the case of OTAccount.
194  //
195  if (0 != (returnVal = ot_super::ProcessXMLNode(xml))) return returnVal;
196 
197  if (!strcmp("trade", xml->getNodeName())) {
198  m_strVersion = xml->getAttributeValue("version");
199  tradesAlreadyDone_ = atoi(xml->getAttributeValue("completedNoTrades"));
200 
201  SetTransactionNum(atol(xml->getAttributeValue("transactionNum")));
202 
203  const OTString creationStr = xml->getAttributeValue("creationDate");
204  const OTString validFromStr = xml->getAttributeValue("validFrom");
205  const OTString validToStr = xml->getAttributeValue("validTo");
206 
207  int64_t creation = creationStr.ToLong();
208  int64_t validFrom = validFromStr.ToLong();
209  int64_t validTo = validToStr.ToLong();
210 
214 
215  OTString activated(xml->getAttributeValue("hasActivated"));
216 
217  if (activated.Compare("true"))
218  hasTradeActivated_ = true;
219  else
220  hasTradeActivated_ = false;
221 
222  const OTString serverID(xml->getAttributeValue("serverID")),
223  userID(xml->getAttributeValue("userID")),
224  assetTypeID(xml->getAttributeValue("assetTypeID")),
225  assetAcctID(xml->getAttributeValue("assetAcctID")),
226  currencyTypeID(xml->getAttributeValue("currencyTypeID")),
227  currencyAcctID(xml->getAttributeValue("currencyAcctID"));
228 
229  const OTIdentifier SERVER_ID(serverID), USER_ID(userID),
230  ASSET_TYPE_ID(assetTypeID), ASSET_ACCT_ID(assetAcctID),
231  CURRENCY_TYPE_ID(currencyTypeID), CURRENCY_ACCT_ID(currencyAcctID);
232 
233  SetServerID(SERVER_ID);
234  SetSenderUserID(USER_ID);
235  SetAssetID(ASSET_TYPE_ID);
236  SetSenderAcctID(ASSET_ACCT_ID);
237  SetCurrencyID(CURRENCY_TYPE_ID);
238  SetCurrencyAcctID(CURRENCY_ACCT_ID);
239 
240  otLog3 << "\n\nTrade. Transaction Number: " << m_lTransactionNum
241  << " Completed # of Trades: " << tradesAlreadyDone_ << "\n";
242 
243  otWarn << " Creation Date: " << creation
244  << " Valid From: " << validFrom << "\n Valid To: " << validTo
245  << "\n"
246  " assetTypeID: " << assetTypeID
247  << "\n assetAcctID: " << assetAcctID << "\n"
248  " ServerID: " << serverID
249  << "\n UserID: " << userID
250  << "\n "
251  " currencyTypeID: " << currencyTypeID
252  << "\n currencyAcctID: " << currencyAcctID << "\n ";
253 
254  returnVal = 1;
255  }
256 
257  if (!strcmp("stopOrder", xml->getNodeName())) {
258  OTString sign(xml->getAttributeValue("sign"));
259 
260  if (sign.Compare("0")) {
261  stopSign_ = 0; // Zero means it isn't a stop order. So why is the
262  // tag in the file?
263  otErr << "Strange: Stop order tag found in trade, but sign "
264  "character set to 0.\n"
265  "(Zero means: NOT a stop order.)\n";
266  return (-1);
267  }
268  else if (sign.Compare("<"))
269  stopSign_ = '<';
270  else if (sign.Compare(">"))
271  stopSign_ = '>';
272  else {
273  stopSign_ = 0;
274  otErr << "Unexpected or nonexistent value in stop order sign: "
275  << sign << "\n";
276  return (-1);
277  }
278 
279  // Now we know the sign is properly formed, let's grab the price value.
280 
281  stopPrice_ = atol(xml->getAttributeValue("price"));
282 
283  OTString activated(xml->getAttributeValue("hasActivated"));
284 
285  if (activated.Compare("true"))
286  stopActivated_ = true;
287  else
288  stopActivated_ = false;
289 
290  otLog3 << "\n\nStop order -- "
291  << (stopActivated_ ? "Already activated" : "Will activate")
292  << " when price " << (stopActivated_ ? "was" : "reaches") << " "
293  << (('<' == stopSign_) ? "LESS THAN" : "GREATER THAN") << ": "
294  << stopPrice_ << ".\n";
295 
296  returnVal = 1;
297  }
298  else if (!strcmp("offer", xml->getNodeName())) {
299  if (!OTContract::LoadEncodedTextField(xml, marketOffer_)) {
300  otErr << "Error in OTTrade::ProcessXMLNode: offer field without "
301  "value.\n";
302  return (-1); // error condition
303  }
304 
305  returnVal = 1;
306  }
307 
308  return returnVal;
309 }
310 
312 {
313  // I release this because I'm about to repopulate it.
315 
316  m_xmlUnsigned.Concatenate("<?xml version=\"%s\"?>\n\n", "1.0");
317 
318  const OTString SERVER_ID(GetServerID()), USER_ID(GetSenderUserID()),
319  ASSET_TYPE_ID(GetAssetID()), ASSET_ACCT_ID(GetSenderAcctID()),
320  CURRENCY_TYPE_ID(GetCurrencyID()),
321  CURRENCY_ACCT_ID(GetCurrencyAcctID());
322 
324  "<trade\n version=\"%s\"\n"
325  " hasActivated=\"%s\"\n"
326  " serverID=\"%s\"\n"
327  " assetTypeID=\"%s\"\n"
328  " assetAcctID=\"%s\"\n"
329  " currencyTypeID=\"%s\"\n"
330  " currencyAcctID=\"%s\"\n"
331  " userID=\"%s\"\n"
332  " completedNoTrades=\"%d\"\n"
333  " transactionNum=\"%lld\"\n"
334  " creationDate=\"%" PRId64 "\"\n"
335  " validFrom=\"%" PRId64 "\"\n"
336  " validTo=\"%" PRId64 "\""
337  " >\n\n",
338  m_strVersion.Get(), (hasTradeActivated_ ? "true" : "false"),
339  SERVER_ID.Get(), ASSET_TYPE_ID.Get(), ASSET_ACCT_ID.Get(),
340  CURRENCY_TYPE_ID.Get(), CURRENCY_ACCT_ID.Get(), USER_ID.Get(),
341  tradesAlreadyDone_, m_lTransactionNum,
345 
346  // There are "closing" transaction numbers, used to CLOSE a transaction.
347  // Often where Cron items are involved such as this payment plan, or in
348  // baskets,
349  // where many asset accounts are involved and require receipts to be closed
350  // out.
351 
352  for (int32_t i = 0; i < GetCountClosingNumbers(); i++) {
353  int64_t closingNumber = GetClosingTransactionNoAt(i);
354  OT_ASSERT(closingNumber > 0);
355 
357  "<closingTransactionNumber value=\"%lld\"/>\n\n", closingNumber);
358  }
359 
360  if (('<' == stopSign_) || ('>' == stopSign_)) {
361  m_xmlUnsigned.Concatenate("<stopOrder\n"
362  " hasActivated=\"%s\"\n"
363  " sign=\"%c\"\n"
364  " price=\"%lld\""
365  " />\n\n",
366  (stopActivated_ ? "true" : "false"),
367  stopSign_, stopPrice_);
368  }
369 
370  if (marketOffer_.Exists()) {
371  OTASCIIArmor ascOffer(marketOffer_);
372  m_xmlUnsigned.Concatenate("<offer>\n%s</offer>\n\n", ascOffer.Get());
373  }
374 
375  m_xmlUnsigned.Concatenate("</trade>\n");
376 }
377 
378 // The trade stores a copy of the Offer in string form.
379 // This function verifies that offer against the trade,
380 // and also verifies the signature on the offer.
381 //
382 // The Nym's ID is compared to offer's SenderUserID, and then the Signature
383 // is checked
384 // on the offer. It also compares the server ID, asset and currency IDs,
385 // transaction #, etc
386 // between this trade and the offer, in order to fully verify the offer's
387 // authenticity.
388 //
389 bool OTTrade::VerifyOffer(OTOffer& offer) const
390 {
391  // At this point, I have a working, loaded, model of the Offer.
392  // Let's verify the thing.
393 
394  if (GetTransactionNum() != offer.GetTransactionNum()) {
395  otErr << "While verifying offer, failed matching transaction number.\n";
396  return false;
397  }
398  else if (GetServerID() != offer.GetServerID()) {
399  otErr << "While verifying offer, failed matching Server ID.\n";
400  return false;
401  }
402  else if (GetAssetID() != offer.GetAssetID()) {
403  otErr << "While verifying offer, failed matching asset type ID.\n";
404  return false;
405  }
406  else if (GetCurrencyID() != offer.GetCurrencyID()) {
407  otErr << "While verifying offer, failed matching currency type ID.\n";
408  return false;
409  }
410 
411  // the Offer validates properly for this Trade.
412  //
413  return true;
414 }
415 
416 // Assuming the offer is ON the market, this will get the pointer to that offer.
417 // Otherwise it will try to add it to the market.
418 // Otherwise it will fail. (Perhaps it's a stop order, and not ready to activate
419 // yet.)
420 //
421 OTOffer* OTTrade::GetOffer(OTIdentifier* offerMarketId, OTMarket** market)
422 {
423  OT_ASSERT(GetCron() != nullptr);
424 
425  // See if the offer has already been instantiated onto a market...
426  if (offer_ != nullptr) {
427  offer_->SetTrade(*this); // Probably don't need this line. I'll remove
428  // it someday while optimizing.
429  // In fact since it should already be set, having this here would
430  // basically
431  // hide it from me if the memory was ever walked on from a bug
432  // somewhere.
433 
434  // It loaded. Let's get the Market ID off of it so we can locate the
435  // market.
436  const OTIdentifier OFFER_MARKET_ID(*offer_);
437 
438  if (market != nullptr) {
439  OTMarket* pMarket = GetCron()->GetMarket(OFFER_MARKET_ID);
440 
441  // Sometimes the caller function would like a copy of this market
442  // pointer, when available.
443  // So I pass it back to him here, if he wants. That way he doesn't
444  // have to do this work again
445  // to look it up.
446  if (pMarket != nullptr)
447  *market = pMarket; // <=================
448  else
449  otErr << "OTTrade::" << __FUNCTION__
450  << ": offer_ already exists, yet unable to find the "
451  "market it's supposed to be on.\n";
452  }
453 
454  if (offerMarketId != nullptr) {
455  // Sometimes the caller function would like a copy of this ID. So I
456  // give the option to pass in a pointer so I can give it here.
457  offerMarketId->Assign(OFFER_MARKET_ID);
458  }
459 
460  return offer_;
461  } // if offer_ ALREADY EXISTS.
462 
463  // else (BELOW) offer_ IS nullptr, and thus it didn't exist yet...
464 
465  if (!marketOffer_.Exists()) {
466  otErr << "OTTrade::GetOffer called with empty marketOffer_.\n";
467  return nullptr;
468  }
469 
470  OTOffer* offer = new OTOffer();
471  OT_ASSERT(offer != nullptr);
472 
473  // Trying to load the offer from the trader's original signed request
474  // (So I can use it to lookup the Market ID, so I can see the offer is
475  // already there on the market.)
476  if (!offer->LoadContractFromString(marketOffer_)) {
477  otErr << "Error loading offer from string in OTTrade::GetOffer\n";
478  delete offer;
479  offer = nullptr;
480  return nullptr;
481  }
482 
483  // No need to do any additional security verification here on the Offer,
484  // since the Offer is already heavily verified in
485  // OTServer::NotarizeMarketOffer().
486  // So as long as you feel safe about the Trade, then you can feel safe about
487  // the Offer already, with no further checks.
488  // *Also remember we saved a copy of the original in the cron folder.
489 
490  // It loaded. Let's get the Market ID off of it so we can locate the market.
491  OTIdentifier OFFER_MARKET_ID(*offer);
492 
493  if (offerMarketId != nullptr) {
494  // Sometimes the caller function would like a copy of this ID. So I
495  // give the option to pass in a pointer so I can give it here.
496  offerMarketId->Assign(OFFER_MARKET_ID);
497  }
498 
499  // Previously if a user tried to use a market that didn't exist, I'd just
500  // return failure.
501  // But now we will create any market that doesn't already exist.
502  // (Remember, the server operator could just erase the market folder--it
503  // wouldn't
504  // affect anyone's balances!) Update: he probably couldn't just wipe the
505  // markets folder,
506  // actually, without making it impossible for certain Nyms to get rid of
507  // certain issued #s.
508  //
509  // OTMarket * pMarket = m_cron->GetMarket(OFFER_MARKET_ID);
510  OTMarket* pMarket = GetCron()->GetOrCreateMarket(
511  GetAssetID(), GetCurrencyID(), offer->GetScale());
512 
513  // Couldn't find (or create) the market.
514  if (pMarket != nullptr) {
515  otOut
516  << "OTTrade::" << __FUNCTION__
517  << ": Unable to find or create market within requested parameters.";
518  delete offer;
519  offer = nullptr;
520  return nullptr;
521  }
522 
523  // If the caller passed in the address of a market pointer (optional)
524  if (market != nullptr) {
525  // Sometimes the caller function would like a copy of this market
526  // pointer, when available.
527  // So I pass it back to him here, if he wants. That way he doesn't have
528  // to do this work again
529  // to look it up.
530  *market = pMarket;
531  }
532 
533  // At this point, I have heap-allocated the offer, used it to get the Market
534  // ID, and successfully
535  // used that to get a pointer to the market matching that ID.
536  //
537  // Let's see if the offer is ALREADY allocated and on this market!
538  // If so, delete the one I just allocated. If not, add it to the market.
539  OTOffer* marketOffer = pMarket->GetOffer(offer->GetTransactionNum());
540 
541  // The Offer is already on the Market.
542  // NOTE: It may just start out this way, without ever being added.
543  // How is that possible? Because maybe it was in the market file when we
544  // first loaded up,
545  // and had been added on some previous run of the software. So since we
546  // started running,
547  // the pMarket->AddOffer() code below has literally never run for that
548  // offer. Instead we
549  // first find it here, and thus return the pointer before getting any
550  // farther.
551  //
552  // IN ALL CASES, we make sure to call offer_->SetTrade() so that it has a
553  // pointer BACK to
554  // this Trade object! (When actually processing the offer, the market will
555  // need the account
556  // numbers and Nym IDs... which are stored here on the trade.)
557  if (marketOffer != nullptr) {
558  offer_ = marketOffer;
559 
560  // Since the Offer already exists on the market, no need anymore for the
561  // one we allocated above (to get the market ID.) So we delete it now.
562  delete offer;
563  offer = nullptr;
564 
565  offer_->SetTrade(*this);
566 
567  return offer_;
568  }
569 
570  // Okay so the offer ISN'T already on the market. If it's not a stop order,
571  // let's ADD the one we
572  // allocated to the market now! (Stop orders are activated through their own
573  // logic, which is below
574  // this, in the else block.)
575  //
576  if (!IsStopOrder()) {
577  if (hasTradeActivated_) {
578  // Error -- how has the trade already activated, yet not on the
579  // market and null in my pointer?
580  otErr << "How has the trade already activated, yet not on the "
581  "market and null in my pointer?\n";
582  }
583  else if (!pMarket->AddOffer(this, *offer, true)) // Since we're
584  // actually adding
585  // an offer to the
586  // market (not just
587  { // loading from disk) the we actually want to save the market.
588  // bSaveFile=true.
589  // Error adding the offer to the market!
590  otErr << "Error adding the offer to the market! (Even though "
591  "supposedly the right market.)\n";
592  }
593  else {
594  // SUCCESS!
595  offer_ = offer;
596 
597  hasTradeActivated_ = true;
598 
599  // The Trade (stored on Cron) has a copy of the Original Offer, with
600  // the User's signature on it.
601  // A copy of that original Trade object (itself with the user's
602  // signature) is already stored in
603  // the cron folder (by transaction number.) This happens when the
604  // Trade is FIRST added to cron,
605  // so it's already safe before we even get here.
606  //
607  // So thus I am FREE to release the signatures on the offer, and
608  // sign with the server instead.
609  // The server-signed offer will be stored by the OTMarket.
610  offer_->ReleaseSignatures();
611  offer_->SignContract(*(GetCron()->GetServerNym()));
612  offer_->SaveContract();
613 
614  pMarket->SaveMarket();
615 
616  // Now when the market loads next time, it can verify this offer
617  // using the server's signature,
618  // instead of having to load the user. Because the server has
619  // verified it and added it, and now
620  // signs it, vouching for it.
621 
622  // The Trade itself (all its other variables) are now allowed to
623  // change, since its signatures
624  // are also released and it is now server-signed. (With a copy
625  // stored of the original.)
626 
627  offer_->SetTrade(*this);
628 
629  return offer_;
630  }
631  }
632 
633  // It's a stop order, and not activated yet.
634  // Should we activate it now?
635  //
636  else if (IsStopOrder() && !stopActivated_) {
637  int64_t relevantPrice = 0;
638 
639  // If the stop order is trying to sell something, then it cares about
640  // the highest bidder.
641  if (offer->IsAsk())
642  relevantPrice = pMarket->GetHighestBidPrice();
643  else // But if the stop order is trying to buy something, then it cares
644  // about the lowest ask price.
645  relevantPrice = pMarket->GetLowestAskPrice();
646 
647  // It's a stop order that hasn't activated yet. SHOULD IT ACTIVATE NOW?
648  if ((IsGreaterThan() && (relevantPrice > GetStopPrice())) ||
649  (IsLessThan() && (relevantPrice < GetStopPrice()))) {
650  // Activate the stop order!
651  if (!pMarket->AddOffer(this, *offer, true)) // Since we're actually
652  // adding an offer to
653  // the market (not just
654  { // loading from disk) the we actually want to save the market.
655  // Error adding the offer to the market! // bSaveFile=true.
656  otErr << "Error adding the stop order to the market! (Even "
657  "though supposedly the right market.)\n";
658  }
659  else {
660  // SUCCESS!
661  offer_ = offer;
662 
663  stopActivated_ = true;
664  hasTradeActivated_ = true;
665 
666  // The Trade (stored on Cron) has a copy of the Original Offer,
667  // with the User's signature on it.
668  // A copy of that original Trade object (itself with the user's
669  // signature) is already stored in
670  // the cron folder (by transaction number.) This happens when
671  // the Trade is FIRST added to cron,
672  // so it's already safe before we even get here.
673  //
674  // So thus I am FREE to release the signatures on the offer, and
675  // sign with the server instead.
676  // The server-signed offer will be stored by the OTMarket.
677  offer_->ReleaseSignatures();
678  offer_->SignContract(*(GetCron()->GetServerNym()));
679  offer_->SaveContract();
680 
681  pMarket->SaveMarket();
682 
683  // Now when the market loads next time, it can verify this offer
684  // using the server's signature,
685  // instead of having to load the user. Because the server has
686  // verified it and added it, and now
687  // signs it, vouching for it.
688 
689  // The Trade itself (all its other variables) are now allowed to
690  // change, since its signatures
691  // are also released and it is now server-signed. (With a copy
692  // stored of the original.)
693 
694  offer_->SetTrade(*this);
695 
696  return offer_;
697  }
698  }
699  }
700 
701  delete offer;
702  offer = nullptr;
703 
704  return nullptr;
705 }
706 
707 // Cron only removes an item when that item REQUESTS to be removed (by setting
708 // the flag.)
709 // Once this happens, Cron has full permission to remove it. Thus, this hook is
710 // forceful. It
711 // is cron saying, YOU ARE BEING REMOVED. Period. So cleanup whatever you have
712 // to clean up.
713 //
714 // In this case, it removes the corresponding offer from the market.
715 //
717 {
718  OTCron* cron = GetCron();
719 
720  OT_ASSERT(cron != nullptr);
721 
722  // If I don't already have an offer on the market, then I will have trouble
723  // figuring out
724  // my SCALE, which is stored on the Offer. Therefore I will instantiate an
725  // offer (since I
726  // store the original internally) and I will look up the scale.
727  //
728 
729  int64_t scale = 1; // todo stop hardcoding.
730  int64_t transactionNum = 0;
731 
732  if (offer_ != nullptr) {
733  if (!marketOffer_.Exists()) {
734  otErr
735  << "OTTrade::onRemovalFromCron called with nullptr offer_ and "
736  "empty marketOffer_.\n";
737  return;
738  }
739 
740  std::unique_ptr<OTOffer> offer(new OTOffer());
741 
742  // Trying to load the offer from the trader's original signed request
743  // (So I can use it to lookup the Market ID, so I can see if the offer
744  // is
745  // already there on the market.)
746  if (!offer->LoadContractFromString(marketOffer_)) {
747  otErr << "Error loading offer from string in "
748  "OTTrade::onRemovalFromCron\n";
749  return;
750  }
751 
752  scale = offer->GetScale();
753  transactionNum = offer->GetTransactionNum();
754  }
755  else {
756  scale = offer_->GetScale();
757  transactionNum = offer_->GetTransactionNum();
758  }
759 
760  OTMarket* market =
761  cron->GetOrCreateMarket(GetAssetID(), GetCurrencyID(), scale);
762 
763  // Couldn't find (or create) the market.
764  //
765  if (market == nullptr) {
766  otErr << "Unable to find market within requested parameters in "
767  "OTTrade::onRemovalFromCron.\n";
768  return;
769  }
770 
771  //
772  // Let's see if the offer is ALREADY allocated and on this market!
773  //
774  OTOffer* marketOffer = market->GetOffer(transactionNum);
775 
776  // The Offer is already on the Market.
777  //
778  if (marketOffer != nullptr) {
779  offer_ = marketOffer;
780 
781  offer_->SetTrade(*this);
782  }
783 
784  market->RemoveOffer(transactionNum);
785 }
786 
787 // GetSenderAcctID() -- asset account.
788 // GetCurrencyAcctID() -- currency account.
789 
790 int64_t OTTrade::GetClosingNumber(const OTIdentifier& acctId) const
791 {
792  if (acctId == GetSenderAcctID())
793  return GetAssetAcctClosingNum();
794  else if (acctId == GetCurrencyAcctID())
795  return GetCurrencyAcctClosingNum();
796  return 0;
797 }
798 
800 {
802  : 0; // todo stop hardcoding.
803 }
804 
806 {
808  : 0; // todo stop hardcoding.
809 }
810 
814 {
815  // I don't call the parent class' version of this function, in the case of
816  // OTTrade,
817  // since it would just be redundant.
818 
819  // You don't just go willy-nilly and remove a cron item from a market unless
820  // you check first
821  // and make sure the Nym who requested it actually has said trans# (and 2
822  // related closing #s)
823  // signed out to him on his last receipt...
824  //
825  if (!nym.CompareID(GetSenderUserID())) {
826  otLog5 << "OTTrade::CanRemoveItem: nym is not the originator of "
827  "this CronItem. "
828  "(He could be a recipient though, so this is normal.)\n";
829  return false;
830  }
831 
832  // By this point, that means nym is DEFINITELY the originator (sender)...
833  else if (GetCountClosingNumbers() < 2) {
834  otOut
835  << "OTTrade::CanRemoveItem Weird: Sender tried to remove a market "
836  "trade; expected at "
837  "least 2 closing numbers to be available--that weren't. (Found "
838  << GetCountClosingNumbers() << ").\n";
839  return false;
840  }
841 
842  const OTString serverID(GetServerID());
843 
844  if (!nym.VerifyIssuedNum(serverID, GetAssetAcctClosingNum())) {
845  otOut << "OTTrade::CanRemoveItemFromCron: Closing number didn't verify "
846  "for asset account.\n";
847  return false;
848  }
849 
850  if (!nym.VerifyIssuedNum(serverID, GetCurrencyAcctClosingNum())) {
851  otOut << "OTTrade::CanRemoveItemFromCron: Closing number didn't verify "
852  "for currency account.\n";
853  return false;
854  }
855 
856  // By this point, we KNOW nym is the sender, and we KNOW there are the
857  // proper number of transaction
858  // numbers available to close. We also know that this cron item really was
859  // on the cron object, since
860  // that is where it was looked up from, when this function got called! So
861  // I'm pretty sure, at this point,
862  // to authorize removal, as long as the transaction num is still issued to
863  // nym (this check here.)
864  //
865  return nym.VerifyIssuedNum(serverID, GetOpeningNum());
866 
867  // Normally this will be all we need to check. The originator will have the
868  // transaction
869  // number signed-out to him still, if he is trying to close it. BUT--in some
870  // cases, someone
871  // who is NOT the originator can cancel. Like in a payment plan, the sender
872  // is also the depositor,
873  // who would normally be the person cancelling the plan. But technically,
874  // the RECIPIENT should
875  // also have the ability to cancel that payment plan. BUT: the transaction
876  // number isn't signed
877  // out to the RECIPIENT... In THAT case, the below VerifyIssuedNum() won't
878  // work! In those cases,
879  // expect that the special code will be in the subclasses override of this
880  // function. (OTPaymentPlan::CanRemoveItem() etc)
881 
882  // P.S. If you override this function, MAKE SURE to call the parent
883  // (OTCronItem::CanRemoveItem) first,
884  // for the VerifyIssuedNum call above. Only if that fails, do you need to
885  // dig deeper...
886 }
887 
888 // This is called by OTCronItem::HookRemovalFromCron
889 // (After calling this method, HookRemovalFromCron then calls
890 // onRemovalFromCron.)
891 //
893  const int64_t& newTransactionNumber,
894  OTPseudonym& originator, OTPseudonym* remover)
895 {
896  const char* szFunc = "OTTrade::onFinalReceipt";
897 
898  OTCron* cron = GetCron();
899  OT_ASSERT(cron != nullptr);
900 
901  OTPseudonym* serverNym = cron->GetServerNym();
902  OT_ASSERT(serverNym != nullptr);
903 
904  // First, we are closing the transaction number ITSELF, of this cron item,
905  // as an active issued number on the originating nym. (Changing it to
906  // CLOSED.)
907  //
908  // Second, we're verifying the CLOSING number, and using it as the closing
909  // number
910  // on the FINAL RECEIPT (with that receipt being "InReferenceTo"
911  // GetTransactionNum())
912  //
913  const int64_t openingNumber = origCronItem.GetTransactionNum();
914 
915  const int64_t closingAssetNumber =
916  (origCronItem.GetCountClosingNumbers() > 0)
917  ? origCronItem.GetClosingTransactionNoAt(0)
918  : 0;
919  const int64_t closingCurrencyNumber =
920  (origCronItem.GetCountClosingNumbers() > 1)
921  ? origCronItem.GetClosingTransactionNoAt(1)
922  : 0;
923 
924  const OTString serverID(GetServerID());
925 
926  // The marketReceipt ITEM's NOTE contains the UPDATED TRADE.
927  // And the **UPDATED OFFER** is stored on the ATTACHMENT on the **ITEM.**
928  //
929  // BUT!!! This is not a marketReceipt Item, is it? ***This is a finalReceipt
930  // ITEM!***
931  // I'm reversing note and attachment for finalReceipt, with the
932  // intention of
933  // eventually reversing them for marketReceipt as well. (Making them all in
934  // line with paymentReceipt.)
935  //
936  // WHY? Because I want a standard convention:
937  // 1. ORIGINAL (user-signed) Cron Items are always stored "in
938  // reference to" on cron receipts in the Inbox (an OTTransaction).
939  // 2. The UPDATED VERSION of that same cron item (a trade or
940  // payment plan) is stored in the ATTACHMENT on the OTItem member.
941  // 3. ADDITIONAL INFORMATION is stored in the NOTE field of the
942  // OTItem member.
943  //
944  // Unfortunately, marketReceipt doesn't adhere to this convention, as it
945  // stores the Updated Cron Item (the trade) in
946  // the note instead of the attachment, and it stores the updated Offer (the
947  // additional info) in the attachment instead
948  // of the note.
949  // Perhaps this is for the best -- it will certainly kick out any accidental
950  // confusions between marketReceipt and finalReceipt!
951  // todo: switch marketReceipt over to be like finalReceipt as described in
952  // this paragraph.
953  //
954  // Once everything is consistent on the above convention -- starting here
955  // and now with finalReceipt -- then we will ALWAYS
956  // be able to count on a Cron Item being in the Transaction Item's
957  // Attachment! We can load it using the existing factory class,
958  // without regard to type, KNOWING it's a cron item every time.
959  // todo: convert marketReceipt to do the same.
960 
961  // The finalReceipt Item's ATTACHMENT contains the UPDATED Cron Item.
962  // (With the SERVER's signature on it!)
963  //
964  OTString updatedCronItem(*this);
965  OTString* attachment = &updatedCronItem; // the Updated TRADE.
966  OTString updatedOffer;
967  OTString* note = nullptr; // the updated Offer (if available.)
968 
969  if (offer_) {
970  offer_->SaveContractRaw(updatedOffer);
971  note = &updatedOffer;
972  }
973 
974  const OTString strOrigCronItem(origCronItem);
975 
976  OTPseudonym theActualNym; // unused unless it's really not already loaded.
977  // (use actualNym.)
978 
979  // The OPENING transaction number must still be signed-out.
980  // It is this act of placing the final receipt, which then finally closes
981  // the opening number.
982  // The closing number, by contrast, is not closed out until the final
983  // Receipt is ACCEPTED
984  // (which happens in a "process inbox" transaction.)
985  //
986  if ((openingNumber > 0) &&
987  originator.VerifyIssuedNum(serverID, openingNumber)) {
988  // The Nym (server side) stores a list of all opening and closing cron
989  // #s.
990  // So when the number is released from the Nym, we also take it off that
991  // list.
992  //
993  std::set<int64_t>& idSet = originator.GetSetOpenCronItems();
994  idSet.erase(openingNumber);
995 
996  originator.RemoveIssuedNum(*serverNym, serverID, openingNumber,
997  false); // bSave=false
998  originator.SaveSignedNymfile(*serverNym); // forcing a save here,
999  // since multiple things
1000  // have changed.
1001 
1002  const OTIdentifier& actualNymId = GetSenderUserID();
1003 
1004  OTPseudonym* actualNym = nullptr; // use this. DON'T use theActualNym.
1005  if ((serverNym != nullptr) && serverNym->CompareID(actualNymId))
1006  actualNym = serverNym;
1007  else if (originator.CompareID(actualNymId))
1008  actualNym = &originator;
1009  else if ((remover != nullptr) && remover->CompareID(actualNymId))
1010  actualNym = remover;
1011 
1012  else // We couldn't find the Nym among those already loaded--so we have
1013  // to load
1014  { // it ourselves (so we can update its NymboxHash value.)
1015  theActualNym.SetIdentifier(actualNymId);
1016 
1017  if (!theActualNym.LoadPublicKey()) // Note: this step may be
1018  // unnecessary since we
1019  // are only updating his
1020  // Nymfile, not his key.
1021  {
1022  OTString strNymID(actualNymId);
1023  otErr << szFunc
1024  << ": Failure loading public key for Nym : " << strNymID
1025  << ". "
1026  "(To update his NymboxHash.) \n";
1027  }
1028  else if (theActualNym.VerifyPseudonym() && // this line may be
1029  // unnecessary.
1030  theActualNym.LoadSignedNymfile(
1031  *serverNym)) // ServerNym here is not theActualNym's
1032  // identity, but merely the signer on
1033  // this file.
1034  {
1035  otLog3
1036  << szFunc
1037  << ": Loading actual Nym, since he wasn't already loaded. "
1038  "(To update his NymboxHash.)\n";
1039  actualNym = &theActualNym; // <=====
1040  }
1041  else {
1042  OTString strNymID(actualNymId);
1043  otErr
1044  << szFunc
1045  << ": Failure loading or verifying Actual Nym public key: "
1046  << strNymID << ". "
1047  "(To update his NymboxHash.)\n";
1048  }
1049  }
1050 
1051  if (!DropFinalReceiptToNymbox(GetSenderUserID(), newTransactionNumber,
1052  strOrigCronItem, note, attachment,
1053  actualNym)) {
1054  otErr << szFunc << ": Failure dropping receipt into nymbox.\n";
1055  }
1056  }
1057  else {
1058  otErr << szFunc << ": Problem verifying Opening Number when calling "
1059  "VerifyIssuedNum(openingNumber)\n";
1060  }
1061 
1062  // ASSET ACCT
1063  //
1064  if ((closingAssetNumber > 0) &&
1065  originator.VerifyIssuedNum(serverID, closingAssetNumber)) {
1067  GetSenderUserID(), GetSenderAcctID(), newTransactionNumber,
1068  closingAssetNumber, // The closing transaction number to put on the
1069  // receipt.
1070  strOrigCronItem, note, attachment);
1071  }
1072  else {
1073  otErr << szFunc
1074  << ": Failed verifying "
1075  "closingAssetNumber=origCronItem."
1076  "GetClosingTransactionNoAt(0)>0 && "
1077  "originator.VerifyTransactionNum(closingAssetNumber)\n";
1078  }
1079 
1080  // CURRENCY ACCT
1081  //
1082  if ((closingCurrencyNumber > 0) &&
1083  originator.VerifyIssuedNum(serverID, closingCurrencyNumber)) {
1085  GetSenderUserID(), GetCurrencyAcctID(), newTransactionNumber,
1086  closingCurrencyNumber, // closing transaction number for the
1087  // receipt.
1088  strOrigCronItem, note, attachment);
1089  }
1090  else {
1091  otErr << szFunc
1092  << ": Failed verifying "
1093  "closingCurrencyNumber=origCronItem."
1094  "GetClosingTransactionNoAt(1)>0 "
1095  "&& "
1096  "originator.VerifyTransactionNum(closingCurrencyNumber)\n";
1097  }
1098 
1099  // the RemoveIssued call means the original transaction# (to find this cron
1100  // item on cron) is now CLOSED.
1101  // But the Transaction itself is still OPEN. How? Because the CLOSING number
1102  // is still signed out.
1103  // The closing number is also USED, since the NotarizePaymentPlan or
1104  // NotarizeMarketOffer call, but it
1105  // remains ISSUED, until the final receipt itself is accepted during a
1106  // process inbox.
1107  //
1108  // if (bDroppedReceiptAssetAcct || bDroppedReceiptCurrencyAcct) // ASSET
1109  // ACCOUNT and CURRENCY ACCOUNT
1110  // {
1111  // This part below doesn't happen until you ACCEPT the finalReceipt (when
1112  // processing your inbox.)
1113  //
1114  // if (bDroppedReceiptAssetAcct)
1115  // originator.RemoveIssuedNum(serverID, closingAssetNumber,
1116  // true); //bSave=false
1117  // else if (bDroppedReceiptCurrencyAcct)
1118  // originator.RemoveIssuedNum(serverID,
1119  // closingCurrencyNumber, true); //bSave=false
1120  // }
1121  // else
1122  // {
1123  // otErr << "OTTrade::onFinalReceipt: Failure dropping receipt into
1124  // asset or currency inbox.\n";
1125  // }
1126 
1127  // QUESTION: Won't there be Cron Items that have no asset account at all?
1128  // In which case, there'd be no need to drop a final receipt, but I don't
1129  // think
1130  // that's the case, since you have to use a transaction number to get onto
1131  // cron
1132  // in the first place.
1133 }
1134 
1135 // OTCron calls this regularly, which is my chance to expire, etc.
1136 // Return True if I should stay on the Cron list for more processing.
1137 // Return False if I should be removed and deleted.
1139 {
1140 
1141  // Right now Cron is called 10 times per second.
1142  // I'm going to slow down all trades so they are once every
1143  // GetProcessInterval()
1144  if (GetLastProcessDate() > OT_TIME_ZERO) {
1145  // (Default ProcessInterval is 1 second, but Trades will use 10 seconds,
1146  // and Payment Plans will use an hour or day.)
1149  return true;
1150  }
1151 
1152  // Keep a record of the last time this was processed.
1153  // (NOT saved to storage, only used while the software is running.)
1154  // (Thus no need to release signatures, sign contract, save contract, etc.)
1156 
1157  // PAST END DATE?
1158  // First call the parent's version (which this overrides) so it has
1159  // a chance to check its stuff. Currently it checks IsExpired().
1160  if (!ot_super::ProcessCron())
1161  return false; // It's expired or flagged for removal--remove it from
1162  // Cron.
1163 
1164  // You might ask, why not check here if this trade is flagged for removal?
1165  // Supposedly the answer is, because it's only below that I have the market
1166  // pointer,
1167  // and am able to remove the corresponding trade from the market.
1168  // Therefore I am adding a hook for "onRemoval" so that Objects such as
1169  // OTTrade ALWAYS
1170  // have the opportunity to perform such cleanup, without having to juggle
1171  // such logic.
1172 
1173  // REACHED START DATE?
1174  // Okay, so it's not expired. But might not have reached START DATE yet...
1175  if (!VerifyCurrentDate())
1176  return true; // The Trade is not yet valid, so we return. BUT, we return
1177  // true, so it will stay on Cron until it BECOMES valid.
1178 
1179  // TRADE-specific stuff below.
1180 
1181  bool bStayOnMarket =
1182  true; // by default stay on the market (until some rule expires me.)
1183 
1184  OTIdentifier OFFER_MARKET_ID;
1185  OTMarket* market = nullptr;
1186 
1187  // If the Offer is already active on a market, then I already have a pointer
1188  // to
1189  // it. This function returns that pointer. If nullptr, it tries to find the
1190  // offer on
1191  // the market and then sets the pointer and returns. If it can't find it, IT
1192  // TRIES
1193  // TO ADD IT TO THE MARKET and sets the pointer and returns it.
1194  OTOffer* offer = GetOffer(
1195  &OFFER_MARKET_ID, &market); // Both of these parameters are optional.
1196 
1197  // In this case, the offer is NOT on the market.
1198  // Perhaps it wasn't ready to activate yet.
1199  if (offer == nullptr) {
1200  // The offer SHOULD HAVE been on the market, since we're within the
1201  // valid range,
1202  // and GetOffer adds it when it's not already there.
1203 
1204  // otErr << "OTTrade::ProcessCron: Offer SHOULD have been on
1205  // Market. I might ASSERT this.\n"; // comment this out
1206 
1207  // Actually! If it's a Stop Order, then it WOULD be within the valid
1208  // range, yet would
1209  // not yet have activated. So I don't want to log some big error every
1210  // time a stop order
1211  // checks its prices.
1212  }
1213  else if (market == nullptr) {
1214  // todo. (This will already leave a log above in GetOffer somewhere.)
1215  // otErr << "OTTrade::ProcessCron: Market was nullptr.\n"; //
1216  // comment this out
1217  }
1218  else // If a valid pointer was returned, that means the offer is on the
1219  // market.
1220  {
1221  // Make sure it hasn't already been flagged by someone else...
1222  if (IsFlaggedForRemoval()) // This is checked above in
1223  // OTCronItem::ProcessCron().
1224  bStayOnMarket = false; // I'm leaving the check here in case the
1225  // flag was set since then.
1226 
1227  else // Process it! <===================
1228  {
1229  otInfo << "Processing trade: " << GetTransactionNum() << ".\n";
1230 
1231  bStayOnMarket = market->ProcessTrade(*this, *offer);
1232  // No need to save the Trade or Offer, since they will
1233  // be saved inside this call if they are changed.
1234  }
1235  }
1236 
1237  // Return True if I should stay on the Cron list for more processing.
1238  // Return False if I should be removed and deleted.
1239  return bStayOnMarket; // defaults true, so if false, that means someone is
1240  // removing it for a reason.
1241 }
1242 
1243 /*
1244 X OTIdentifier currencyTypeID_; // GOLD (Asset) is trading for DOLLARS
1245 (Currency).
1246 X OTIdentifier currencyAcctID_; // My Dollar account, used for paying
1247 for my Gold (say) trades.
1248 
1249 X int64_t stopPrice_; // The price limit that activates the
1250 STOP order.
1251 X char stopSign_; // Value is 0, or '<', or '>'.
1252 
1253 X time64_t m_CREATION_DATE; // The date, in seconds, when the trade
1254 was authorized.
1255 X int32_t tradesAlreadyDone_; // How many trades have already
1256 processed through this order? We keep track.
1257 */
1258 
1259 // This is called by the client side. First you call MakeOffer() to set up the
1260 // Offer,
1261 // then you call IssueTrade() and pass the Offer into it here.
1262 bool OTTrade::IssueTrade(OTOffer& offer, char stopSign, int64_t stopPrice)
1263 {
1264  // Make sure the Stop Sign is within parameters (0, '<', or '>')
1265  if ((stopSign == 0) || (stopSign == '<') || (stopSign == '>'))
1266  stopSign_ = stopSign;
1267  else {
1268  otErr << "Bad data in Stop Sign while issuing trade: " << stopSign
1269  << "\n";
1270  return false;
1271  }
1272 
1273  // Make sure, if this IS a Stop order, that the price is within parameters
1274  // and set.
1275  if ((stopSign_ == '<') || (stopSign_ == '>')) {
1276  if (0 >= stopPrice) {
1277  otErr << "Expected Stop Price for trade.\n";
1278  return false;
1279  }
1280 
1281  stopPrice_ = stopPrice;
1282  }
1283 
1284  tradesAlreadyDone_ = 0;
1285 
1287  OTTimeGetCurrentTime()); // This time is set to TODAY NOW (OTCronItem)
1288 
1289  // Validate the Server ID, Asset Type ID, Currency Type ID, and Date Range.
1290  if ((GetServerID() != offer.GetServerID()) ||
1291  (GetCurrencyID() != offer.GetCurrencyID()) ||
1292  (GetAssetID() != offer.GetAssetID()) ||
1293  (offer.GetValidFrom() < OT_TIME_ZERO) ||
1294  (offer.GetValidTo() < offer.GetValidFrom())) {
1295  return false;
1296  }
1297 
1298  // currencyTypeID_ // This is already set in the constructors of this
1299  // and the offer. (And compared.)
1300  // currencyAcctID_ // This is already set in the constructor of this.
1301 
1302  // Set the (now validated) date range as per the Offer.
1303  SetValidFrom(offer.GetValidFrom());
1304  SetValidTo(offer.GetValidTo());
1305 
1306  // Get the transaction number from the Offer.
1308 
1309  // Save a copy of the offer, in XML form, here on this Trade.
1310  OTString strOffer(offer);
1311  marketOffer_.Set(strOffer);
1312 
1313  return true;
1314 }
1315 
1317  : ot_super()
1318  , offer_(nullptr)
1319  , hasTradeActivated_(false)
1320  , stopPrice_(0)
1321  , stopSign_(0)
1322  , stopActivated_(false)
1323  , tradesAlreadyDone_(0)
1324 {
1325  // offer_ = nullptr; // NOT responsible to clean this up.
1326  // Just keeping the pointer for convenience.
1327  // You might ask, "but what if it goes bad?" Actually only THIS object
1328  // should ever decide that.
1329  // Only the Trade object decides when to add or remove an offer from any
1330  // market.
1331 
1332  InitTrade();
1333 }
1334 
1335 OTTrade::OTTrade(const OTIdentifier& serverId, const OTIdentifier& assetId,
1336  const OTIdentifier& assetAcctId, const OTIdentifier& userId,
1337  const OTIdentifier& currencyId,
1338  const OTIdentifier& currencyAcctId)
1339  : ot_super(serverId, assetId, assetAcctId, userId)
1340  , offer_(nullptr)
1341  , hasTradeActivated_(false)
1342  , stopPrice_(0)
1343  , stopSign_(0)
1344  , stopActivated_(false)
1345  , tradesAlreadyDone_(0)
1346 {
1347  // offer_ = nullptr; // NOT responsible to clean this up.
1348  // Just keeping the pointer for convenience.
1349  // You might ask, "but what if it goes bad?" Actually only THIS object
1350  // should ever decide that.
1351  // Only the Trade object decides when to add or remove an offer from any
1352  // market.
1353 
1354  InitTrade();
1355 
1356  SetCurrencyID(currencyId);
1357  SetCurrencyAcctID(currencyAcctId);
1358 }
1359 
1361 {
1362  Release_Trade();
1363 }
1364 
1365 // the framework will call this at the right time.
1367 {
1368  // If there were any dynamically allocated objects, clean them up here.
1369  currencyTypeID_.Release();
1370  currencyAcctID_.Release();
1371 
1372  marketOffer_.Release();
1373 }
1374 
1375 // the framework will call this at the right time.
1377 {
1378  Release_Trade();
1379 
1381 
1382  // Then I call this to re-initialize everything
1383  // (Only cause it's convenient...)
1384  InitTrade();
1385 }
1386 
1387 // This CAN have values that are reset
1389 {
1390  // initialization here. Sometimes also called during cleanup to zero values.
1391  m_strContractType = "TRADE";
1392 
1393  SetProcessInterval(TradeProcessIntervalSeconds); // Trades default to
1394  // processing every 10
1395  // seconds.
1396  // (vs 1 second for Cron items and 1 hour for payment plans)
1397 
1398  tradesAlreadyDone_ = 0;
1399 
1400  stopSign_ = 0; // IS THIS a STOP order? Value is 0, or '<', or '>'.
1401  stopPrice_ = 0; // The price limit that activates the STOP order.
1402  stopActivated_ = false; // Once the Stop Order activates, it puts the
1403  // order on the market.
1404  // I'll put a "HasOrderOnMarket()" bool method that answers this for u.
1405  hasTradeActivated_ = false; // I want to keep track of general activations
1406  // as well, not just stop orders.
1407 }
1408 
1409 bool OTTrade::SaveContractWallet(std::ofstream&) const
1410 {
1411  return true;
1412 }
1413 
1414 } // namespace opentxs
OTMarket * GetOrCreateMarket(const OTIdentifier &ASSET_ID, const OTIdentifier &CURRENCY_ID, const int64_t &lScale)
Definition: OTCron.cpp:1070
bool AddOffer(OTTrade *pTrade, OTOffer &theOffer, bool bSaveFile=true, time64_t tDateAddedToMarket=OT_TIME_ZERO)
Definition: OTMarket.cpp:740
virtual bool SaveContractWallet(std::ofstream &ofs) const
Definition: OTTrade.cpp:1409
OTOffer * GetOffer(const int64_t &lTransactionNum)
Definition: OTMarket.cpp:623
virtual bool VerifyNymAsAgent(OTPseudonym &nym, OTPseudonym &signerNym, mapOfNyms *preloadedMap=nullptr) const
Definition: OTTrade.cpp:165
const OTIdentifier & GetSenderUserID() const
time64_t GetValidTo() const
void SetValidFrom(time64_t TIME_FROM)
bool IsGreaterThan() const
Definition: OTTrade.hpp:239
virtual int64_t GetClosingNumber(const OTIdentifier &acctId) const
Definition: OTTrade.cpp:790
int64_t GetTransactionNum() const
const int64_t & GetScale() const
Definition: OTOffer.hpp:299
virtual void Release()
Definition: OTTrade.cpp:1376
int64_t OTTimeGetTimeInterval(time64_t lhs, time64_t rhs)
Definition: Common.hpp:234
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
EXPORT bool SaveContract()
EXPORT bool VerifyIssuedNum(const OTString &strServerID, const int64_t &lTransNum) const
EXPORT int64_t ToLong() const
Definition: OTString.cpp:702
bool IsLessThan() const
Definition: OTTrade.hpp:247
const OTIdentifier & GetAssetID() const
const OTIdentifier & GetCurrencyID() const
Definition: OTOffer.hpp:304
bool IsFlaggedForRemoval() const
Definition: OTCronItem.hpp:238
OTLOG_IMPORT OTLogStream otOut
std::map< std::string, OTPseudonym * > mapOfNyms
Definition: OTWallet.hpp:161
OTLOG_IMPORT OTLogStream otLog3
int64_t GetLowestAskPrice()
Definition: OTMarket.cpp:934
const OTIdentifier & GetCurrencyAcctID() const
Definition: OTTrade.hpp:269
EXPORT bool SaveContractRaw(OTString &strOutput) const
const int64_t & GetStopPrice() const
Definition: OTTrade.hpp:234
void SetTrade(const OTTrade &theTrade)
Definition: OTOffer.hpp:332
void SetValidTo(time64_t TIME_TO)
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
Definition: Common.hpp:215
void SetAssetID(const OTIdentifier &ASSET_ID)
EXPORT bool LoadSignedNymfile(OTPseudonym &SIGNER_NYM)
EXPORT bool IssueTrade(OTOffer &offer, char stopSign=0, int64_t stopPrice=0)
Definition: OTTrade.cpp:1262
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
EXPORT bool VerifyCurrentDate()
void SetCreationDate(const time64_t &CREATION_DATE)
Definition: OTCronItem.hpp:264
virtual EXPORT ~OTTrade()
Definition: OTTrade.cpp:1360
EXPORT int64_t GetClosingTransactionNoAt(uint32_t nIndex) const
Definition: OTCronItem.cpp:681
EXPORT bool VerifyPseudonym() const
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT void SetIdentifier(const OTIdentifier &theIdentifier)
EXPORT bool VerifyOffer(OTOffer &offer) const
Definition: OTTrade.cpp:389
const OTIdentifier & GetServerID() const
time64_t GetValidFrom() const
EXPORT bool LoadPublicKey()
bool DropFinalReceiptToInbox(const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID, const int64_t &lNewTransactionNumber, const int64_t &lClosingNumber, const OTString &strOrigCronItem, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTAccount *pActualAcct=nullptr)
virtual void onRemovalFromCron()
Definition: OTTrade.cpp:716
EXPORT int32_t GetCountClosingNumbers() const
Definition: OTCronItem.cpp:676
virtual void onFinalReceipt(OTCronItem &origCronItem, const int64_t &newTransactionNumber, OTPseudonym &originator, OTPseudonym *remover)
Definition: OTTrade.cpp:892
EXPORT bool VerifyOwner(const OTPseudonym &candidate) const
Definition: OTAccount.cpp:463
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
time64_t OTTimeGetCurrentTime()
Definition: Common.hpp:211
EXPORT void Assign(const OTData &source)
Definition: OTData.cpp:275
virtual bool ProcessCron()
Definition: OTCronItem.cpp:769
virtual bool ProcessCron()
Definition: OTTrade.cpp:1138
void Release_Trade()
Definition: OTTrade.cpp:1366
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
EXPORT bool RemoveIssuedNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lTransNum, bool bSave)
void SetTransactionNum(int64_t lTransactionNum)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTString m_strContractType
Definition: OTContract.hpp:178
const int64_t & GetTransactionNum() const
Definition: OTOffer.hpp:277
OTLOG_IMPORT OTLogStream otInfo
void SetCurrencyAcctID(const OTIdentifier &currencyAcctID)
Definition: OTTrade.hpp:274
EXPORT bool CompareID(const OTIdentifier &theIdentifier) const
const int64_t & GetProcessInterval() const
Definition: OTCronItem.hpp:288
void SetSenderAcctID(const OTIdentifier &ACCT_ID)
const OTIdentifier & GetCurrencyID() const
Definition: OTTrade.hpp:259
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
EXPORT int64_t GetOpeningNum() const
void SetCurrencyID(const OTIdentifier &currencyId)
Definition: OTTrade.hpp:264
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
Definition: OTString.cpp:1045
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTContract.cpp:484
void SetServerID(const OTIdentifier &SERVER_ID)
OTLOG_IMPORT OTLogStream otErr
virtual bool CanRemoveItemFromCron(OTPseudonym &nym)
Definition: OTTrade.cpp:813
EXPORT int64_t GetCurrencyAcctClosingNum() const
Definition: OTTrade.cpp:805
void ProcessTrade(OTTrade &theTrade, OTOffer &theOffer, OTOffer &theOtherOffer)
Definition: OTMarket.cpp:1023
EXPORT int64_t GetAssetAcctClosingNum() const
Definition: OTTrade.cpp:799
OTPseudonym * GetServerNym() const
Definition: OTCron.hpp:303
int64_t GetHighestBidPrice()
Definition: OTMarket.cpp:919
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
Definition: OTContract.cpp:818
const OTIdentifier & GetSenderAcctID() const
const time64_t & GetLastProcessDate() const
Definition: OTCronItem.hpp:279
std::set< int64_t > & GetSetOpenCronItems()
EXPORT OTTrade()
Definition: OTTrade.cpp:1316
bool DropFinalReceiptToNymbox(const OTIdentifier &USER_ID, const int64_t &lNewTransactionNumber, const OTString &strOrigCronItem, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTPseudonym *pActualNym=nullptr)
void SetSenderUserID(const OTIdentifier &USER_ID)
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
EXPORT bool LoadContractFromString(const OTString &theStr)
virtual bool VerifyNymAsAgentForAccount(OTPseudonym &nym, OTAccount &account) const
Definition: OTTrade.cpp:175
#define OT_TIME_ZERO
Definition: Common.hpp:180
virtual EXPORT void Release()
Definition: OTData.cpp:257
EXPORT OTMarket * GetMarket(const OTIdentifier &MARKET_ID)
Definition: OTCron.cpp:1110
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
Definition: OTTrade.cpp:182
OTOffer * GetOffer(OTIdentifier *offerMarketId=nullptr, OTMarket **market=nullptr)
Definition: OTTrade.cpp:421
bool RemoveOffer(const int64_t &lTransactionNum)
Definition: OTMarket.cpp:649
virtual void UpdateContents()
Definition: OTTrade.cpp:311
virtual EXPORT void Release()
Definition: OTString.cpp:765
virtual void Release()
void SetProcessInterval(const int64_t &THE_DATE)
Definition: OTCronItem.hpp:284
EXPORT bool SaveSignedNymfile(OTPseudonym &SIGNER_NYM)
const time64_t & GetCreationDate() const
Definition: OTCronItem.hpp:268
bool IsStopOrder() const
Definition: OTTrade.hpp:226
OTLOG_IMPORT OTLogStream otLog5
void SetLastProcessDate(const time64_t &THE_DATE)
Definition: OTCronItem.hpp:275