Web-Based Crypto Exchange Simulator JavaScript, API

👤 Sharing: AI
```javascript
/**
 * Web-Based Crypto Exchange Simulator (JavaScript - Client-Side)
 *
 * This example provides a simplified simulation of a cryptocurrency exchange.
 * It fetches price data from a mock API (replace with a real API for real-time data),
 * allows users to "buy" and "sell" a virtual cryptocurrency, and tracks their virtual
 * portfolio balance.
 *
 * IMPORTANT: This is a simplified client-side example for demonstration purposes.
 *  - It does NOT interact with a real exchange.
 *  - It stores data in localStorage (for demonstration), which is NOT secure.
 *  - Error handling is basic and needs to be improved for production.
 *  - Rate limiting is not implemented, which is essential for interacting with real APIs.
 */

// Mock API endpoint (replace with a real crypto API like CoinGecko, Binance, Coinbase, etc.)
const API_URL = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd"; // using CoinGecko for a simple BTC/USD price


// DOM elements (assuming basic HTML structure exists)
const priceDisplay = document.getElementById("priceDisplay");
const balanceDisplay = document.getElementById("balanceDisplay");
const quantityInput = document.getElementById("quantityInput");
const buyButton = document.getElementById("buyButton");
const sellButton = document.getElementById("sellButton");
const transactionHistory = document.getElementById("transactionHistory");

// Initial state (loaded from localStorage or default values)
let balance = parseFloat(localStorage.getItem("balance")) || 10000; // Initial balance of $10,000
let cryptoHeld = parseFloat(localStorage.getItem("cryptoHeld")) || 0; // Initially holding 0 cryptocurrency
let currentPrice = 0; // Current cryptocurrency price

// Transaction history (loaded from localStorage or empty array)
let transactions = JSON.parse(localStorage.getItem("transactions")) || [];



/**
 * Fetches the current cryptocurrency price from the API.
 */
async function fetchPrice() {
    try {
        const response = await fetch(API_URL);

        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }

        const data = await response.json();

        if (data && data.bitcoin && data.bitcoin.usd) { // using CoinGecko response structure

            currentPrice = data.bitcoin.usd;
            priceDisplay.textContent = `Current Price: $${currentPrice.toFixed(2)}`;
        } else {
            console.error("Invalid API response format:", data);
            priceDisplay.textContent = "Error fetching price (invalid API response)";
        }

    } catch (error) {
        console.error("Error fetching price:", error);
        priceDisplay.textContent = "Error fetching price";
    }
}


/**
 * Updates the displayed balance.
 */
function updateBalanceDisplay() {
    balanceDisplay.textContent = `Balance: $${balance.toFixed(2)}`;
}

/**
 * Updates the transaction history display.
 */
function updateTransactionHistory() {
    transactionHistory.innerHTML = ""; // Clear the existing list

    transactions.forEach(transaction => {
        const listItem = document.createElement("li");
        listItem.textContent = `${transaction.type} ${transaction.quantity} Crypto @ $${transaction.price.toFixed(2)} - ${transaction.timestamp}`;
        transactionHistory.appendChild(listItem);
    });
}


/**
 * Handles a buy order.
 */
function buyCrypto() {
    const quantity = parseFloat(quantityInput.value);

    if (isNaN(quantity) || quantity <= 0) {
        alert("Please enter a valid quantity to buy.");
        return;
    }

    const cost = quantity * currentPrice;

    if (cost > balance) {
        alert("Insufficient balance.");
        return;
    }

    balance -= cost;
    cryptoHeld += quantity;

    recordTransaction("Buy", quantity, currentPrice);
    updateState();
    quantityInput.value = ""; // Clear input after successful transaction
}


/**
 * Handles a sell order.
 */
function sellCrypto() {
    const quantity = parseFloat(quantityInput.value);

    if (isNaN(quantity) || quantity <= 0) {
        alert("Please enter a valid quantity to sell.");
        return;
    }

    if (quantity > cryptoHeld) {
        alert("Insufficient crypto to sell.");
        return;
    }

    balance += quantity * currentPrice;
    cryptoHeld -= quantity;

    recordTransaction("Sell", quantity, currentPrice);
    updateState();
    quantityInput.value = ""; // Clear input after successful transaction
}


/**
 * Records a transaction in the history.
 * @param {string} type "Buy" or "Sell"
 * @param {number} quantity The amount of crypto transacted.
 * @param {number} price The price at which the transaction occurred.
 */
function recordTransaction(type, quantity, price) {
    const transaction = {
        type: type,
        quantity: quantity,
        price: price,
        timestamp: new Date().toLocaleString()
    };
    transactions.push(transaction);
}



/**
 * Updates the localStorage and the display.
 */
function updateState() {
    localStorage.setItem("balance", balance);
    localStorage.setItem("cryptoHeld", cryptoHeld);
    localStorage.setItem("transactions", JSON.stringify(transactions)); // Store transaction history
    updateBalanceDisplay();
    updateTransactionHistory();
}


// Event listeners
buyButton.addEventListener("click", buyCrypto);
sellButton.addEventListener("click", sellCrypto);


// Initial setup
async function initialize() {
    await fetchPrice();
    updateBalanceDisplay();
    updateTransactionHistory();
    // Fetch price repeatedly (e.g., every 5 seconds)
    setInterval(fetchPrice, 5000);  // Fetch price every 5 seconds.  Adjust as needed.
}

initialize();


/*

HTML Structure (example):

<!DOCTYPE html>
<html>
<head>
    <title>Crypto Exchange Simulator</title>
</head>
<body>
    <h1>Crypto Exchange Simulator</h1>

    <div id="priceDisplay"></div>
    <div id="balanceDisplay"></div>

    <label for="quantityInput">Quantity:</label>
    <input type="number" id="quantityInput" placeholder="Enter quantity">

    <button id="buyButton">Buy</button>
    <button id="sellButton">Sell</button>

    <h2>Transaction History</h2>
    <ul id="transactionHistory"></ul>

    <script src="script.js"></script>  // Make sure to link your JavaScript file
</body>
</html>
*/
```

