This project is about creating a rudimentary market for cryptocurrencies. A class, name "Exchange", has public member functions that allow for the deposit and withdrawl of various assets (e.g. Bitcoin, Etherum and US Dollars). Orders to buy and sell assets at a specified price can also be made and the exchange will perform trades as possible to fulfill orders. Lastly, the exchange has a member function dedicated to printing out the current status of the exchange (i.e. what is in each user’s portfolio, what orders have been opened and filled, what trades have taken place, and what the current prices are for the assets being traded.
The starter code has three header files and 4 implementation files. Some of these files have content in them already, but you are welcome to add, remove or change any part of the code given. Each test case will compile the implementation files and include the exchange.hpp and/or utility.hpp if it makes use of a class declared within. The useraccount files are not directly tested in the test cases, but they can be optionally used to store and manipulate information associated with a user’s account (as helper class(es) for the exchange). The provided main file is never used by any test cases, but it provides an example use of the exchange for your own testing purposes.

main.cpp:
#include <iostream>
#include <map>
#include <string>
#include <vector>

#include "exchange.hpp"
#include "useraccount.hpp"
#include "utility.hpp"

int main() {
  std::cout << "start" << std::endl;

  Exchange base;
  base.MakeDeposit("Nahum", "USD", 1000);
  base.MakeDeposit("Nahum", "ETH", 400);
  base.MakeDeposit("Dolson", "BTC", 100);
  base.MakeDeposit("Dolson", "USD", 7000);
  base.MakeDeposit("Enbody", "USD", 7000);
  base.MakeDeposit("Ofria", "BCH", 9);
  base.MakeWithdrawal("Dolson", "BTC", 10);
  base.PrintUserPortfolios(std::cout);
  std::cout << std::endl;
  Order o_n{"Nahum", "Buy", "BTC", 2, 22};
  Order o_d{"Dolson", "Sell", "BTC", 3, 17};
  std::cout << "Before 1st add order" << std::endl;

  base.AddOrder(o_n);
  std::cout << "After 1st add order" << std::endl;
  base.PrintUsersOrders(std::cout);

  std::cout << std::endl;

  std::cout << "Before 2nd add order" << std::endl;

  base.AddOrder(o_d);

  std::cout << "After 2nd add order" << std::endl;

  base.PrintTradeHistory(std::cout);
  std::cout << std::endl;
  base.PrintUserPortfolios(std::cout);
  std::cout << std::endl;
  base.PrintUsersOrders(std::cout);
  std::cout << std::endl;
  base.AddOrder({"Dolson", "Buy", "ETH", 10, 200});
  base.AddOrder({"Enbody", "Buy", "ETH", 15, 300});
  base.AddOrder({"Nahum", "Sell", "ETH", 20, 100});

  base.PrintTradeHistory(std::cout);
  base.PrintUsersOrders(std::cout);
  base.AddOrder({"Nahum", "Sell", "ETH", 20, 1000});
  base.AddOrder({"Dolson", "Sell", "ETH", 2, 250});
  base.AddOrder({"Enbody", "Buy", "BTC", 1, 10});
  base.PrintTradeHistory(std::cout);
  base.PrintUserPortfolios(std::cout);
  std::cout << std::endl << std::endl;
  base.PrintUsersOrders(std::cout);
  base.AddOrder({"Enbody", "Buy", "LTC", 1, 10});
  base.AddOrder({"Ofria", "Sell", "BCH", 2, 55});
  base.PrintBidAskSpread(std::cout);

  return 0;
}

exchange.cpp:
#include "exchange.hpp"


exchange.hpp:
#pragma once
#include <iostream>
#include <string>

#include "useraccount.hpp"
#include "utility.hpp"

class Exchange {
 public:
  void MakeDeposit(const std::string &username, const std::string &asset,
                   int amount);
  void PrintUserPortfolios(std::ostream &os) const;
  bool MakeWithdrawal(const std::string &username, const std::string &asset,
                      int amount);
  bool AddOrder(const Order &order);
  void PrintUsersOrders(std::ostream &os) const;
  void PrintTradeHistory(std::ostream &os) const;
  void PrintBidAskSpread(std::ostream &os) const;
};

useraccount.cpp:
#include "useraccount.hpp"


useraccount.hpp:
#pragma once

utility.cpp:
#include "utility.hpp"

utility.hpp:
#pragma once
#include <iostream>
#include <string>

struct Order {
  std::string username;
  std::string side;  // Can be "Buy" or "Sell"
  std::string asset;
  int amount;
  int price;
};

struct Trade {
  std::string buyer_username;
  std::string seller_username;
  std::string asset;
  int amount;
  int price;
};


Please write these Exchange member functions:
MakeDeposit: this function should take a username (e.g. Prof), an asset (e.g. “BTC”), and an amount (e.g. 100). The function does not return anything, but should store the information that the deposit occurred to a user’s portfolio. A portfolio is a record of the assets a user possesses on the exchange that are not involved in any open orders. In the example, Prof is depositing 100 BTC (Bitcoins) into the exchange.
PrintUserPortfolios: this function takes a reference to a std::ostream and should print out each user’s portfolio (ordered alphabetically by user’s name, and then by asset). Remember that assets that are involved in an open order should not be part of a user’s portfolio. Please see the test cases for exact formatting. Most test cases involving printing will print to std::cout (for easier output reading), as well as, to a std::ostringstream (for test case validation).
PrintUserOrders: For each user (ordered alphabetically), this function prints the open and filled trades (ordered chronologically as each trade was opened/filled) to the referenced std::ostream. See test cases for exact formatting.
PrintTradeHistory: Prints a record of each trade (chronologically) that occurred to the provided reference to std::ostream. See test cases for exact formatting.
PrintBidAskSpread: For each asset (ordered alphabetically), prints the bid ask spread dictated by the open orders to the reference to std::ostream. See test cases for exact formatting.