04/20/2019

Let's Build a Cryptocurrency Portfolio App

In this article, we will be making a very simple cryptocurrency portfolio calculator from scratch with react.js and ruby on rails.

After a lengthy hibernation period, it looks like cryptocurrencies are back on the rise again. So I thought it would be fun to build a cryptocurrency portfolio calculator to help me prepare for the ensuing emotional rollercoaster that is surely on the horizon.

In this post, we are going to use ruby on rails and react js to build our own cryptocurrency portfolio app. We will be using the webpacker gem which will help us do everything in one app, although most of what we will be covering should work if you would prefer to build a separated backend api and front end. Let's get started!

Create a new rails app

First things first, let's create a brand new rails app. We can do this by entering the following command into our terminal:

rails new cryptocurrency-portfolio -d=postgresql --webpack=react

A few things to note: I have added -d=postgresql to explicitly set my database to postgres (the default would otherwise be sqlite), and I've added --webpack=react to configure our app right out of the gate with webpacker to use react. This will allow us to easily use react as the view layer for our app.

Creating our data model

Now that we have a new rails app, the next thing I want to do is create our data model. In this case, things should be pretty simple - all that we need for now is a currency model with some attributes for each cryptocurrency.

For each cryptocurrency I want to have the name of the currency, the currency_symbol (e.g. BTC for bitcoin), and the max_supply (not sure if we will use this but might come in handy in the future). Also, I'm going to be using the CoinMarketCap api, so it would also be helpful to store a slug for each currency that corresponds to this api for easy price lookups.

So let's create a new model with this data. We can do this from our terminal with the following:

rails g model Currency name currency_symbol max_supply:bigint slug
Note that the max_supply is set as bigint, you could probably also just make it an integer, but this might be helpful in case any max supply numbers we get are really large.

After running that generator in your terminal to create our currency model, we can go ahead and migrate our database. Do this from your terminal:

rails db:migrate
You may need to run rails db:create first if you haven't already done so at this point

Now if you navigate into your db folder, you should see a migration and a schema file with our new currency model. You should also see a new currency model inside of app/models.

Seed data

Now that we have created our currency model, we can go ahead and seed our database with data on various cryptocurrencies. Lucky for us, I've put together a dataset of all the information we need on +1300 cryptocurrencies! You can copy the entire set of data from here. Simply paste that file into your db/seed.rb file.

Once you have that copied you can run this command from your terminal to seed your database:

rails db:seed

Now, if you open up a rails console with rails c and type in Currency.count you should see over 1,300 currencies in your database. Type in Currency.firstand the resulting record should be Bitcoin.

Building our rails backend

Now that we have our currency model created and we have added some seed data, building in the key functionality of our portfolio will actually be pretty simple.

All that we really need are methods to do two things:
1) Get the real-time market price of a cryptocurrency, and
2) calculate the value of that cryptocurrency in your portfolio based off of that price and how many units of that currency you currently own.

I'll be using the coin market cap api to get price data. The endpoint we will be using will be api.coinmarketcap.com/v1/ticker/#{symbol} where symbol is replaced by the individual currency's unique symbol, which we already have from when we used the seed file.

I'll also be using the gem httparty to help us make api requests. Let's go ahead and install httparty into our app. In your gemfile add this:

gem 'httparty'

Then in your terminal you can bundle install to install the gem.

Once we have our api end point figured out and httparty installed, the code we will need to get price data is pretty simple. In our currency model, let's add the following method:


  def current_price
    url = "https://api.coinmarketcap.com/v1/ticker/#{self.slug}"
    resp = JSON.parse(HTTParty.get(url).body)
    
    resp[0]["price_usd"]
  end
      

Go ahead and test this out from your rails console. Doing the following should now get you the current price of bitcoin for example:


        bitcoin = Currency.first
        bitcoin.current_price
        # => 7523.09
      

Next we need a method to determine the value in your portfolio based off the current price and how many units you have. So all we need then is a method that multiplies the amount you own times the current price:


  def check_portfolio_value(amount)
    ( self.current_price.to_f * amount.to_f ).round(4)
  end
      

With these two methods, we should be good for our Currency model. Your model should now look something like this:


  class Currency < ApplicationRecord
    def current_price
      url = "https://api.coinmarketcap.com/v1/ticker/#{self.slug}"
      resp = JSON.parse(HTTParty.get(url).body)
      
      resp[0]["price_usd"]
    end 

    def check_portfolio_value(amount)
      ( self.current_price.to_f * amount.to_f ).round(4)
    end 
  end      
        

Creating our currencies controller

Now we can go ahead and build out our currencies controller. from your terminal you can use the following generator to create a new controller. I'm also going to add an index method that we can make into the root path of our app, as well as the entry point for our react when we start adding that momentarily:

rails g controller currencies index

Along with index, I also want to add a search endpoint so that we can search for a cryptocurrency, and a calculate endpoint for calculating portfolio values. So our controller so far should look something like this:


  class CurrenciesController < ApplicationController
    def index
    end

    def search
    end

    def calculate
    end
  end
        

We will need to set up some corresponding routes in our config/routes.rb file as well:


        root 'currencies#index'
        post 'search', to: 'currencies#search'
        post 'calculate', to: 'currencies#calculate'
      

So now, when a user searches for a cryptocurrency from our front end app (which we have not started building yet), they should hit the /search endpoint in this controller where we will then need to return all of the corresponding matches to their search from our database.

This might sound complicated, but we can actually handle this pretty easily using a fuzzy search:


  def search
    @currencies = Currency.where('LOWER(name) LIKE ?', "%#{params[:name].downcase}%")
    
    render json: { currencies: @currencies }
  end
      

Next, when a user submits how much of a currency they own, we want to make a post request to our calculate endpoint and calculate the value. At this point we should have the amount the user owns as well as the id of the currency both in our params when we hit this controller method, so we can do something like this:


  def calculate
    currency = Currency.find(params[:id])
    amount = params[:amount].to_f
    
    render json: { 
      currency: currency, 
      current_price: currency.current_price, 
      amount_owned: amount, 
      value: currency.check_portfolio_value(amount)
    }
  end
      

And with that, I think that is everything we need for our rails backend. Time to start building out our react front end!

Building our React App

Recall that at the beginning of this when we created our new rails app, we added the --webpack=react flag. This did a couple of things for us to help us get up and running with react. In your app if you now jump into javascript/packs you should see a file titled hello_react.jsx. This is a little example boilerplate we've been given along with some instructions on how to use the javascript_pack_tag which is nice.

What we can go ahead and do now is modify this file and then inject it into our root path (currently currencies#index) so that our react code displays on the home page of our site.

I'm going to go ahead and rename this file to index.js, and then what we can do is add it using the javascript pack tag to views/currencies/index.html.erb:

<%= javascript_pack_tag 'index' %>

Now, if you fire up your rails server (rails s) and navigate to localhost:3000 you should see 'Hello react' displaying on the page. Woohoo!

[This section is still being written. More coming soon!]

Conclussion

You can view and fork the code from the video here.

Cryptocurrency Seed Data

Want to use the cryptocurrency seed data that was used in this video for your own apps? You can grab the entire seed file on github here.