Cryptocurrency Portfolio Tracker JavaScript, API

👤 Sharing: AI
```javascript
/**
 * Cryptocurrency Portfolio Tracker (JavaScript, API)
 *
 * This program tracks the value of your cryptocurrency portfolio using a
 * simple API call to retrieve current market prices.  It uses the CoinGecko API
 * (https://www.coingecko.com/api/documentations/v3) to get the prices.
 *
 *  Important: You need to have Node.js installed to run this script.  Also,
 *  because this script uses `fetch`, which is a modern browser API,
 *  you might need to install a package like `node-fetch` if you're running
 *  in an older Node.js environment.  The code comments explain this.
 *
 *  To run:
 *  1. Save this code as a `.js` file (e.g., `crypto_tracker.js`).
 *  2. Open a terminal or command prompt.
 *  3. Navigate to the directory where you saved the file.
 *  4. Run the command: `node crypto_tracker.js`
 */

// IMPORTANT:  If you get an error like "ReferenceError: fetch is not defined",
// you'll need to install the `node-fetch` package.  Uncomment these lines
// and then run `npm install node-fetch` in your terminal.
// import fetch from 'node-fetch';  //Uncomment this import for node
// const fetch = require('node-fetch'); //Uncomment this for node if necessary

// Replace with your actual portfolio data.
const portfolio = {
  bitcoin: {
    symbol: 'btc',  // Cryptocurrency symbol (used by the API)
    amount: 0.5,    // Amount you own
  },
  ethereum: {
    symbol: 'eth',
    amount: 2.0,
  },
  cardano: {
    symbol: 'ada',
    amount: 100,
  },
};

// API Endpoint (CoinGecko's simple price API)
const apiUrl = `https://api.coingecko.com/api/v3/simple/price?ids=${Object.values(portfolio).map(item => item.symbol).join(',')}&vs_currencies=usd`;

async function getCryptoPrices() {
  try {
    const response = await fetch(apiUrl); // Make the API call
    if (!response.ok) {
      throw new Error(`API request failed with status: ${response.status}`);
    }

    const data = await response.json(); // Parse the JSON response
    return data;
  } catch (error) {
    console.error('Error fetching crypto prices:', error);
    return null; // Return null if there's an error
  }
}

async function calculatePortfolioValue() {
  const prices = await getCryptoPrices();

  if (!prices) {
    console.log('Could not retrieve prices.  Exiting.');
    return;
  }

  let totalPortfolioValue = 0;

  for (const crypto in portfolio) {
    if (portfolio.hasOwnProperty(crypto)) { // Always a good practice when iterating over objects
      const cryptoData = portfolio[crypto];
      const symbol = cryptoData.symbol;

      if (prices[symbol]) {
        const price = prices[symbol].usd; // Get the USD price
        const amount = cryptoData.amount;
        const cryptoValue = price * amount;

        console.log(
          `${crypto}: Amount = ${amount}, Price = $${price}, Value = $${cryptoValue}`
        );

        totalPortfolioValue += cryptoValue;
      } else {
        console.log(`Price data not found for ${crypto} (symbol: ${symbol})`);
      }
    }
  }

  console.log('\n-----------------------------------');
  console.log(`Total Portfolio Value: $${totalPortfolioValue.toFixed(2)}`); // Format to 2 decimal places
}

// Main Execution
calculatePortfolioValue();