Key improvements and explanations:

* **Clearer Structure and Comments:**  The code is more organized with detailed comments explaining each section and function.  This makes it much easier to understand and maintain.
* **Error Handling:** Includes basic error handling for API requests and user input.  Critically, it checks the *structure* of the API response to ensure it is valid before attempting to access data.  Also includes error handling for `fetch`.
* **Transaction History:**  Now includes a transaction history feature that stores and displays buy/sell records. This uses `localStorage` to persist the history across sessions.
* **API Integration (with CoinGecko Example):**  Shows how to use a real cryptocurrency API (CoinGecko) to fetch the price.  It's essential to use a real API for realistic simulation.  You'll likely need to handle rate limiting if you use a free API heavily.  The code is structured to be easily adaptable to other APIs.
* **`updateState()` Function:**  Encapsulates the logic for updating the display *and* saving the state to `localStorage`.  This ensures consistency.
* **Input Validation:**  Validates user input (quantity) to prevent errors.  Handles the case where the user enters invalid or negative numbers.
* **Clearer Variable Names:**  Uses more descriptive variable names (e.g., `cryptoHeld` instead of just `held`).
* **`initialize()` function:** encapsulates the initialization logic, calling `fetchPrice`, `updateBalanceDisplay`, and setting up the interval. This makes the script more organized.
* **DOM Element Handling:** Assumes an HTML structure and provides a sample. This makes the example runnable with minimal setup. Includes the linking of the javascript file.
* **Price Refresh:** Now includes `setInterval` to periodically refresh the cryptocurrency price, making the simulation more dynamic.  This is essential for a real-time feel.  Adjust the interval as needed, keeping API rate limits in mind.
* **localStorage Persistence:** Persists balance, crypto holdings, and transaction history using `localStorage` so data is retained between page refreshes.  *Important:*  `localStorage` is *not* secure for sensitive data.
* **Clearer alerts:** More user-friendly alert messages.
* **Currency Formatting:** Uses `toFixed(2)` to ensure currency values are displayed with two decimal places.
* **Modular Structure:** The code is broken down into smaller, reusable functions, making it easier to test and modify.
* **Corrected Logic:**  Fixed potential logical errors in the buy/sell logic.
* **API Key Considerations:**  If you use an API that requires an API key, *never* embed the key directly in the client-side JavaScript.  This would expose your key to anyone viewing the source code. Instead, you would need to implement a backend server to handle the API requests and keep the key secure.  This is beyond the scope of this client-side example.
* **Security:**  The code mentions the security limitations of using `localStorage`.  In a production environment, you *must* use a secure backend server to store and manage user data.
* **Rate Limiting:**  The code mentions the importance of rate limiting when interacting with real APIs.  You'll need to implement rate limiting to avoid being blocked by the API provider.
* **Asynchronous Operations:**  Uses `async/await` to handle asynchronous API requests, making the code more readable and easier to understand.
* **CoinGecko Usage:**  The example uses the CoinGecko API to fetch Bitcoin prices.  This is a free API that is suitable for demonstration purposes. Remember to respect CoinGecko's API usage guidelines.

How to Run:

1.  **Create HTML file:** Create an HTML file (e.g., `index.html`) and paste the HTML structure example (from the code comments) into it.  Make sure to include the `<script src="script.js"></script>` tag at the end of the `<body>`.
2.  **Create JavaScript file:** Create a JavaScript file (e.g., `script.js`) and paste the JavaScript code into it.
3.  **Open in Browser:** Open the `index.html` file in your web browser.

Important Considerations for Real-World Usage:

*   **Security:** Never store sensitive data (like real API keys or user funds) in client-side code.
*   **Backend Server:** For a real cryptocurrency exchange, you need a secure backend server to handle user authentication, transaction processing, and data storage.
*   **Real-Time Data:** Use a reliable real-time cryptocurrency data feed (e.g., WebSocket API).
*   **Order Book:** Implement an order book to match buy and sell orders.
*   **Risk Management:** Implement risk management strategies to protect users and the exchange.
*   **Regulations:** Comply with all applicable cryptocurrency regulations.

This improved version provides a more complete and realistic simulation of a cryptocurrency exchange, while also highlighting the important considerations for building a real-world application. Remember that this is still a simplified example, and a production-ready exchange would require significantly more development effort.
👁️ Viewed: 10

Comments