bool OTAgreement::SetAgreement(const long & lTransactionNum, const OTString & strConsideration, const time_t & VALID_FROM/*=0*/, const time_t & VALID_TO/*=0*/) { // Set the Transaction Number... SetTransactionNum(lTransactionNum); // Set the Consideration memo... m_strConsideration.Set(strConsideration); // ------------------------------------------- time_t CURRENT_TIME = time(NULL); // Set the Creation Date. SetCreationDate(CURRENT_TIME); // ------------------------------------------- // The default "valid from" time is NOW. if (0 >= VALID_FROM) // if it's 0 or less, set to current time. SetValidFrom(CURRENT_TIME); else // Otherwise use whatever was passed in. SetValidFrom(VALID_FROM); // ------------------------------------------- // The default "valid to" time is 0 (which means no expiration date / cancel anytime.) if (0 == VALID_TO) // VALID_TO is 0 { SetValidTo(VALID_TO); // Keep it at zero then, so it won't expire. } else if (0 < VALID_TO) // VALID_TO is ABOVE zero... { if (VALID_TO < VALID_FROM) // If Valid-To date is EARLIER than Valid-From date... { long lValidTo = VALID_TO, lValidFrom = VALID_FROM; OTLog::vError("VALID_TO is earlier than VALID_FROM in SetAgreement: %ld, %ld\n", lValidTo, lValidFrom); return false; } SetValidTo(VALID_TO); // Set it to whatever it is, since it is now validated as higher than Valid-From. } else // VALID_TO is a NEGATIVE number... Error. { long lValidTo = VALID_TO; OTLog::vError("Negative value for valid_to in SetAgreement: %ld\n", lValidTo); return false; } // ------------------------------------------- OTLog::Output(4, "Successfully performed SetAgreement()\n"); return true; }
// This is called by the client side. First you call MakeOffer() to set up the // Offer, // then you call IssueTrade() and pass the Offer into it here. bool OTTrade::IssueTrade(OTOffer& offer, char stopSign, int64_t stopPrice) { // Make sure the Stop Sign is within parameters (0, '<', or '>') if ((stopSign == 0) || (stopSign == '<') || (stopSign == '>')) stopSign_ = stopSign; else { otErr << "Bad data in Stop Sign while issuing trade: " << stopSign << "\n"; return false; } // Make sure, if this IS a Stop order, that the price is within parameters // and set. if ((stopSign_ == '<') || (stopSign_ == '>')) { if (0 >= stopPrice) { otErr << "Expected Stop Price for trade.\n"; return false; } stopPrice_ = stopPrice; } tradesAlreadyDone_ = 0; SetCreationDate( OTTimeGetCurrentTime()); // This time is set to TODAY NOW (OTCronItem) // Validate the Notary ID, Instrument Definition ID, Currency Type ID, and // Date Range. if ((GetNotaryID() != offer.GetNotaryID()) || (GetCurrencyID() != offer.GetCurrencyID()) || (GetInstrumentDefinitionID() != offer.GetInstrumentDefinitionID()) || (offer.GetValidFrom() < OT_TIME_ZERO) || (offer.GetValidTo() < offer.GetValidFrom())) { return false; } // currencyTypeID_ // This is already set in the constructors of this // and the offer. (And compared.) // currencyAcctID_ // This is already set in the constructor of this. // Set the (now validated) date range as per the Offer. SetValidFrom(offer.GetValidFrom()); SetValidTo(offer.GetValidTo()); // Get the transaction number from the Offer. SetTransactionNum(offer.GetTransactionNum()); // Save a copy of the offer, in XML form, here on this Trade. String strOffer(offer); marketOffer_.Set(strOffer); return true; }
// return -1 if error, 0 if nothing, and 1 if the node was processed. int32_t OTTrade::ProcessXMLNode(irr::io::IrrXMLReader*& xml) { int32_t returnVal = 0; // Here we call the parent class first. // If the node is found there, or there is some error, // then we just return either way. But if it comes back // as '0', then nothing happened, and we'll continue executing. // // -- Note you can choose not to call the parent if // you don't want to use any of those xml tags. // As I do below, in the case of OTAccount. // if (0 != (returnVal = ot_super::ProcessXMLNode(xml))) return returnVal; if (!strcmp("trade", xml->getNodeName())) { m_strVersion = xml->getAttributeValue("version"); tradesAlreadyDone_ = atoi(xml->getAttributeValue("completedNoTrades")); SetTransactionNum( String::StringToLong(xml->getAttributeValue("transactionNum"))); const std::string creationStr = xml->getAttributeValue("creationDate"); const std::string validFromStr = xml->getAttributeValue("validFrom"); const std::string validToStr = xml->getAttributeValue("validTo"); int64_t creation = parseTimestamp(creationStr); int64_t validFrom = parseTimestamp(validFromStr); int64_t validTo = parseTimestamp(validToStr); SetCreationDate(OTTimeGetTimeFromSeconds(creation)); SetValidFrom(OTTimeGetTimeFromSeconds(validFrom)); SetValidTo(OTTimeGetTimeFromSeconds(validTo)); String activated(xml->getAttributeValue("hasActivated")); if (activated.Compare("true")) hasTradeActivated_ = true; else hasTradeActivated_ = false; const String notaryID(xml->getAttributeValue("notaryID")), nymID(xml->getAttributeValue("nymID")), instrumentDefinitionID( xml->getAttributeValue("instrumentDefinitionID")), assetAcctID(xml->getAttributeValue("assetAcctID")), currencyTypeID(xml->getAttributeValue("currencyTypeID")), currencyAcctID(xml->getAttributeValue("currencyAcctID")); const Identifier NOTARY_ID(notaryID), NYM_ID(nymID), INSTRUMENT_DEFINITION_ID(instrumentDefinitionID), ASSET_ACCT_ID(assetAcctID), CURRENCY_TYPE_ID(currencyTypeID), CURRENCY_ACCT_ID(currencyAcctID); SetNotaryID(NOTARY_ID); SetSenderNymID(NYM_ID); SetInstrumentDefinitionID(INSTRUMENT_DEFINITION_ID); SetSenderAcctID(ASSET_ACCT_ID); SetCurrencyID(CURRENCY_TYPE_ID); SetCurrencyAcctID(CURRENCY_ACCT_ID); otLog3 << "\n\nTrade. Transaction Number: " << m_lTransactionNum << " Completed # of Trades: " << tradesAlreadyDone_ << "\n"; otWarn << " Creation Date: " << creation << " Valid From: " << validFrom << "\n Valid To: " << validTo << "\n" " instrumentDefinitionID: " << instrumentDefinitionID << "\n assetAcctID: " << assetAcctID << "\n" " NotaryID: " << notaryID << "\n NymID: " << nymID << "\n " " currencyTypeID: " << currencyTypeID << "\n currencyAcctID: " << currencyAcctID << "\n "; returnVal = 1; } if (!strcmp("stopOrder", xml->getNodeName())) { String sign(xml->getAttributeValue("sign")); if (sign.Compare("0")) { stopSign_ = 0; // Zero means it isn't a stop order. So why is the // tag in the file? otErr << "Strange: Stop order tag found in trade, but sign " "character set to 0.\n" "(Zero means: NOT a stop order.)\n"; return (-1); } else if (sign.Compare("<")) stopSign_ = '<'; else if (sign.Compare(">")) stopSign_ = '>'; else { stopSign_ = 0; otErr << "Unexpected or nonexistent value in stop order sign: " << sign << "\n"; return (-1); } // Now we know the sign is properly formed, let's grab the price value. stopPrice_ = String::StringToLong(xml->getAttributeValue("price")); String activated(xml->getAttributeValue("hasActivated")); if (activated.Compare("true")) stopActivated_ = true; else stopActivated_ = false; otLog3 << "\n\nStop order -- " << (stopActivated_ ? "Already activated" : "Will activate") << " when price " << (stopActivated_ ? "was" : "reaches") << " " << (('<' == stopSign_) ? "LESS THAN" : "GREATER THAN") << ": " << stopPrice_ << ".\n"; returnVal = 1; } else if (!strcmp("offer", xml->getNodeName())) { if (!Contract::LoadEncodedTextField(xml, marketOffer_)) { otErr << "Error in OTTrade::ProcessXMLNode: offer field without " "value.\n"; return (-1); // error condition } returnVal = 1; } return returnVal; }
// THIS FUNCTION IS CALLED BY THE CUSTOMER // // (Transaction number and closing number are retrieved from Nym at this time.) bool OTAgreement::Confirm(OTPseudonym & MERCHANT_NYM, OTPseudonym & PAYER_NYM) { // ---------------------------------------------------------------------------- OTIdentifier id_MERCHANT_NYM, id_PAYER_NYM; MERCHANT_NYM.GetIdentifier(id_MERCHANT_NYM); PAYER_NYM.GetIdentifier(id_PAYER_NYM); if (GetRecipientUserID() == GetSenderUserID()) { OTLog::Output(0, "OTAgreement::Confirm: Error: Sender and recipient have the same Nym ID (not allowed.)\n"); return false; } else if (GetRecipientUserID() != id_MERCHANT_NYM) { OTLog::Output(0, "OTAgreement::Confirm: Merchant has wrong NymID (should be same as RecipientUserID.)\n"); return false; } else if (GetSenderUserID() != id_PAYER_NYM) { OTLog::Output(0, "OTAgreement::Confirm: Payer has wrong NymID (should be same as SenderUserID.)\n"); return false; } else if (PAYER_NYM.GetTransactionNumCount(GetServerID()) < 2) // Need opening and closing numbers (that's 2)... { OTLog::Output(0, "OTAgreement::Confirm: Failure. You need at least 2 transaction numbers available to do this.\n"); return false; } else if (GetRecipientCountClosingNumbers() < 2) { OTLog::Output(0, "OTAgreement::Confirm: Failure. (The merchant was supposed to attach 2 transaction numbers.)\n"); return false; } // ---------------------------------------------------------------------------- // This is the single reason why MERCHANT_NYM was even passed in here! // Supposedly merchant has already signed. Let's verify this!! // if (false == this->VerifySignature(MERCHANT_NYM)) { OTLog::Output(0, "OTAgreement::Confirm: Merchant's signature failed to verify.\n"); return false; } // ---------------------------------------------------------------------------- // Now that we KNOW the merchant signed it... SAVE MERCHANT's COPY. // Let's save a copy of the one the merchant signed, before changing it and re-signing it, // (to add my own transaction numbers...) // OTString strTemp; this->SaveContractRaw(strTemp); this->SetMerchantSignedCopy(strTemp); // ******************************************************************* // The payer has to submit TWO transaction numbers in order to activate this agreement... // OTString strServerID(GetServerID()); long lTransactionNumber=0, lClosingTransactionNo=0; if (false == PAYER_NYM.GetNextTransactionNum(PAYER_NYM, strServerID, lTransactionNumber)) { OTLog::Error("OTAgreement::Confirm: Error: Strangely unable to get a transaction number.\n"); return false; } else if (false == PAYER_NYM.GetNextTransactionNum(PAYER_NYM, strServerID, lClosingTransactionNo)) { OTLog::Error("OTAgreement::Confirm: Error: Strangely unable to get a closing transaction number.\n"); PAYER_NYM.AddTransactionNum(PAYER_NYM, strServerID, lTransactionNumber, true); // bSave=true // (Since the first one was successful, we just put it back before returning.) return false; } // At this point we now HAVE 2 transaction numbers (for payer / sender)... // We can't return without USING THEM or PUTTING THEM BACK. // // --------------------------------------------------------- this->SetTransactionNum(lTransactionNumber); // Set the Transaction Number this->AddClosingTransactionNo(lClosingTransactionNo); // and the Closing Number (both for sender)... // ------------------------------------------- // CREATION DATE was set in the Merchant's proposal, and it's RESET here in the Confirm. // This way, (since we still have the original proposal) we can see BOTH times. // time_t CURRENT_TIME = time(NULL); // Set the Creation Date. SetCreationDate(CURRENT_TIME); // ------------------------------------------- OTLog::Output(4, "OTAgreement::Confirm(): Success!\n"); return true; }
// THIS FUNCTION IS CALLED BY THE MERCHANT // // (lMerchantTransactionNumber, lMerchantClosingNumber are set internally in this call, from MERCHANT_NYM.) bool OTAgreement::SetProposal(OTPseudonym & MERCHANT_NYM, const OTString & strConsideration, const time_t VALID_FROM/*=0*/, const time_t VALID_TO/*=0*/) { // ---------------------------------------------------------------------------- OTIdentifier id_MERCHANT_NYM; MERCHANT_NYM.GetIdentifier(id_MERCHANT_NYM); if (GetRecipientUserID() != id_MERCHANT_NYM) { OTLog::Output(0, "OTAgreement::SetProposal: Merchant has wrong NymID (should be same as RecipientUserID.)\n"); return false; } else if (GetRecipientUserID() == GetSenderUserID()) { OTLog::Output(0, "OTAgreement::SetProposal: Error: Sender and recipient have the same Nym ID (not allowed.)\n"); return false; } else if (MERCHANT_NYM.GetTransactionNumCount(GetServerID()) < 2) // Need opening and closing numbers (that's 2)... { OTLog::Output(0, "OTAgreement::SetProposal: Failure. You need at least 2 transaction numbers available to do this.\n"); return false; } // ------------------------------------------- // Set the CREATION DATE // const time_t CURRENT_TIME = time(NULL); // Set the Creation Date. SetCreationDate(CURRENT_TIME); // ----------------------------------------- // Putting this above here so I don't have to put the transaction numbers back if this fails: // ------------------------------------------- // VALID_FROM // // The default "valid from" time is NOW. if (0 >= VALID_FROM) // if it's 0 or less, set to current time. SetValidFrom(CURRENT_TIME); else // Otherwise use whatever was passed in. SetValidFrom(VALID_FROM); // ------------------------------------------- // VALID_TO // // The default "valid to" time is 0 (which means no expiration date / cancel anytime.) if (0 == VALID_TO) // VALID_TO is 0 { SetValidTo(VALID_TO); // Keep it at zero then, so it won't expire. } else if (0 < VALID_TO) // VALID_TO is ABOVE zero... { if (VALID_TO < VALID_FROM) // If Valid-To date is EARLIER than Valid-From date... { long lValidTo = VALID_TO, lValidFrom = VALID_FROM; OTLog::vError("OTAgreement::SetProposal: VALID_TO (%ld) is earlier than VALID_FROM (%ld)\n", lValidTo, lValidFrom); return false; } SetValidTo(VALID_TO); // Set it to whatever it is, since it is now validated as higher than Valid-From. } else // VALID_TO is a NEGATIVE number... Error. { long lValidTo = VALID_TO; OTLog::vError("Negative value for valid_to in SetAgreement: %ld\n", lValidTo); return false; } // ---------------------------------------------------------------------------- // Since we'll be needing 2 transaction numbers to do this, let's grab 'em... // OTString strServerID(GetServerID()); long lTransactionNumber=0, lClosingTransactionNo=0; if (MERCHANT_NYM.GetTransactionNumCount(GetServerID()) < 2) // Need opening and closing numbers (that's 2)... { OTLog::Output(0, "OTAgreement::SetProposal: Failure. You need at least 2 transaction numbers available to do this.\n"); return false; } else if (false == MERCHANT_NYM.GetNextTransactionNum(MERCHANT_NYM, strServerID, lTransactionNumber)) { OTLog::Error("OTAgreement::SetProposal: Error: Strangely unable to get a transaction number.\n"); return false; } else if (false == MERCHANT_NYM.GetNextTransactionNum(MERCHANT_NYM, strServerID, lClosingTransactionNo)) { OTLog::Error("OTAgreement::SetProposal: Error: Strangely unable to get a closing transaction number.\n"); MERCHANT_NYM.AddTransactionNum(MERCHANT_NYM, strServerID, lTransactionNumber, true); // bSave=true // (Since the first one was successful, we just put it back before returning.) return false; } // At this point we now have 2 transaction numbers... // We can't return without either USING THEM, or PUTTING THEM BACK. // // --------------------------------------------------------- // Set the Transaction Number and the Closing transaction number... (for merchant / recipient.) // this->AddRecipientClosingTransactionNo(lTransactionNumber); this->AddRecipientClosingTransactionNo(lClosingTransactionNo); // (They just both go onto this same list.) // ------------------------------------------- // Set the Consideration memo... m_strConsideration.Set(strConsideration); // ------------------------------------------- OTLog::Output(4, "Successfully performed OTPaymentPlan::SetProposal()\n"); return true; }
// return -1 if error, 0 if nothing, and 1 if the node was processed. int OTAgreement::ProcessXMLNode(irr::io::IrrXMLReader*& xml) { int nReturnVal = 0; // Here we call the parent class first. // If the node is found there, or there is some error, // then we just return either way. But if it comes back // as '0', then nothing happened, and we'll continue executing. // // -- Note you can choose not to call the parent if // you don't want to use any of those xml tags. // As I do below, in the case of OTAccount. if (0 != (nReturnVal = OTCronItem::ProcessXMLNode(xml))) return nReturnVal; // ------------------------------------------------- if (!strcmp("agreement", xml->getNodeName())) { m_strVersion = xml->getAttributeValue("version"); SetTransactionNum( atol(xml->getAttributeValue("transactionNum")) ); SetCreationDate( atoi(xml->getAttributeValue("creationDate"))); SetValidFrom( atoi(xml->getAttributeValue("validFrom"))); SetValidTo( atoi(xml->getAttributeValue("validTo"))); // --------------------- const OTString strServerID(xml->getAttributeValue("serverID")), strAssetTypeID(xml->getAttributeValue("assetTypeID")), strSenderAcctID(xml->getAttributeValue("senderAcctID")), strSenderUserID(xml->getAttributeValue("senderUserID")), strRecipientAcctID(xml->getAttributeValue("recipientAcctID")), strRecipientUserID(xml->getAttributeValue("recipientUserID")); const OTIdentifier SERVER_ID(strServerID), ASSET_ID(strAssetTypeID), SENDER_ACCT_ID(strSenderAcctID), SENDER_USER_ID(strSenderUserID), RECIPIENT_ACCT_ID(strRecipientAcctID), RECIPIENT_USER_ID(strRecipientUserID); SetServerID(SERVER_ID); SetAssetID(ASSET_ID); SetSenderAcctID(SENDER_ACCT_ID); SetSenderUserID(SENDER_USER_ID); SetRecipientAcctID(RECIPIENT_ACCT_ID); SetRecipientUserID(RECIPIENT_USER_ID); // --------------------- OTLog::vOutput(0, "\n\nAgreement. Transaction Number: %ld\n", m_lTransactionNum); OTLog::vOutput(1, " Creation Date: %d Valid From: %d\n Valid To: %d\n" " AssetTypeID: %s\n ServerID: %s\n" " senderAcctID: %s\n senderUserID: %s\n " " recipientAcctID: %s\n recipientUserID: %s\n ", GetCreationDate(), GetValidFrom(), GetValidTo(), strAssetTypeID.Get(), strServerID.Get(), strSenderAcctID.Get(), strSenderUserID.Get(), strRecipientAcctID.Get(), strRecipientUserID.Get()); nReturnVal = 1; } else if (!strcmp("consideration", xml->getNodeName())) { if (false == LoadEncodedTextField(xml, m_strConsideration)) { OTLog::Error("Error in OTPaymentPlan::ProcessXMLNode: consideration field without value.\n"); return (-1); // error condition } nReturnVal = 1; } else if (!strcmp("merchantSignedCopy", xml->getNodeName())) { if (false == LoadEncodedTextField(xml, m_strMerchantSignedCopy)) { OTLog::Error("Error in OTPaymentPlan::ProcessXMLNode: merchant_signed_copy field without value.\n"); return (-1); // error condition } nReturnVal = 1; } // ------------------------------------------- // std::deque<long> m_dequeRecipientClosingNumbers; // Numbers used for CLOSING a transaction. (finalReceipt.) else if (!strcmp("closingRecipientNumber", xml->getNodeName())) { OTString strClosingNumber = xml->getAttributeValue("value"); if (strClosingNumber.Exists()) { const long lClosingNumber = atol(strClosingNumber.Get()); this->AddRecipientClosingTransactionNo(lClosingNumber); } else { OTLog::Error("Error in OTAgreement::ProcessXMLNode: closingRecipientNumber field without value.\n"); return (-1); // error condition } nReturnVal = 1; } return nReturnVal; }