コード例 #1
0
// Loops through ALL markets, and calls pMarket->GetNym_OfferList(NYM_ID, *pOfferList) for each.
// Returns a list of all the offers that a specific Nym has on all the markets.
//
bool OTCron::GetNym_OfferList(OTASCIIArmor & ascOutput, const OTIdentifier & NYM_ID, int & nOfferCount)
{
    nOfferCount = 0; // Outputs the number of offers on this nym.
    
    // ---------------------------
    
	OTDB::OfferListNym * pOfferList  = dynamic_cast<OTDB::OfferListNym*>(OTDB::CreateObject(OTDB::STORED_OBJ_OFFER_LIST_NYM));
	OTCleanup<OTDB::OfferListNym> theListAngel(*pOfferList);
	
	// -----------------------------------------------------------
	
	FOR_EACH(mapOfMarkets, m_mapMarkets)
	{
		OTMarket * pMarket = (*it).second;
		OT_ASSERT(NULL != pMarket);
		
        int nNymOfferCount = 0;
        
		if (false == pMarket->GetNym_OfferList(NYM_ID, *pOfferList, nNymOfferCount)) // appends to *pOfferList, each iteration.
		{
				// may wish to add a log later. Anyway, keep iterationg and appending, then send back whatever we have.
		}
        else // Success!
            nOfferCount += nNymOfferCount;
	}		
コード例 #2
0
ファイル: OTCron.cpp プロジェクト: batouzo/Open-Transactions
// OTCron IS responsible for cleaning up theMarket, and takes ownership.
// So make SURE it is allocated on the HEAP before you pass it in here, and
// also make sure to delete it again if this call fails!
bool OTCron::AddMarket(OTMarket & theMarket, bool bSaveMarketFile/*=true*/)
{	
	OT_ASSERT(NULL != GetServerNym());

	theMarket.SetCronPointer(*this); // This way every Market has a pointer to Cron.
	
	OTIdentifier	MARKET_ID(theMarket);
	OTString		str_MARKET_ID(MARKET_ID);
	std::string		std_MARKET_ID = str_MARKET_ID.Get();
	
	// See if there's something else already there with the same market ID.
	mapOfMarkets::iterator ii = m_mapMarkets.find(std_MARKET_ID);
	
	// If it's not already on the list, then add it...
	if ( ii == m_mapMarkets.end() )
	{
		// If I've been instructed to save the market, and Cron did NOT successfully save the market
		//  (to its own file), then return false.  This will happen if filesystem problems.
		if (bSaveMarketFile && !theMarket.SaveMarket())
		{
			OTLog::vError("Error saving market file while adding new Market to Cron:\n%s\n",
						 std_MARKET_ID.c_str());
			return false;
		}
		
		m_mapMarkets[std_MARKET_ID] = &theMarket;
		
		bool bSuccess = true;
		
		// When Cron serializes, it stores a list of all its markets in the main cron file.
		// The actual markets themselves serialize separately to the market folder.
		//
		if (bSaveMarketFile)	// This executes only the first time that a market is added to Cron. 
			// (versus when it's just being reloaded from file and added back to the internal list.)
		{
			// Since we added a market to the Cron, we SAVE it. 
			bSuccess = SaveCron(); // If we're loading from file, and bSaveMarketFile is false, I don't want to save here. that's why it's in this block.
			
			if (bSuccess) 
				OTLog::Output(3, "New Market has been added to Cron.\n");
			else 				
				OTLog::Error("Error saving while adding new Market to Cron.\n");
		}
		
		return bSuccess; 
	}
	// Otherwise, if it was already there, log an error.
	else 
	{
		OTLog::vError("Attempt to add Market that was already there: %s\n", std_MARKET_ID.c_str());
	}
	
	return false;
}
コード例 #3
0
ファイル: OTCron.cpp プロジェクト: batouzo/Open-Transactions
void OTCron::UpdateContents()
{
	// I release this because I'm about to repopulate it.
	m_xmlUnsigned.Release();
	
	m_xmlUnsigned.Concatenate("<?xml version=\"%s\"?>\n\n", "1.0");		
	
	// -------------------------------------------------------------
	
	const OTString	SERVER_ID(m_SERVER_ID);
	
	m_xmlUnsigned.Concatenate("<cron\n version=\"%s\"\n"
							  " serverID=\"%s\""
							  " >\n\n", 
							  m_strVersion.Get(),
							  SERVER_ID.Get());	
		
	// -------------------------------------------------------------
	
	// Save the Market entries (the markets themselves are saved in a markets folder.)
	OTMarket * pMarket = NULL;
	for (mapOfMarkets::iterator ii = m_mapMarkets.begin(); ii != m_mapMarkets.end(); ++ii)
	{
		pMarket = (*ii).second;
		
		OT_ASSERT(NULL != pMarket);
		
		OTIdentifier	MARKET_ID(*pMarket);
		OTString		str_MARKET_ID(MARKET_ID);
		
		OTString		str_ASSET_ID(pMarket->GetAssetID());
		OTString		str_CURRENCY_ID(pMarket->GetCurrencyID());
		
		m_xmlUnsigned.Concatenate("<market\n marketID=\"%s\"\n"
								  " assetID=\"%s\"\n"
								  " currencyID=\"%s\"\n"
								  " marketScale=\"%ld\""
								  " >\n\n", 
								  str_MARKET_ID.Get(),
								  str_ASSET_ID.Get(),
								  str_CURRENCY_ID.Get(),
								  pMarket->GetScale());	
	}		
	
	// -------------------------------------------------------------
	
	
	// Save the Cron Items
	OTCronItem * pItem = NULL;
	for (mapOfCronItems::iterator ii = m_mapCronItems.begin(); ii != m_mapCronItems.end(); ++ii)
	{
		pItem = (*ii).second;
		
		OT_ASSERT(NULL != pItem);
		
		OTString strItem(*pItem);		// Extract the cron item contract into string form.
		OTASCIIArmor ascItem(strItem);	// Base64-encode that for storage.
		
		m_xmlUnsigned.Concatenate("<cronItem>\n%s</cronItem>\n\n", ascItem.Get());
	}		
	
	// -------------------------------------------------------------
	
	// Save the transaction numbers.
	
	long lTransactionNumber = 0;
	
	for (listOfTransactionNumbers::iterator iii = m_listTransactionNumbers.begin(); 
		 iii != m_listTransactionNumbers.end(); ++iii)
	{	
		lTransactionNumber = *iii;
		
		m_xmlUnsigned.Concatenate("<transactionNum value=\"%ld\" />\n\n", 
						   lTransactionNumber);
	} // for

	// -------------------------------------------------------------

	m_xmlUnsigned.Concatenate("</cron>\n");							
}
コード例 #4
0
ファイル: OTCron.cpp プロジェクト: batouzo/Open-Transactions
// return -1 if error, 0 if nothing, and 1 if the node was processed.
int OTCron::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
{
	OT_ASSERT(NULL != GetServerNym());
	
	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 (nReturnVal = OTContract::ProcessXMLNode(xml))
	//	return nReturnVal;
	
	
	if (!strcmp("cron", xml->getNodeName())) 
	{		
		m_strVersion		= xml->getAttributeValue("version");
		
		// ---------------------
		
		const OTString	strServerID(xml->getAttributeValue("serverID"));
		
		m_SERVER_ID.SetString(strServerID);
		
		// ---------------------
		
		OTLog::vOutput(0, "\n\nLoading an OTCron object. ServerID:\n%s\n", 
					   strServerID.Get());
				
		nReturnVal = 1;
	}
	else if (!strcmp("transactionNum", xml->getNodeName()))
	{
		long lTransactionNum = 0;
		
		lTransactionNum	= atol(xml->getAttributeValue("value"));
		
		OTLog::vOutput(1, "Transaction Number %ld available for Cron.\n",
					   lTransactionNum);
		
		AddTransactionNumber(lTransactionNum); // This doesn't save to disk. Make sure to save Cron when it changes.

		nReturnVal = 1;
	}	
	
	else if (!strcmp("cronItem", xml->getNodeName())) 
	{		
		OTString strData;
		
		if (!LoadEncodedTextField(xml, strData) || !strData.Exists())
		{
			OTLog::Error("Error in OTCron::ProcessXMLNode: cronItem field without value.\n");
			return (-1); // error condition
		}
		else 
		{
			OTCronItem * pItem = OTCronItem::NewCronItem(strData);
			
			if (NULL == pItem)
			{
				OTLog::Error("Unable to create cron item from data in cron file.\n");
				return (-1);
			}
			
			if (AddCronItem(*pItem, false))	// bSaveReceipt=false. The receipt is only saved once: When item FIRST added to cron.
			{								// But here, the item was ALREADY in cron, and is merely being loaded from disk. Thus,
				// it would be wrong to try to create the "original record" as if it were brand new
				// and still had the user's signature on it. (Once added to Cron, the signatures are 
				// released and the SERVER signs it from there. That's why the user's version is saved
				// as a receipt in the first place -- so we have a record of the user's authorization.)
				OTLog::Output(2, "Successfully loaded cron item and added to list.\n");
			}
			else 
			{
				OTLog::Error("Though loaded successfully, unable to add cron item (from cron file) to cron list.\n");
				delete pItem;
				pItem = NULL;
				return (-1);
			}
		}
		
		nReturnVal = 1;
	}
	
	else if (!strcmp("market", xml->getNodeName()))
	{
		const OTString	strMarketID(xml->getAttributeValue("marketID"));
		const OTString	strAssetID(xml->getAttributeValue("assetID"));
		const OTString	strCurrencyID(xml->getAttributeValue("currencyID"));
		
		const long		lScale = atol(xml->getAttributeValue("marketScale"));
		
		const OTIdentifier	ASSET_ID(strAssetID), CURRENCY_ID(strCurrencyID);
		
		OTLog::vOutput(1, "Loaded cron entry for Market:\n%s.\n", strMarketID.Get());
		
		// LoadMarket() needs this info to do its thing.
		OTMarket * pMarket = new OTMarket(m_SERVER_ID, ASSET_ID, CURRENCY_ID, lScale);
		
		OT_ASSERT(NULL != pMarket);
		
		pMarket->SetCronPointer(*this); // This way every Market has a pointer to Cron.

		//	AddMarket normally saves to file, but we don't want that when we're LOADING from file, now do we?
		if (!pMarket->LoadMarket() || !pMarket->VerifySignature(*GetServerNym()) ||
			!AddMarket(*pMarket, false)) // bSaveFile=false: don't save this file WHILE loading it!!! 
		{
			OTLog::Error("Somehow error while loading, verifying, or adding market while loading Cron file.\n");
			delete pMarket; pMarket = NULL;
			return (-1);
		}
		else 
		{
			OTLog::Output(1, "Loaded market entry from cronfile, and also loaded the market file itself.\n");
		}
		nReturnVal = 1;
	}
	
	return nReturnVal;	
}
コード例 #5
0
ファイル: OTCron.cpp プロジェクト: batouzo/Open-Transactions
bool OTCron::GetMarketList (OTASCIIArmor & ascOutput, int & nMarketCount)
{
    nMarketCount        = 0; // This parameter is set to zero here, and incremented in the loop below.
    
    // ------------------------
	OTMarket * pMarket  = NULL;

	OTDB::MarketList * pMarketList  = dynamic_cast<OTDB::MarketList*>(OTDB::CreateObject(OTDB::STORED_OBJ_MARKET_LIST));
	OTCleanup<OTDB::MarketList> theListAngel(*pMarketList);

	// -----------------------------------------------------------
	    
	for (mapOfMarkets::iterator ii = m_mapMarkets.begin(); ii != m_mapMarkets.end(); ++ii)
	{
		pMarket = (*ii).second;
		
		OT_ASSERT(NULL != pMarket);
		
		OTDB::MarketData * pMarketData  = dynamic_cast<OTDB::MarketData *>(OTDB::CreateObject(OTDB::STORED_OBJ_MARKET_DATA));
		OTCleanup<OTDB::MarketData> theDataAngel(*pMarketData);
		
		// --------------------------------------------
		const OTIdentifier	MARKET_ID(*pMarket);
		const OTString		str_MARKET_ID(MARKET_ID);
		const OTString		str_ServerID(pMarket->GetServerID());
		const OTString		str_ASSET_ID(pMarket->GetAssetID());
		const OTString		str_CURRENCY_ID(pMarket->GetCurrencyID());
		
		pMarketData->server_id			= str_ServerID.Get();
		pMarketData->market_id			= str_MARKET_ID.Get();
		pMarketData->asset_type_id		= str_ASSET_ID.Get();
		pMarketData->currency_type_id	= str_CURRENCY_ID.Get();
		// --------------------------------------------		
		const long & lScale	= pMarket->GetScale();
		
		pMarketData->scale				= to_string<long>(lScale);
		
		// --------------------------------------------
		
		const uint64_t theCurrentBid	= pMarket->GetHighestBidPrice();
		const uint64_t theCurrentAsk	= pMarket->GetLowestAskPrice();
		
		pMarketData->current_bid		= to_string<uint64_t>(theCurrentBid);
		pMarketData->current_ask		= to_string<uint64_t>(theCurrentAsk);
		
		// ---------------------------------------------
		
		const long &	lLastSalePrice			= pMarket->GetLastSalePrice();
		const long &	lTotalAvailableAssets	= pMarket->GetTotalAvailableAssets();
		
		pMarketData->total_assets		= to_string<long>(lTotalAvailableAssets);
		pMarketData->last_sale_price	= to_string<long>(lLastSalePrice);

		// ---------------------------------------------
		
		const mapOfOffers::size_type theBidCount = pMarket->GetBidCount();
		const mapOfOffers::size_type theAskCount = pMarket->GetAskCount();
		
		pMarketData->number_bids		= to_string<mapOfOffers::size_type>(theBidCount);
		pMarketData->number_asks		= to_string<mapOfOffers::size_type>(theAskCount);

		// ---------------------------------------------
		// In the past 24 hours.
		// (I'm not collecting this data yet, (maybe never), so these values aren't set at all.)
		//
//		pMarketData->volume_trades		= ???;
//		pMarketData->volume_assets		= ???;
//		pMarketData->volume_currency	= ???;
//		
//		pMarketData->recent_highest_bid	= ???;
//		pMarketData->recent_lowest_ask	= ???;
		// ---------------------------------------------

		// *pMarketData is CLONED at this time (I'm still responsible to delete.)
		// That's also why I add it here, below: So the data is set right before the cloning occurs.
		//
		pMarketList->AddMarketData(*pMarketData);
        nMarketCount++;
	}		
	
	// -------------------------------------------------------------
	
	// Now pack the list into strOutput...
    if (nMarketCount == 0)
        return true; // Success, but the list contains 0 markets.
    
	else if (nMarketCount > 0)
    {
        OTDB::Storage * pStorage = OTDB::GetDefaultStorage();
        OT_ASSERT(NULL != pStorage);
        
        OTDB::OTPacker * pPacker = pStorage->GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either.
            
        // -----------------------------
        
        OTDB::PackedBuffer * pBuffer = pPacker->Pack(*pMarketList); // Now we PACK our market list.
        
        if (NULL == pBuffer)
        {
            OTLog::Error("Failed packing pMarketList in OTCron::GetMarketList. \n");
            return false;
        }
        
        OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure memory is cleaned up.
        
        // --------------------------------------------------------	
        
        // Now we need to translate pBuffer into strOutput.
        
        const uint8_t* pUint = static_cast<const uint8_t*>(pBuffer->GetData());
        const size_t theSize = pBuffer->GetSize();
        
        if ((theSize > 0) && (NULL != pUint))
        {
            OTData theData(pUint, theSize);

            // This function will base64 ENCODE theData,
            // and then Set() that as the string contents.
            ascOutput.SetData(theData);
//            bool bSuccessSetData = false;
//            bSuccessSetData = ascOutput.SetData(theData);

            return true;
        }
        else 
            OTLog::Error("OTCron::GetMarketList: 0 size, or null return value, while getting raw data from packed buffer.\n");
	}
    
    else
        OTLog::vError("OTCron::GetMarketList: nMarketCount is less than zero: %d.\n", nMarketCount);      
        
	return false;
}
コード例 #6
0
ファイル: OTCron.cpp プロジェクト: batouzo/Open-Transactions
// Loops through ALL markets, and calls pMarket->GetNym_OfferList(NYM_ID, *pOfferList) for each.
// Returns a list of all the offers that a specific Nym has on all the markets.
//
bool OTCron::GetNym_OfferList(OTASCIIArmor & ascOutput, const OTIdentifier & NYM_ID, int & nOfferCount)
{
    nOfferCount = 0; // Outputs the number of offers on this nym.
    
    // ---------------------------
    
	OTDB::OfferListNym * pOfferList  = dynamic_cast<OTDB::OfferListNym*>(OTDB::CreateObject(OTDB::STORED_OBJ_OFFER_LIST_NYM));
	OTCleanup<OTDB::OfferListNym> theListAngel(*pOfferList);
	
	// -----------------------------------------------------------
	
	for (mapOfMarkets::iterator ii = m_mapMarkets.begin(); ii != m_mapMarkets.end(); ++ii)
	{
		OTMarket * pMarket = (*ii).second;
		
		OT_ASSERT(NULL != pMarket);
		
        int nNymOfferCount = 0;
        
		if (false == pMarket->GetNym_OfferList(NYM_ID, *pOfferList, nNymOfferCount)) // appends to *pOfferList, each iteration.
		{
				// may wish to add a log later. Anyway, keep iterationg and appending, then send back whatever we have.
		}
        else // Success!
            nOfferCount += nNymOfferCount;
	}		
	
	// -------------------------------------------------------------
	
	// Now pack the list into strOutput...
    if (nOfferCount == 0)
        return true; // Success, but 0 offers being returned. (List is empty.)
    
    else if (nOfferCount > 0)
    {
        OTDB::Storage * pStorage = OTDB::GetDefaultStorage();
        OT_ASSERT(NULL != pStorage);
        
        OTDB::OTPacker * pPacker = pStorage->GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either.
        
        // -----------------------------
        
        OTDB::PackedBuffer * pBuffer = pPacker->Pack(*pOfferList); // Now we PACK our nym's offer list.
        
        if (NULL == pBuffer)
        {
            OTLog::Error("Failed packing pOfferList in OTCron::GetNym_OfferList. \n");
            return false;
        }
        
        OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure memory is cleaned up.
        
        // --------------------------------------------------------	
        
        // Now we need to translate pBuffer into strOutput.
        
        const uint8_t* pUint = static_cast<const uint8_t*>(pBuffer->GetData());
        const size_t theSize = pBuffer->GetSize();
        
        if ((NULL != pUint) || (theSize < 2))
        {
            OTData theData(pUint, theSize);
            
            // This function will base64 ENCODE theData,
            // and then Set() that as the string contents.
            ascOutput.SetData(theData);
            
            return true;
        }
        else 
            OTLog::Error("Null returned, or bad size, while getting buffer data in OTCron::GetNym_OfferList.\n");
	}
    
    else
        OTLog::vError("Error: Less-than-zero nOfferCount in OTCron::GetNym_OfferList: %d.\n", nOfferCount); 
    
	return false;	
}
コード例 #7
0
ファイル: OTTrade.cpp プロジェクト: StandardLaw/opentxs
// Cron only removes an item when that item REQUESTS to be removed (by setting
// the flag.)
// Once this happens, Cron has full permission to remove it. Thus, this hook is
// forceful. It
// is cron saying, YOU ARE BEING REMOVED. Period. So cleanup whatever you have
// to clean up.
//
// In this case, it removes the corresponding offer from the market.
//
void OTTrade::onRemovalFromCron()
{
    OTCron* cron = GetCron();

    OT_ASSERT(cron != nullptr);

    // If I don't already have an offer on the market, then I will have trouble
    // figuring out
    // my SCALE, which is stored on the Offer. Therefore I will instantiate an
    // offer (since I
    // store the original internally) and I will look up the scale.
    //

    int64_t scale = 1; // todo stop hardcoding.
    int64_t transactionNum = 0;

    if (offer_ != nullptr) {
        if (!marketOffer_.Exists()) {
            otErr
                << "OTTrade::onRemovalFromCron called with nullptr offer_ and "
                   "empty marketOffer_.\n";
            return;
        }

        std::unique_ptr<OTOffer> offer(new OTOffer());

        // Trying to load the offer from the trader's original signed request
        // (So I can use it to lookup the Market ID, so I can see if the offer
        // is
        // already there on the market.)
        if (!offer->LoadContractFromString(marketOffer_)) {
            otErr << "Error loading offer from string in "
                     "OTTrade::onRemovalFromCron\n";
            return;
        }

        scale = offer->GetScale();
        transactionNum = offer->GetTransactionNum();
    }
    else {
        scale = offer_->GetScale();
        transactionNum = offer_->GetTransactionNum();
    }

    OTMarket* market = cron->GetOrCreateMarket(GetInstrumentDefinitionID(),
                                               GetCurrencyID(), scale);

    // Couldn't find (or create) the market.
    //
    if (market == nullptr) {
        otErr << "Unable to find market within requested parameters in "
                 "OTTrade::onRemovalFromCron.\n";
        return;
    }

    //
    // Let's see if the offer is ALREADY allocated and on this market!
    //
    OTOffer* marketOffer = market->GetOffer(transactionNum);

    // The Offer is already on the Market.
    //
    if (marketOffer != nullptr) {
        offer_ = marketOffer;

        offer_->SetTrade(*this);
    }

    market->RemoveOffer(transactionNum);
}
コード例 #8
0
ファイル: OTTrade.cpp プロジェクト: StandardLaw/opentxs
// Assuming the offer is ON the market, this will get the pointer to that offer.
// Otherwise it will try to add it to the market.
// Otherwise it will fail. (Perhaps it's a stop order, and not ready to activate
// yet.)
//
OTOffer* OTTrade::GetOffer(Identifier* offerMarketId, OTMarket** market)
{
    OT_ASSERT(GetCron() != nullptr);

    // See if the offer has already been instantiated onto a market...
    if (offer_ != nullptr) {
        offer_->SetTrade(*this); // Probably don't need this line. I'll remove
                                 // it someday while optimizing.
        // In fact since it should already be set, having this here would
        // basically
        // hide it from me if the memory was ever walked on from a bug
        // somewhere.

        // It loaded. Let's get the Market ID off of it so we can locate the
        // market.
        const Identifier OFFER_MARKET_ID(*offer_);

        if (market != nullptr) {
            OTMarket* pMarket = GetCron()->GetMarket(OFFER_MARKET_ID);

            // Sometimes the caller function would like a copy of this market
            // pointer, when available.
            // So I pass it back to him here, if he wants. That way he doesn't
            // have to do this work again
            // to look it up.
            if (pMarket != nullptr)
                *market = pMarket; // <=================
            else
                otErr << "OTTrade::" << __FUNCTION__
                      << ": offer_ already exists, yet unable to find the "
                         "market it's supposed to be on.\n";
        }

        if (offerMarketId != nullptr) {
            // Sometimes the caller function would like a copy of this ID. So I
            // give the option to pass in a pointer so I can give it here.
            offerMarketId->Assign(OFFER_MARKET_ID);
        }

        return offer_;
    } // if offer_ ALREADY EXISTS.

    // else (BELOW) offer_ IS nullptr, and thus it didn't exist yet...

    if (!marketOffer_.Exists()) {
        otErr << "OTTrade::GetOffer called with empty marketOffer_.\n";
        return nullptr;
    }

    OTOffer* offer = new OTOffer();
    OT_ASSERT(offer != nullptr);

    // Trying to load the offer from the trader's original signed request
    // (So I can use it to lookup the Market ID, so I can see the offer is
    // already there on the market.)
    if (!offer->LoadContractFromString(marketOffer_)) {
        otErr << "Error loading offer from string in OTTrade::GetOffer\n";
        delete offer;
        offer = nullptr;
        return nullptr;
    }

    // No need to do any additional security verification here on the Offer,
    // since the Offer is already heavily verified in
    // OTServer::NotarizeMarketOffer().
    // So as long as you feel safe about the Trade, then you can feel safe about
    // the Offer already, with no further checks.
    // *Also remember we saved a copy of the original in the cron folder.

    // It loaded. Let's get the Market ID off of it so we can locate the market.
    Identifier OFFER_MARKET_ID(*offer);

    if (offerMarketId != nullptr) {
        // Sometimes the caller function would like a copy of this ID. So I
        // give the option to pass in a pointer so I can give it here.
        offerMarketId->Assign(OFFER_MARKET_ID);
    }

    // Previously if a user tried to use a market that didn't exist, I'd just
    // return failure.
    // But now we will create any market that doesn't already exist.
    // (Remember, the server operator could just erase the market folder--it
    // wouldn't
    // affect anyone's balances!) Update: he probably couldn't just wipe the
    // markets folder,
    // actually, without making it impossible for certain Nyms to get rid of
    // certain issued #s.
    //
    //    OTMarket * pMarket = m_cron->GetMarket(OFFER_MARKET_ID);
    OTMarket* pMarket = GetCron()->GetOrCreateMarket(
        GetInstrumentDefinitionID(), GetCurrencyID(), offer->GetScale());

    // Couldn't find (or create) the market.
    if (pMarket == nullptr) {
        otOut
            << "OTTrade::" << __FUNCTION__
            << ": Unable to find or create market within requested parameters.";
        delete offer;
        offer = nullptr;
        return nullptr;
    }

    // If the caller passed in the address of a market pointer (optional)
    if (market != nullptr) {
        // Sometimes the caller function would like a copy of this market
        // pointer, when available.
        // So I pass it back to him here, if he wants. That way he doesn't have
        // to do this work again
        // to look it up.
        *market = pMarket;
    }

    // At this point, I have heap-allocated the offer, used it to get the Market
    // ID, and successfully
    // used that to get a pointer to the market matching that ID.
    //
    // Let's see if the offer is ALREADY allocated and on this market!
    // If so, delete the one I just allocated. If not, add it to the market.
    OTOffer* marketOffer = pMarket->GetOffer(offer->GetTransactionNum());

    // The Offer is already on the Market.
    // NOTE: It may just start out this way, without ever being added.
    // How is that possible? Because maybe it was in the market file when we
    // first loaded up,
    // and had been added on some previous run of the software. So since we
    // started running,
    // the pMarket->AddOffer() code below has literally never run for that
    // offer. Instead we
    // first find it here, and thus return the pointer before getting any
    // farther.
    //
    // IN ALL CASES, we make sure to call offer_->SetTrade() so that it has a
    // pointer BACK to
    // this Trade object! (When actually processing the offer, the market will
    // need the account
    // numbers and Nym IDs... which are stored here on the trade.)
    if (marketOffer != nullptr) {
        offer_ = marketOffer;

        // Since the Offer already exists on the market, no need anymore for the
        // one we allocated above (to get the market ID.) So we delete it now.
        delete offer;
        offer = nullptr;

        offer_->SetTrade(*this);

        return offer_;
    }

    // Okay so the offer ISN'T already on the market. If it's not a stop order,
    // let's ADD the one we
    // allocated to the market now! (Stop orders are activated through their own
    // logic, which is below
    // this, in the else block.)
    //
    if (!IsStopOrder()) {
        if (hasTradeActivated_) {
            // Error -- how has the trade already activated, yet not on the
            // market and null in my pointer?
            otErr << "How has the trade already activated, yet not on the "
                     "market and null in my pointer?\n";
        }
        else if (!pMarket->AddOffer(this, *offer, true)) // Since we're
                                                           // actually adding
                                                           // an offer to the
                                                           // market (not just
        { // loading from disk) the we actually want to save the market.
            // bSaveFile=true.
            // Error adding the offer to the market!
            otErr << "Error adding the offer to the market! (Even though "
                     "supposedly the right market.)\n";
        }
        else {
            // SUCCESS!
            offer_ = offer;

            hasTradeActivated_ = true;

            // The Trade (stored on Cron) has a copy of the Original Offer, with
            // the User's signature on it.
            // A copy of that original Trade object (itself with the user's
            // signature) is already stored in
            // the cron folder (by transaction number.) This happens when the
            // Trade is FIRST added to cron,
            // so it's already safe before we even get here.
            //
            // So thus I am FREE to release the signatures on the offer, and
            // sign with the server instead.
            // The server-signed offer will be stored by the OTMarket.
            offer_->ReleaseSignatures();
            offer_->SignContract(*(GetCron()->GetServerNym()));
            offer_->SaveContract();

            pMarket->SaveMarket();

            // Now when the market loads next time, it can verify this offer
            // using the server's signature,
            // instead of having to load the user. Because the server has
            // verified it and added it, and now
            // signs it, vouching for it.

            // The Trade itself (all its other variables) are now allowed to
            // change, since its signatures
            // are also released and it is now server-signed. (With a copy
            // stored of the original.)

            offer_->SetTrade(*this);

            return offer_;
        }
    }

    // It's a stop order, and not activated yet.
    // Should we activate it now?
    //
    else if (IsStopOrder() && !stopActivated_) {
        int64_t relevantPrice = 0;

        // If the stop order is trying to sell something, then it cares about
        // the highest bidder.
        if (offer->IsAsk())
            relevantPrice = pMarket->GetHighestBidPrice();
        else // But if the stop order is trying to buy something, then it cares
             // about the lowest ask price.
            relevantPrice = pMarket->GetLowestAskPrice();

        // It's a stop order that hasn't activated yet. SHOULD IT ACTIVATE NOW?
        if ((IsGreaterThan() && (relevantPrice > GetStopPrice())) ||
            (IsLessThan() && (relevantPrice < GetStopPrice()))) {
            // Activate the stop order!
            if (!pMarket->AddOffer(this, *offer, true)) // Since we're actually
                                                        // adding an offer to
                                                        // the market (not just
            { // loading from disk) the we actually want to save the market.
                // Error adding the offer to the market!    // bSaveFile=true.
                otErr << "Error adding the stop order to the market! (Even "
                         "though supposedly the right market.)\n";
            }
            else {
                // SUCCESS!
                offer_ = offer;

                stopActivated_ = true;
                hasTradeActivated_ = true;

                // The Trade (stored on Cron) has a copy of the Original Offer,
                // with the User's signature on it.
                // A copy of that original Trade object (itself with the user's
                // signature) is already stored in
                // the cron folder (by transaction number.) This happens when
                // the Trade is FIRST added to cron,
                // so it's already safe before we even get here.
                //
                // So thus I am FREE to release the signatures on the offer, and
                // sign with the server instead.
                // The server-signed offer will be stored by the OTMarket.
                offer_->ReleaseSignatures();
                offer_->SignContract(*(GetCron()->GetServerNym()));
                offer_->SaveContract();

                pMarket->SaveMarket();

                // Now when the market loads next time, it can verify this offer
                // using the server's signature,
                // instead of having to load the user. Because the server has
                // verified it and added it, and now
                // signs it, vouching for it.

                // The Trade itself (all its other variables) are now allowed to
                // change, since its signatures
                // are also released and it is now server-signed. (With a copy
                // stored of the original.)

                offer_->SetTrade(*this);

                return offer_;
            }
        }
    }

    delete offer;
    offer = nullptr;

    return nullptr;
}
コード例 #9
0
ファイル: OTTrade.cpp プロジェクト: StandardLaw/opentxs
// OTCron calls this regularly, which is my chance to expire, etc.
// Return True if I should stay on the Cron list for more processing.
// Return False if I should be removed and deleted.
bool OTTrade::ProcessCron()
{
    // Right now Cron is called 10 times per second.
    // I'm going to slow down all trades so they are once every
    // GetProcessInterval()
    if (GetLastProcessDate() > OT_TIME_ZERO) {
        // (Default ProcessInterval is 1 second, but Trades will use 10 seconds,
        // and Payment Plans will use an hour or day.)
        if (OTTimeGetTimeInterval(OTTimeGetCurrentTime(),
                                  GetLastProcessDate()) <= GetProcessInterval())
            return true;
    }
    
    // Keep a record of the last time this was processed.
    // (NOT saved to storage, only used while the software is running.)
    // (Thus no need to release signatures, sign contract, save contract, etc.)
    SetLastProcessDate(OTTimeGetCurrentTime());

    // PAST END DATE?
    // First call the parent's version (which this overrides) so it has
    // a chance to check its stuff. Currently it checks IsExpired().
    if (!ot_super::ProcessCron())
        return false; // It's expired or flagged for removal--remove it from
                      // Cron.

    // You might ask, why not check here if this trade is flagged for removal?
    // Supposedly the answer is, because it's only below that I have the market
    // pointer,
    // and am able to remove the corresponding trade from the market.
    // Therefore I am adding a hook for "onRemoval" so that Objects such as
    // OTTrade ALWAYS
    // have the opportunity to perform such cleanup, without having to juggle
    // such logic.

    // REACHED START DATE?
    // Okay, so it's not expired. But might not have reached START DATE yet...
    if (!VerifyCurrentDate())
        return true; // The Trade is not yet valid, so we return. BUT, we return
                     //  true, so it will stay on Cron until it BECOMES valid.

    // TRADE-specific stuff below.

    bool bStayOnMarket =
        true; // by default stay on the market (until some rule expires me.)

    Identifier OFFER_MARKET_ID;
    OTMarket* market = nullptr;

    // If the Offer is already active on a market, then I already have a pointer
    // to
    // it. This function returns that pointer. If nullptr, it tries to find the
    // offer on
    // the market and then sets the pointer and returns. If it can't find it, IT
    // TRIES
    // TO ADD IT TO THE MARKET and sets the pointer and returns it.
    OTOffer* offer = GetOffer(
        &OFFER_MARKET_ID, &market); // Both of these parameters are optional.

    // In this case, the offer is NOT on the market.
    // Perhaps it wasn't ready to activate yet.
    if (offer == nullptr) {
        
        // The offer SHOULD HAVE been on the market, since we're within the
        // valid range,
        // and GetOffer adds it when it's not already there.

        //        otErr << "OTTrade::ProcessCron: Offer SHOULD have been on
        // Market. I might ASSERT this.\n"; // comment this out

        // Actually! If it's a Stop Order, then it WOULD be within the valid
        // range, yet would
        // not yet have activated. So I don't want to log some big error every
        // time a stop order
        // checks its prices.
    }
    else if (market == nullptr) {
        
        // todo. (This will already leave a log above in GetOffer somewhere.)
        //        otErr << "OTTrade::ProcessCron: Market was nullptr.\n"; //
        // comment this out
    }
    else // If a valid pointer was returned, that means the offer is on the
           // market.
    {
        // Make sure it hasn't already been flagged by someone else...
        if (IsFlaggedForRemoval()) // This is checked above in
                                   // OTCronItem::ProcessCron().
            bStayOnMarket = false; // I'm leaving the check here in case the
                                   // flag was set since then.

        else // Process it!  <===================
        {
            otInfo << "Processing trade: " << GetTransactionNum() << ".\n";

            bStayOnMarket = market->ProcessTrade(*this, *offer);
            // No need to save the Trade or Offer, since they will
            // be saved inside this call if they are changed.
        }
    }

    // Return True if I should stay on the Cron list for more processing.
    // Return False if I should be removed and deleted.
    return bStayOnMarket; // defaults true, so if false, that means someone is
                          // removing it for a reason.
}
コード例 #10
0
ファイル: OTTrade.cpp プロジェクト: germc/Open-Transactions
// OTCron calls this regularly, which is my chance to expire, etc.
// Return True if I should stay on the Cron list for more processing.
// Return False if I should be removed and deleted.
bool OTTrade::ProcessCron()
{	
	// -----------------------------------------------------------------
	// Right now Cron is called 10 times per second.
	// I'm going to slow down all trades so they are once every GetProcessInterval()
	if (GetLastProcessDate() > 0)
	{
		// (Default ProcessInternal is 1 second, but Trades will use 10 seconds,
		// and Payment Plans will use an hour or day.)
		if ((GetCurrentTime() - GetLastProcessDate()) <= GetProcessInterval())
			return true;
	}
	// Keep a record of the last time this was processed.
	// (NOT saved to storage, only used while the software is running.)
	// (Thus no need to release signatures, sign contract, save contract, etc.)
	SetLastProcessDate(GetCurrentTime());
	// -----------------------------------------------------------------

	
	// PAST END DATE? --------------------------------
	// First call the parent's version (which this overrides) so it has
	// a chance to check its stuff. Currently it checks IsExpired().
	if (!OTCronItem::ProcessCron())
		return false;	// It's expired--remove it from Cron.

	
	// REACHED START DATE? --------------------------------
	// Okay, so it's not expired. But might not have reached START DATE yet...
	if (!VerifyCurrentDate())
		return true;	// The Trade is not yet valid, so we return. BUT, we return 
						//  true, so it will stay on Cron until it BECOMES valid.
	
	
	
	// TRADE-specific stuff below. --------------------------------
	
	bool bStayOnMarket = true; // by default stay on the market (until some rule expires me.)
	
	OTIdentifier OFFER_MARKET_ID;
	OTMarket * pMarket = NULL;
	
	// If the Offer is already active on a market, then I already have a pointer to
	// it. This function returns that pointer. If NULL, it tries to find the offer on
	// the market and then sets the pointer and returns. If it can't find it, IT TRIES
	// TO ADD IT TO THE MARKET and sets the pointer and returns it.
	OTOffer * pOffer = GetOffer(&OFFER_MARKET_ID, &pMarket); // Both of these parameters are optional.

	
	// In this case, the offer is NOT on the market. 
	// Perhaps it wasn't ready to activate yet.
	if (NULL == pOffer)
	{
		// The offer SHOULD HAVE been on the market, since we're within the valid range,
		// and GetOffer adds it when it's not already there.
//		OTLog::Error("OTTrade::ProcessCron: Offer SHOULD have been on Market. I might ASSERT this.\n");
		
		// Actually! If it's a Stop Order, then it WOULD be within the valid range, yet would
		// not yet have activated. So I don't want to log some big error every time a stop order
		// checks its prices.
	}	
	else if (NULL == pMarket)
	{
		//todo. (This will already leave a log above in GetOffer somewhere.)
	}	
	else  // If a valid pointer was returned, that means the offer is on the market.
	{
		// Make sure it hasn't already been flagged by someone else...
		if (this->IsFlaggedForRemoval())
			bStayOnMarket = false;
		else
		{ // Process it!  <===================
			bStayOnMarket = pMarket->ProcessTrade(*this, *pOffer);
			// No need to save the Trade or Offer, since they will
			// be saved inside this call if they are changed.
		}			
	}
	
	// The offer needs to be removed from the market.
	// (Which means this trade also needs to be removed from Cron.
	// I assume calling function will do that.)
	if (!bStayOnMarket)
	{
		pMarket->RemoveOffer(GetTransactionNum());
	}

	// Return True if I should stay on the Cron list for more processing.
	// Return False if I should be removed and deleted.
	return bStayOnMarket; // defaults true, so if false, that means someone is removing it for a reason.
}
コード例 #11
0
ファイル: OTTrade.cpp プロジェクト: germc/Open-Transactions
// Assuming the offer is ON the market, this will get the pointer to that offer.
// Otherwise it will try to add it to the market.
OTOffer	* OTTrade::GetOffer(OTIdentifier * pOFFER_MARKET_ID/*=NULL*/, OTMarket ** ppMarket/*=NULL*/)
{
	OT_ASSERT(NULL != GetCron());
			  
	// See if the offer has already been instantiated.
	if (NULL != m_pOffer)
	{
		m_pOffer->SetTrade(*this);	// Probably don't need this one. I'll remove it someday while optimizing.
		return m_pOffer;			// In fact since it should already be set, having this here would basically
									// hide it from me if the memory was ever walked on from a bug somewhere.
	}
	
	if (!m_strOffer.Exists())
	{
		OTLog::Error("OTTrade::GetOffer called with empty m_strOffer.\n");
		return NULL;
	}
	
	OTOffer * pOffer = new OTOffer();
	
	OT_ASSERT(NULL != pOffer);

	// --------------------------------------------------
	
	// Trying to load the offer from the trader's original signed request
	// (So I can use it to lookup the Market ID, so I can see the offer is
	// already there on the market.)
	if (!pOffer->LoadContractFromString(m_strOffer))
	{
		OTLog::Error("Error loading offer from string in OTTrade::GetOffer\n");
		delete pOffer; pOffer = NULL;
		return NULL;
	}
	
	// No need to do any additional security verification here on the Offer,
	// since the Offer is already heavily verified in OTServer::NotarizeMarketOffer().
	// So as long as you feel safe about the Trade, then you can feel safe about
	// the Offer already, with no further checks.
	// *Also remember we saved a copy of the original in the cron folder.
	
	// It loaded. Let's get the Market ID off of it so we can locate the market.
	OTIdentifier OFFER_MARKET_ID(*pOffer);
	
	if (NULL != pOFFER_MARKET_ID)
	{
		// Sometimes the caller function would like a copy of this ID. So I 
		// give the option to pass in a pointer so I can give it here.
		pOFFER_MARKET_ID->Assign(OFFER_MARKET_ID);
	}
	
	
	// Previously if a user tried to use a market that didn't exist, I'd just return failure.
	// But now we will create any market that doesn't already exist.
	// (Remember, the server operator could just erase the market folder--it wouldn't 
	// affect anyone's balances!)
	//
//	OTMarket * pMarket = m_pCron->GetMarket(OFFER_MARKET_ID);
	OTMarket * pMarket = GetCron()->GetOrCreateMarket(GetAssetID(), GetCurrencyID(), pOffer->GetScale()); 

	
	// Couldn't find (or create) the market.
	if (NULL == pMarket)
	{
		OTLog::Output(3, "Unable to find or create market within requested parameters in OTTrade::GetOffer.");
		delete pOffer; pOffer = NULL;
		return NULL;
	}
	
	// If the caller passed in the address of a market pointer (optional)
	if (NULL != ppMarket)
	{
		// Sometimes the caller function would like a copy of this market pointer, when available.
		// So I pass it back to him here, if he wants. That way he doesn't have to do this work again
		// to look it up.
		*ppMarket = pMarket;
	}
	
	// --------------------------------------------------
	
	// At this point, I have heap-allocated the offer, used it to get the Market ID, and successfully
	// used that to get a pointer to the market matching that ID.
	//
	// Let's see if the offer is ALREADY allocated and on this market! 
	// If so, delete the one I just allocated. If not, add it to the market.
	OTOffer * pMarketOffer = pMarket->GetOffer(pOffer->GetTransactionNum());
	
	// The Offer is already on the Market.
	// NOTE: It may just start out this way, without ever being added.
	// How is that possible? Because maybe it was in the market file when we first loaded up,
	// and had been added on some previous run of the software. So since we started running,
	// the pMarket->AddOffer() code below has literally never run for that offer. Instead we
	// first find it here, and thus return the pointer before getting any farther.
	//
	// IN ALL CASES, we make sure to call m_pOffer->SetTrade() so that it has a pointer BACK to
	// this Trade object! (When actually processing the offer, the market will need the account
	// numbers and Nym IDs... which are stored here on the trade.)
	if (NULL != pMarketOffer)
	{
		m_pOffer = pMarketOffer;
		
		// Since the Offer already exists on the market, no need anymore for the
		// one we allocated above (to get the market ID.) So we delete it now.
		delete pOffer;
		pOffer = NULL;
		
		m_pOffer->SetTrade(*this);
		
		return m_pOffer;
	}
	
	// Okay so the offer ISN'T already on the market. If it's not a stop order, let's ADD the one we
	// allocated to the market now! (Stop orders are activated through their own logic, which is in the else.)
	if (!IsStopOrder())
	{
		if (m_bHasTradeActivated)
		{
			// Error -- how has the trade already activated, yet not on the market and null in my pointer?
			OTLog::Error("How has the trade already activated, yet not on the market and null in my pointer?\n");			
		}
		else if (!pMarket->AddOffer(*pOffer, true))	// Since we're actually adding an offer to the market (not just
		{											// loading from disk) the we actually want to save the market. bSaveFile=true.
			
			// Error adding the offer to the market!
			OTLog::Error("Error adding the offer to the market! (Even though supposedly the right market.)\n");
		}
		else 
		{
			// SUCCESS!
			m_pOffer = pOffer;
			
			m_bHasTradeActivated = true;
			
			// The Trade (stored on Cron) has a copy of the Original Offer, with the User's signature on it.
			// A copy of that original Trade object (itself with the user's signature) is already stored in
			// the cron folder (by transaction number.) This happens when the Trade is FIRST added to cron,
			// so it's already safe before we even get here.
			//
			// So thus I am FREE to release the signatures on the offer, and sign with the server instead.
			// The server-signed offer will be stored by the OTMarket.
			m_pOffer->ReleaseSignatures();
			m_pOffer->SignContract(*(GetCron()->GetServerNym()));
			m_pOffer->SaveContract();
			
			pMarket->SaveMarket();
			
			// Now when the market loads next time, it can verify this offer using the server's signature,
			// instead of having to load the user. Because the server has verified it and added it, and now
			// signs it, vouching for it.
			
			
			// The Trade itself (all its other variables) are now allowed to change, since its signatures
			// are also released and it is now server-signed. (With a copy stored of the original.)

			m_pOffer->SetTrade(*this);

			return m_pOffer;
		}
	}
	else if(IsStopOrder() && !m_bHasStopActivated) // It's a stop order. Should we activate it now?
	{
		long lRelevantPrice = 0;
		
		// If the stop order is trying to sell something, then it cares about the highest bidder.
		if (pOffer->IsAsk()) 
			lRelevantPrice = pMarket->GetHighestBidPrice();
		else // But if the stop order is trying to buy something, then it cares about the lowest ask price.
			lRelevantPrice = pMarket->GetLowestAskPrice();
		
		// It's a stop order that hasn't activated yet. SHOULD IT ACTIVATE NOW?
		if ((IsGreaterThan()	&& (lRelevantPrice > GetStopPrice())) ||
			(IsLessThan()		&& (lRelevantPrice < GetStopPrice())))
		{
			// Activate the stop order!
			if (!pMarket->AddOffer(*pOffer, true))	// Since we're actually adding an offer to the market (not just
			{										// loading from disk) the we actually want to save the market. bSaveFile=true.
				// Error adding the offer to the market!
				OTLog::Error("Error adding the stop order to the market! (Even though supposedly the right market.)\n");
			}
			else 
			{
				// SUCCESS!
				m_pOffer = pOffer;
				
				m_bHasStopActivated		= true;
				m_bHasTradeActivated	= true;
				
				// The Trade (stored on Cron) has a copy of the Original Offer, with the User's signature on it.
				// A copy of that original Trade object (itself with the user's signature) is already stored in
				// the cron folder (by transaction number.) This happens when the Trade is FIRST added to cron,
				// so it's already safe before we even get here.
				//
				// So thus I am FREE to release the signatures on the offer, and sign with the server instead.
				// The server-signed offer will be stored by the OTMarket.
				m_pOffer->ReleaseSignatures();
				m_pOffer->SignContract(*(GetCron()->GetServerNym()));
				m_pOffer->SaveContract();
				
				pMarket->SaveMarket();
				
				// Now when the market loads next time, it can verify this offer using the server's signature,
				// instead of having to load the user. Because the server has verified it and added it, and now
				// signs it, vouching for it.
				
				
				// The Trade itself (all its other variables) are now allowed to change, since its signatures
				// are also released and it is now server-signed. (With a copy stored of the original.)
				
				
				m_pOffer->SetTrade(*this);

				return m_pOffer;
			}
		}		
	}

	delete pOffer;
	pOffer = NULL;

	return NULL;
}