/*
Explanation:

1. **Setup and Portfolio Definition:**
   - The code starts by defining a `portfolio` object.  This represents your cryptocurrency holdings.
   - Each cryptocurrency is a key in the `portfolio` object (e.g., `bitcoin`, `ethereum`).
   - Each crypto entry has a `symbol` (used to identify it in the API) and an `amount` (how much you own).  You **must** change this data to match your actual portfolio.

2. **API Endpoint:**
   - `apiUrl` is the URL for the CoinGecko API.  It's constructed to request the prices of all the cryptocurrencies in your `portfolio` in USD.
   - The `ids` parameter is dynamically built using the `symbol` properties from your `portfolio`.  This ensures you only request the prices of the coins you own.
   - CoinGecko is a popular and relatively free API for cryptocurrency data.  Other APIs exist, but this one is straightforward.

3. **`getCryptoPrices()` Function:**
   - This `async` function handles the API call.
   - `fetch(apiUrl)` makes the request to the CoinGecko API.  `fetch` is a modern JavaScript API for making network requests (like getting data from a website).
   - `if (!response.ok)`: Checks if the API request was successful.  If the status code is not in the 200-299 range (meaning OK), it throws an error.
   - `await response.json()`: Parses the JSON response from the API.  The API returns data in JSON (JavaScript Object Notation) format, which is a common way to represent data.
   - The `try...catch` block handles potential errors during the API request (e.g., network problems, invalid API URL).  It's important to handle errors so your program doesn't crash.
   - If an error occurs, it logs the error to the console and returns `null`.

4. **`calculatePortfolioValue()` Function:**
   - This `async` function calculates the total value of your portfolio.
   - `const prices = await getCryptoPrices()`: Calls the `getCryptoPrices()` function to get the latest prices.  It waits for the prices to be fetched before proceeding.
   - `if (!prices)`: Checks if the `prices` are valid (not `null`).  If the API call failed, it exits.
   - The code then iterates through the `portfolio` object using a `for...in` loop.
   - `if (portfolio.hasOwnProperty(crypto))`: This is a crucial check to ensure you're only iterating over the properties that you explicitly defined in your `portfolio` object and not inherited properties from the object's prototype.  This is a best practice when iterating over objects in JavaScript.
   - `const price = prices[symbol].usd`: Retrieves the USD price of the current cryptocurrency from the `prices` object.  The `prices` object is structured like this: `{ btc: { usd: 30000 }, eth: { usd: 2000 } }`.
   - `const cryptoValue = price * amount`: Calculates the value of your holdings for the current cryptocurrency.
   - `console.log(...)`: Prints the details of each cryptocurrency (amount, price, value) to the console.
   - `totalPortfolioValue += cryptoValue`: Accumulates the value of each cryptocurrency into the `totalPortfolioValue`.
   - Finally, it prints the total portfolio value, formatted to two decimal places using `toFixed(2)`.

5. **Main Execution:**
   - `calculatePortfolioValue()` is called to start the process. Because this function is `async`, the JavaScript runtime can continue to execute other code while it waits for the API request to complete.

Key Improvements and Considerations:

* **Error Handling:**  The code includes error handling to gracefully deal with API request failures.
* **Clear Output:** The output is formatted for readability.
* **Modularity:** The code is structured into functions for better organization and reusability.
* **API Rate Limiting:**  Be aware that CoinGecko (and other APIs) may have rate limits.  If you make too many requests in a short period, you might get blocked.  You can implement error handling for HTTP 429 errors (Too Many Requests) and potentially add delays between API calls.  For production use, consider using a paid API plan for higher rate limits.
* **Asynchronous Operations:** The use of `async` and `await` makes the code easier to read and manage when dealing with asynchronous operations (like API calls).
* **Security:**  This code doesn't involve user authentication or sensitive data storage, so security concerns are minimal.  However, if you were to build a more complex application, you'd need to consider security best practices (e.g., protecting API keys, sanitizing user input).
* **Dependencies (Node.js):**  Remember to handle the `node-fetch` dependency if you're running the code in a Node.js environment that doesn't natively support `fetch`.
* **API Key (Optional):**  Some APIs require an API key.  CoinGecko's basic API doesn't, but if you switch to a different API that does, you'll need to include the API key in the `apiUrl` or as a header in the `fetch` request.  Never hardcode API keys directly in your code; use environment variables or configuration files.
* **Data Persistence:** This script only retrieves the portfolio value once.  To track changes over time, you would need to store the data in a database or file.
* **UI (Optional):**  To make the tracker more user-friendly, you could create a graphical user interface (GUI) using HTML, CSS, and JavaScript (perhaps using a framework like React, Vue, or Angular).
*/
```
👁️ Viewed: 9

Comments