In the fast-paced world of cryptocurrencies, staying informed about price fluctuations is crucial. Manually checking prices on various exchanges can be time-consuming and inefficient. This tutorial will guide you through building a simple, interactive web-based cryptocurrency price tracker using TypeScript. This project will not only teach you the fundamentals of TypeScript but also provide you with a practical application that you can use and expand upon.
Why Build a Cryptocurrency Price Tracker?
Creating a cryptocurrency price tracker offers several benefits:
- Real-time Data: Access live price updates, allowing for informed decisions.
- Practical Skill Application: Solidify your understanding of TypeScript concepts.
- Customization: Tailor the tracker to display the cryptocurrencies you’re most interested in.
- Learning by Doing: Gain hands-on experience building a functional web application.
This tutorial is designed for beginners to intermediate developers. We will break down each step, explaining the underlying concepts in simple terms with code examples. By the end, you’ll have a working price tracker and a solid foundation in TypeScript web development.
Prerequisites
Before we begin, ensure you have the following installed:
- Node.js and npm (or yarn): Required to manage project dependencies. Download from https://nodejs.org/.
- A Code Editor: Visual Studio Code (VS Code) is recommended, but you can use any editor you prefer.
- Basic HTML, CSS, and JavaScript knowledge: Familiarity with these technologies will be helpful.
Setting Up Your Project
Let’s start by setting up our project. Open your terminal or command prompt and follow these steps:
- Create a Project Directory: Create a new directory for your project:
mkdir crypto-tracker
cd crypto-tracker
- Initialize npm: Initialize a new npm project:
npm init -y
- Install TypeScript: Install TypeScript and the necessary types for DOM manipulation:
npm install typescript @types/node @types/dom
- Create `tsconfig.json`: Initialize a `tsconfig.json` file to configure TypeScript:
npx tsc --init --rootDir src --outDir dist
This command creates a `tsconfig.json` file with default settings. We’ll make some adjustments to it shortly.
- Project Structure: Your project structure should now look like this:
crypto-tracker/
├── node_modules/
├── package.json
├── package-lock.json
├── tsconfig.json
Configuring `tsconfig.json`
Open `tsconfig.json` in your code editor. We’ll configure it for our project. Here’s a recommended configuration:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"]
}
Key configurations explained:
- `target`: Specifies the JavaScript version to compile to (ES5 for broader browser compatibility).
- `module`: Specifies the module system (CommonJS for Node.js).
- `outDir`: Specifies the output directory for compiled JavaScript files.
- `rootDir`: Specifies the root directory of your TypeScript source files.
- `strict`: Enables strict type checking.
- `esModuleInterop`: Enables interoperability between CommonJS and ES modules.
- `skipLibCheck`: Skips type checking of declaration files.
- `include`: Specifies which files to include in the compilation.
Creating the HTML Structure
Create an `index.html` file in your project’s root directory. This will be the structure for our price tracker. Here’s a basic structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cryptocurrency Price Tracker</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>Cryptocurrency Price Tracker</h1>
<div id="crypto-table">
<!-- Crypto prices will be displayed here -->
</div>
</div>
<script src="dist/app.js"></script>
</body>
</html>
This HTML provides a basic structure with a title, a container, and a designated area (`crypto-table`) where we’ll display the cryptocurrency prices. It also links to a CSS file (`style.css`) for styling and a JavaScript file (`dist/app.js`) which will be generated from our TypeScript code.
Styling with CSS
Create a `style.css` file in your project’s root directory. Add some basic styling to make the tracker visually appealing. Here’s an example:
body {
font-family: sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 80%;
max-width: 800px;
}
h1 {
text-align: center;
color: #333;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
This CSS provides basic styling for the body, container, headings, and table elements. Feel free to customize the styles to your preference.
Writing the TypeScript Code
Create a `src` directory and inside it, create a file named `app.ts`. This is where we’ll write our TypeScript code. Let’s start by defining some interfaces and types:
// Define an interface for a single cryptocurrency
interface CryptoData {
symbol: string;
name: string;
price: number;
change: number;
}
// Define a type for an array of CryptoData objects
type CryptoList = CryptoData[];
// API endpoint for fetching cryptocurrency prices
const API_URL = 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=10&page=1&sparkline=false&price_change_percentage=24h';
// Function to fetch crypto data
async function getCryptoData(): Promise<CryptoList> {
try {
const response = await fetch(API_URL);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data: CryptoList = await response.json();
return data.map(crypto => ({
symbol: crypto.symbol.toUpperCase(),
name: crypto.name,
price: crypto.current_price,
change: crypto.price_change_percentage_24h,
}));
} catch (error: any) {
console.error('Could not fetch crypto data:', error);
throw error; // Re-throw the error to be handled by the caller
}
}
// Function to create a table row for a crypto
function createCryptoRow(crypto: CryptoData): HTMLTableRowElement {
const row = document.createElement('tr');
row.innerHTML = `
<td>${crypto.symbol}</td>
<td>${crypto.name}</td>
<td>$${crypto.price.toFixed(2)}</td>
<td style="color: ${crypto.change > 0 ? 'green' : 'red'}">${crypto.change.toFixed(2)}%</td>
`;
return row;
}
// Function to display crypto data in the table
async function displayCryptoData() {
const cryptoTable = document.getElementById('crypto-table');
if (!cryptoTable) {
console.error('Crypto table element not found!');
return;
}
try {
const cryptoData = await getCryptoData();
// Create table
const table = document.createElement('table');
const thead = document.createElement('thead');
thead.innerHTML = `
<tr>
<th>Symbol</th>
<th>Name</th>
<th>Price</th>
<th>Change (24h)</th>
</tr>
`;
table.appendChild(thead);
const tbody = document.createElement('tbody');
cryptoData.forEach(crypto => {
const row = createCryptoRow(crypto);
tbody.appendChild(row);
});
table.appendChild(tbody);
// Clear existing content and append the table
cryptoTable.innerHTML = ''; // Clear existing content
cryptoTable.appendChild(table);
} catch (error) {
// Handle errors (e.g., display an error message)
cryptoTable.innerHTML = '<p style="color: red;">Failed to load cryptocurrency data.</p>';
}
}
// Initial call to display data when the page loads
window.onload = displayCryptoData;
Let’s break down the code:
- Interfaces and Types: We define `CryptoData` interface to represent the structure of each cryptocurrency’s data and `CryptoList` type to represent an array of `CryptoData`.
- API Endpoint: The `API_URL` constant stores the API endpoint for fetching cryptocurrency prices from CoinGecko.
- `getCryptoData()` Function: This asynchronous function fetches data from the API, parses the JSON response, and maps it to our `CryptoData` interface. It includes error handling to catch and log any issues during the API call.
- `createCryptoRow()` Function: This function creates a table row (`<tr>`) for a single cryptocurrency, populating it with the symbol, name, price, and 24-hour change. It also styles the change percentage to be green if positive and red if negative.
- `displayCryptoData()` Function: This asynchronous function fetches the crypto data, creates an HTML table, populates it with the data, and appends it to the `crypto-table` element in your HTML. It also includes error handling to display an error message if the API call fails.
- `window.onload` Event: The `displayCryptoData()` function is called when the page is fully loaded, ensuring that the HTML elements are available before attempting to manipulate them.
Compiling and Running the Code
Now that we have our TypeScript code, let’s compile it and run our application:
- Compile the TypeScript: Open your terminal and run the following command from the project root:
tsc
This command will compile your `app.ts` file into `app.js` and place it in the `dist` directory.
- Open `index.html` in your browser: Open the `index.html` file in your web browser. You should see the cryptocurrency price tracker displaying the prices of the top cryptocurrencies.
Common Mistakes and How to Fix Them
Here are some common mistakes and how to avoid them:
- Incorrect File Paths: Double-check the file paths in your HTML (e.g., `<script src=”dist/app.js”></script>`) and CSS (`<link rel=”stylesheet” href=”style.css”>`). Ensure they point to the correct files.
- Typographical Errors: Typos in variable names, function names, or HTML element IDs can cause errors. Carefully review your code for any spelling mistakes.
- API Rate Limits: Be mindful of API rate limits. CoinGecko has rate limits to prevent abuse. If you exceed the limits, you may receive an error. Consider implementing error handling and possibly caching the API responses.
- CORS Errors: If you encounter CORS (Cross-Origin Resource Sharing) errors, it means the API server is not configured to allow requests from your domain. This is less likely with the CoinGecko API, but if it occurs, you may need to use a proxy server or configure CORS on the API server (if you have control over it).
- Incorrect Data Parsing: Ensure that the data you receive from the API matches your `CryptoData` interface. If the API response changes, you may need to update your interface and parsing logic. Inspect the API response using your browser’s developer tools to verify the data structure.
- Uncaught Errors: Always include proper error handling using `try…catch` blocks to catch potential errors. Display helpful error messages to the user and log errors for debugging purposes.
Enhancements and Next Steps
This is a basic cryptocurrency price tracker. Here are some ideas to enhance it:
- Add More Cryptocurrencies: Allow users to search for and add their favorite cryptocurrencies to the tracker.
- Implement Real-time Updates: Use WebSockets or Server-Sent Events (SSE) to receive real-time price updates from the API.
- Add Price Charts: Integrate a charting library (e.g., Chart.js) to display price history.
- User Interface Improvements: Improve the user interface with better styling, responsive design, and more user-friendly interactions.
- Data Persistence: Store user preferences and data using local storage or a backend database.
- Add Sorting and Filtering: Allow users to sort the cryptocurrency list by price, change, or market capitalization.
- Implement Error Handling: Improve error handling and display more informative error messages to the user.
- Add Themes: Allow users to choose between light and dark themes.
Key Takeaways
- TypeScript Fundamentals: You’ve learned how to define interfaces, types, and use async/await for asynchronous operations.
- API Integration: You’ve successfully fetched data from a public API and displayed it in a web application.
- DOM Manipulation: You’ve learned how to create and manipulate HTML elements using JavaScript.
- Project Setup: You’ve learned how to set up a TypeScript project using npm and configure `tsconfig.json`.
- Practical Application: You’ve built a functional cryptocurrency price tracker that you can use and expand upon.
FAQ
- How do I update the cryptocurrency prices in real-time?
- To update prices in real-time, you’ll need to use WebSockets or Server-Sent Events (SSE) to receive live data from the API. The current tutorial fetches data on page load, but real-time updates require a different approach.
- Can I add more cryptocurrencies to the tracker?
- Yes, you can modify the code to allow users to search for and add their favorite cryptocurrencies. You would need to update the API calls to include the specific cryptocurrency symbols the user selects.
- How can I deploy this application?
- You can deploy this application using services like Netlify, Vercel, or GitHub Pages. You will need to build the project (using `tsc`) and deploy the `dist` directory and `index.html` file.
- What if the API changes?
- If the API changes, you may need to update the `CryptoData` interface and the parsing logic in the `getCryptoData()` function to match the new API response. It’s important to monitor the API documentation for any updates or changes.
- How do I handle API rate limits?
- To handle API rate limits, implement error handling in your `getCryptoData()` function. You could also implement caching to store data locally and reduce the frequency of API calls. Some APIs provide rate limit information in the response headers; you can use this information to implement a backoff strategy.
Building this cryptocurrency price tracker is a great starting point for learning TypeScript and web development. The combination of practical application and clear explanations provides an effective way to learn. Remember to experiment, explore, and continue to build upon what you’ve learned. The skills you’ve gained here are transferable to many other web development projects. The ability to fetch data from APIs, manipulate the DOM, and handle asynchronous operations are fundamental skills for any front-end developer. With this foundation, you are well-equipped to tackle more complex projects and continue your journey in the world of web development.
