BitEx

Build a simple chrome extension which tracks Bitcoin prices.

faisalsayed10@faisalsayed10
Edit this page!

Today we'll be building a simple chrome extension which is based on web technologies. It uses HTML, CSS and JavaScript and once, we build it, it will track live Bitcoin prices!

Here's how it will look like:

Demo of how our extension will look like

Here's the source code.

Part 1: Prerequisites

You should have a beginner understanding of:

  • HTML
  • CSS
  • JavaScript

If you're having trouble, feel free to ask me or anyone in the Hack Club Slack!

Part 2: Setup

For writing our code, we'll be using Repl.it but later, we'll need to download it inorder to test our extension.

To get started, go to this HTML starter code.

Part 3: Building the project

1) The Manifest

If there is something which is really important for any chrome extension, then it is the manifest.json file. Without it, we can't create any extensions. So let's first create our manifest.json file!

First, click on 'Add file'.

visual guide to creating manifest

Then, name your file as manifest.json.

Let's now start writing the json. First, we need to create an empty object ({}). Then, inside that, we'll first create a name key, then the manifest_version and so on.

{
  "name": "BitEx",
  "manifest_version": 2,
  "version": "1.0",
  "description": "Chrome Extension which tracks Bitcoin prices",
  "browser_action": {
    "default_name": "BitEx",
    "default_icon": "icon.png",
    "default_popup": "index.html"
  },
  "permissions": []
}

Explanation: The manifest_version will be 2 according to chrome's documentation as manifest_version 1 was deprecated in Chrome 18. The version is your extension's version. If you roll out updates to your extension, the version number increases.

Now, we are going to have our extension's icon in the main Google Chrome toolbar and also have a popup UI for our extension, therefore we will use the browser_action.

If you want to create an icon that isn't always visible, use a page action instead of a browser action.

Next, the browser_action will need the default_name, default_icon and the default_popup values for our extension to work. (Although these values are optional but for our case, we need them.)

NOTE: You can download the icon which I used here.

We don't need any permissions for our extension so we'll keep it as empty.

And with this, we finish building our manifest!

done!

2) HTML

Let's start building the UI for our extension. Building an extension's UI is no different than building a website! So let's start writing the HTML!

<body>
  <div>
    <h1 class="title">Bitcoin Price Tracker</h1>
    <img src="./bitcoin.png" alt="bitcoin logo">
    <div class="bitcoin">Loading...</div>
  </div>
  <script src="index.js"></script>
</body>

NOTE: Download bitcoin.png from here and simply drag and drop it into your repl!

demo on how to drag and drop files in repl.it

We simply create a div element containing a heading, an image and also another div which will display Loading... for now.

You should see something like this in your preview window:

Demo of the code written so far

What mess have we created! It definitely needs some styles! Let's add CSS in the next section!

3) CSS

Let's start by importing a few fonts, then adding styles to each elements!

@import url('https://fonts.googleapis.com/css2?family=Sansita+Swashed:wght@300;400;500;600;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Merriweather:wght@300;400;700&display=swap');

body {
  min-width: 450px;
  background-color: #f4f4f4ee;
  color: #0e0e0e;
  text-align: center;
}

h1 {
  font-family: 'Sansita Swashed', cursive;
  font-size: 28px;
  letter-spacing: 1px;
}

img {
  display: block;
  margin: 0 auto;
  width: 76px;
}

Explanation: First, we import two fonts namely, Sansita Swashed and Merriweather from fonts.google.com. Then, the HTML body has a minimum width of 450px, a background color, a text color and all the text is aligned to center.

Similarly, the heading tag uses the font family Sansita Swashed and has a font size of 28px. There is also a letter spacing set to 1px.

The bitcoin logo image is set to display: block so that we can align it to center using margin: 0 auto. As it was a very large image, we also set its width to 76 pixels.

Let's also set some styles to the <p> tag with the class of bitcoin

.bitcoin {
  font-family: 'Merriweather', serif;
  font-size: 22px;
}

Here, we simply set its font family to Merriweather and its font size is set to 22px.

Yay! Now we have a far better UI compared to what we had earlier!

live demo of code written so far

4) JavaScript

Now we will use JavaScript to fetch the realtime Bitcoin prices and then to show it on the browser screen instead of showing Loading... all the time. First, navigate to your index.js file and let's start writing!

const div = document.querySelector(".bitcoin");
const url =
  "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=bitcoin%2Cbitcoincash%2Cethereum%2Clitecoin%2Cbinancecoin%2Cripple&order=market_cap_desc&per_page=100&page=1&sparkline=false&price_change_percentage=24h";

let data;

We select the div tag with the class of bitcoin using querySelector() and assign it to the div variable. The querySelector() method returns the first element that matches a specified CSS selector(s) in the document.

Learn more about querySelector().

Then, we assign the API URL from where the data will be fetched to the variable url. We also create a data variable where we'll store the fetched data later.

Now, let's fetch the data from that url.

async function fetchData() {
  try {
    const res = await fetch(url);
    data = await res.json();
  } catch (err) {
    console.error(err);
  }
}

Explanation: We first create an async function and then by using the try-catch blocks, the response we receive is stored inside the res variable. Then, after converting this response to json format, it is then stored into the data variable. As usual, the fetch API returns a promise and to handle that promise, we used the async-await syntax.

If there's any error, it will simply get console logged.

Learn more about async-await.

Now if you try console logging the data variable, you should see something like this:

[ { id: 'bitcoin',
    symbol: 'btc',
    name: 'Bitcoin',
    image: 'https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579',
    current_price: 19327.06,
    market_cap: 357299782216,
    market_cap_rank: 1,
    fully_diluted_valuation: 404286280236,
    total_volume: 41738893348,
    high_24h: 19832.27,
    low_24h: 18338.09,
    price_change_24h: -257.1378091,
    price_change_percentage_24h: -1.31299,
    // ...
    last_updated: '2020-12-01T15:05:30.303Z',
    price_change_percentage_24h_in_currency: -1.3129860318628117 },
  {
    // ...
  }

We get an array of data about various cryptocurrencies! From this, we'll make use of the current_price value and the price_change_percentage_24h value of Bitcoin!

Now, let's create a function which will extract these values and add them to the DOM!

Also an important thing to keep in mind is that the price_change_percentage_24h can be negative or positive. So we'll need to check that and display it in a green color or a red color accordingly.

function showPrices() {
  if (data[0].price_change_percentage_24h > 0) {
    // Gentle Reminder: We are using backticks below and not quotes.
    div.innerHTML = 
    `<p>1 BTC = $${data[0].current_price}</p>
      <p class="increased">
        <span>
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7" />
          </svg>
        </span>
        ${data[0].price_change_percentage_24h}%
      </p>`;
  }
}

Explanation: We simply check if the price_change_percentage_24h is greater than 0 or not. If this is true, we start to add various <p> tags inside the <div> tag.

NOTE: Using backticks (``) allows you to inject HTML elements in the DOM using JavaScript, and that's exactly what we do in the above code.

In the first <p> tag, we render bitcoin's current price. Next, we create a <p> tag with a class of increased in which we create a <span> containing a 'chevron up' svg and next to it, we show the price change percentage.

Similarly, we will add an else condition which will do the rendering if the price_change_percentage_24h is negative.

function showPrices() {
  if (data[0].price_change_percentage_24h > 0) {
    // ...
  } else {
    div.innerHTML = 
    `<p>1 BTC = $${data[0].current_price}</p>
      <p class="decreased">
        <span>
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
          </svg>
        </span>
        ${data[0].price_change_percentage_24h}%
      </p>`;
  }
}

Explanation: Everything seems similar here, except the class of the <p> element is now as decreased and the svg we now use is 'chevron down'.

Now let's call this function once all the data is fetched.

async function fetchData() {
  try {
    const res = await fetch(url);
    data = await res.json();
    showPrices(); // Calling the showPrices() function!
  } catch (err) {
    console.error(err);
  }
}

And lastly, call the fetchData() function at the very last line of the document!

Your JavaScript code so far:
const div = document.querySelector(".bitcoin");
const url =
  "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=bitcoin%2Cbitcoincash%2Cethereum%2Clitecoin%2Cbinancecoin%2Cripple&order=market_cap_desc&per_page=100&page=1&sparkline=false&price_change_percentage=24h";

let data;

async function fetchData() {
  try {
    const res = await fetch(url);
    data = await res.json();
    showPrices();
  } catch (err) {
    console.error(err);
  }
}

function showPrices() {
  if (data[0].price_change_percentage_24h > 0) {
    div.innerHTML = `<p>1 BTC = $${data[0].current_price}</p>
  <p class="increased">
    <span>
      <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7" />
      </svg>
    </span>
    ${data[0].price_change_percentage_24h}%
  </p>`;
  } else {
    div.innerHTML = `<p>1 BTC = $${data[0].current_price}</p>
    <p class="decreased"><span><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg></span>${data[0].price_change_percentage_24h}%</p>`;
  }
}

fetchData();

If you RUN this code, you should see something like this!

Preview of the code written so far

We haven't yet implemented the CSS for the classes increased and decreased due to which we don't see the green/red color for the price change percentage. Let's do that finally!

5) CSS, again

Head back to style.css again and let's add styles for those 2 classes.

.increased {
  padding: 4px;
  color: #4dbb79;
}

.decreased {
  padding: 4px;
  color: #f56565;
}

The increased class gets a greenish color and similarly, the decreased class gets a reddish color!

Now if you RUN the code, you'll see that everything works perfectly as we expected!

Demo of code written so far

And now its finally time to turn this into an extension!

Mind is blown, boom boom boom

6) Adding your extension to Chrome

First we'll need to download our code. For this, simply click on the 3 vertical dots on the left and select the option Download as zip.

visual tutorial on how to do it

Once you have download the zip file. Extract it. It will then give you a folder of your repl's name with our code inside!

Next, navigate to chrome://extensions in your chrome browser. You'll see a list of all your installed extensions!

image of chrome extensions page

On the top right corner, make sure you have Developer mode turned on. If not, make sure you turn it on!

developer mode image

Now you'll see 3 new options popped up! Click on the Load unpacked option and select the folder containing your code!

Load unpacked option

And there we go! We successfully installed our extension into our chrome browser! Now you'll be able to see your extension's icon in the chrome toolbar!

Part 4: The End

Yay! We successfully built a wonderful chrome extension which tracks Bitcoin prices!

yay

If you have a developer account, feel free to publish it on the chrome web store! Here's how.

Here are some helpful links:

  1. Chrome Extension Documentation

  2. Cryptocurrency API

  3. Coindesk Bitcoin API

Here are some tasks for you:

  1. Create an extension which shows the current prices for top 5 cryptocurrencies.
    Example

  2. Want to censor/highlight any words on websites you browse? You can create an extension for that too!
    Example where it highlights the word Hack Club on websites.

  3. Create a chrome extension which displays the historical data for Bitcoin using this API.
    Example

  4. Create a chrome extension which shows the past prices of any cyptocurrency of any given date(s)!

  5. Add a feature which alerts you if there is a big price drop!

Now that you have finished building it, you should share your beautiful creation with other people! (I can't wait to see you ship this!)

You probably know the best ways to get in touch with your friends and family, but if you want to share your project with the worldwide Hack Club community there is no better place to do that than on Slack.

  1. In a new tab, open and follow these directions to signup for our Slack.
  2. Then, post the link to the #ship channel to share it with everyone and also ping me!

PS. I'm @fayd on slack.

Byeeee!

We'd love to see what you've made!

Share a link to your project (through Replit, GitHub etc.)