Create a cryptocurrency tracking app with push notifications using Swift and Laravel - Part 1: The backend
Tags: pusher, swift, ios, realtime
Published: 2018-11-22 10:44:59

---
title: Create a cryptocurrency tracking app with push notifications using Swift and Laravel - Part 1: The backend
published: true
description: 
tags: pusher, swift, ios, realtime
---

> You will need the following installed on your machine: Xcode, the Laravel CLI, SQLite, and Cocoapods. Familiarity with the Xcode IDE will be helpful.

## Introduction

Cryptocurrency has been and is still one of the biggest trends this year. With currencies like Bitcoin reaching record highs and new companies creating tokens and offerings, it’s showing just how much potential cryptocurrencies have. However, cryptocurrency prices are erratic and can fall or climb at a moments notice, so it’s always a good idea to keep tabs on the changes.

In this article, we will be building an application that keeps tabs on changes to the crypto market. The application will focus on BTC and ETH and will allow users of the application to set minimum and maximum amounts when they would like to be notified about the coins current price. The application will be built using Swift, Laravel, Pusher Channels, and Pusher Beams.

## Prerequisites

To follow along you need the following requirements:

- [Xcode](https://developer.apple.com/xcode) installed on your machine.
- Knowledge of the Xcode IDE.
- Basic knowledge using the [Laravel framework](https://laravel.com/).
- Basic knowledge of the [Swift programming language](http://developer.apple.com/swift).
- [Laravel CLI](https://laravel.com/docs/5.6/installation) installed on your machine.
- SQLite installed on your machine. [Installation guide](https://www.tutorialspoint.com/sqlite/sqlite_installation.htm).
- [Cocoapods](https://guides.cocoapods.org/using/getting-started.html) installed on your machine.
- [Pusher Beams](https://pusher.com/beams) and [Channels](https://pusher.com/channels) application.

## What we will be building

We will start out by building the backend of the application using Laravel. Then we will build the iOS application using Swift. If you want to test the push notifications then you will need to run the application on a live device.

### How the client application will work

For the client app, the iOS application, we will create a simple list that will display the available currencies and the current prices to the dollar. Whenever the price of the cryptocurrency changes, we will trigger an event using Pusher Channels so the prices are updated.

From the application, you will be able to set a minimum and maximum price change when you want to be alerted. For instance, you can configure the application to send a push notification to the application when the price of one Etherium (ETH) goes below $500. You can also configure the application to receive a notification when the price of Bitcoin goes above $5000.

### How the backend application will work

For the backend application, we will be using Laravel and we will create endpoints that allow a user update the settings and load the settings for a device. The API will be responsible for checking the current prices of the cryptocurrency and sending both a Channels update and a Beams notification when the price changes.

However, because the prices don’t change very predictably, we will be simulating the currency changes so we can preview the application in action. We will also be using [task scheduling](https://laravel.com/docs/5.6/scheduling) in Laravel to trigger the checks for the current currency prices.

In a production environment we will set the scheduler as a cronjob, but because we are in development, we will manually run the command to trigger price changes.

### How the application will look

When we are done with the application, here's how the application will look:

![](//images.ctfassets.net/1es3ne0caaid/1K08NTSdaoIIqWQ2YAyOqo/4efdb4fa01a2ee599bf5b71561a717a4/ios-cryptocurrency-part-1-demo.gif)

Let’s get started.

## Setting up Pusher Beams and Channels

### Setting up Pusher Channels

Log in to your [Pusher dashboard](https://dashboard.pusher.com). If you don’t have an account, create one. Your dashboard should look like this:

![](//images.ctfassets.net/1es3ne0caaid/47FA7jeU0w62siO8G6iCQi/aeda1c00644c75e4d327dbe6725694d7/ios-cryptocurrency-part-1-keys.png)

Create a new Channels app. You can easily do this by clicking the big **Create new Channels app** card at the bottom right. When you create a new app, you are provided with keys. Keep them safe as you will soon need them.

### Setting up Pusher Beams

Next, log in to the new [Pusher dashboard](https://dash.pusher.com/), in here we will create a Pusher Beams instance. You should sign up if you don’t have an account yet. Click on the **Beams** button on the sidebar then click **Create**, this will launch a pop up to **Create a new Beams instance**. Name it `cryptoalat`.

![](//images.ctfassets.net/1es3ne0caaid/4xKD0goX606gGqUSQW2EcC/3dcd7757df87351ddc54cb62397ce2e7/ios-cryptocurrency-part-1-new-beams.png)

As soon as you create the instance, you will be presented with a quickstart guide. Select the **IOS** quickstart and follow through the wizard.

![](//images.ctfassets.net/1es3ne0caaid/27fmUEHf64Qc0KcIQo0KAw/265bde6f67ea031f5d5495a10273e678/ios-cryptocurrency-part-1-beams-quickstart.png)

When you are done creating the Beams application, you will be provided with an instance ID and a secret key, we will need these later.

## Setting up your backend application

In your terminal, run the command below to create a new Laravel project:

```
    $ laravel new cryptoapi

```

This command will create a new Laravel project and install all the required Laravel dependencies.

Next, let’s install some of the project specific dependencies. Open the `composer.json` file and in the `require` property, add the following dependencies:

```
    // File: composer.json
    "require": {
        [...]

        "neo/pusher-beams": "^1.0",
        "pusher/pusher-php-server": "~3.0"
    },
```

Now run the command below to install these dependencies.

```
    $ composer update

```

When the installation is complete, open the project in a text editor of your choice. [Visual Studio Code](https://code.visualstudio.com/) is pretty nice.

### Setting up our Pusher Beams library

The first thing we want to do is set up the [Pusher Beams library](https://github.com/neoighodaro/pusher-beams) we just pulled in using composer. To set up, open the `.env` file and add the following keys:

```
    PUSHER_BEAMS_SECRET_KEY="PUSHER_BEAMS_SECRET_KEY"
    PUSHER_BEAMS_INSTANCE_ID="PUSHER_BEAMS_INSTANCE_ID"

```

You should replace the `PUSHER_BEAMS_*` placeholders with the keys you got when setting up your Beams application.

Next, open the `config/broadcasting.php` file and scroll until you see the `connections` key. In there, you’ll have the `pusher` settings, add the following to the `pusher` configuration:

```
    <span class="hljs-string">'pusher'</span> => [
        <span class="hljs-comment">// [...]</span>

        <span class="hljs-string">'beams'</span> => [
            <span class="hljs-string">'secret_key'</span> => env(<span class="hljs-string">'PUSHER_BEAMS_SECRET_KEY'</span>),
            <span class="hljs-string">'instance_id'</span> => env(<span class="hljs-string">'PUSHER_BEAMS_INSTANCE_ID'</span>),
        ],
    ],
```

### Setting up our Pusher Channels library

The next step is to set up Pusher Channels. Laravel comes with native support for Pusher Channels so we do not need to do much to set it up.

Open the `.env` file and update the following keys below:

```
    BROADCAST_DRIVER=pusher

    // [...]

    PUSHER_APP_ID="PUSHER_APP_ID"
    PUSHER_APP_KEY="PUSHER_APP_KEY"
    PUSHER_APP_SECRET="PUSHER_APP_SECRET"
    PUSHER_APP_CLUSTER="PUSHER_APP_CLUSTER"

```

Above you set the `BROADCAST_DRIVER` to `pusher` and then for the other `PUSHER_APP_*` keys, replace the placeholders with the keys gotten from your Pusher dashboard. That’s all we need to do to set up Pusher Channels for this application.

## Building the backend application

Now that we have set up all the dependencies, we can start building the application. We will start by creating the routes. However, instead of creating controllers to hook into the routes, we will be adding the logic directly to the routes.

### Setting up the database, migration, and model

Since we will be working with a database, we need to set up the database we are going to be working with. To make things easy we will be using SQLite. Create an empty `database.sqlite` file in the `database` directory.

Open the `.env` file and replace:

```
    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=homestead
    DB_USERNAME=homestead
    DB_PASSWORD=secret

```

With

```
    DB_CONNECTION=sqlite
    DB_DATABASE=/full/path/to/your/database.sqlite

```

Next, let’s create a migration for the `devices` table. We will use this table to store devices and their notification settings. This will help us know what devices to send push notifications to.

Run the command below to create the migration and model:

```
    $ php artisan make:model Device -m

```

> The `-m` flag will instruct artisan to create a migration alongside the model.

This command will generate two files, the migration file in the `database/migrations` and the model in the `app` directory. Let’s edit the migration file first.

Open the `*_create_devices_table.php` migration file in the `database/migrations` directory and replace the contents with the following:

```
    <span class="hljs-meta"><?php</span>

    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Schema</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Schema</span>\<span class="hljs-title">Blueprint</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Migrations</span>\<span class="hljs-title">Migration</span>;

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreateDevicesTable</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Migration</span>
    </span>{
        <span class="hljs-comment">/**
         * Run the migrations.
         *
         * <span class="hljs-doctag">@return</span> void
         */</span>
        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span><span class="hljs-params">()</span>
        </span>{
            Schema::create(<span class="hljs-string">'devices'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(Blueprint $table)</span> </span>{
                $table->increments(<span class="hljs-string">'id'</span>);
                $table->string(<span class="hljs-string">'uuid'</span>)->unique();
                $table->float(<span class="hljs-string">'btc_min_notify'</span>)->default(<span class="hljs-number">0</span>);
                $table->float(<span class="hljs-string">'btc_max_notify'</span>)->default(<span class="hljs-number">0</span>);
                $table->float(<span class="hljs-string">'eth_min_notify'</span>)->default(<span class="hljs-number">0</span>);
                $table->float(<span class="hljs-string">'eth_max_notify'</span>)->default(<span class="hljs-number">0</span>);
            });
        }

        <span class="hljs-comment">/**
         * Reverse the migrations.
         *
         * <span class="hljs-doctag">@return</span> void
         */</span>
        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">down</span><span class="hljs-params">()</span>
        </span>{
            Schema::dropIfExists(<span class="hljs-string">'devices'</span>);
        }
    }
```

In the `up` method, we have defined the structure of the `devices` table. We have the `uuid` field which will be a unique string for each device registered. We have two `btc_notify` fields which are there to save the minimum and maximum prices of BTC at which point the device should be notified. Same applies to the\* `eth_*_notify` fields.

To run the migration, run the command below:

```
    $ php artisan migrate

```

Open the `app/Device.php` model and replace the contents with the code below:

```
    <span class="hljs-meta"><?php</span>
    <span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>;

    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Model</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Notifications</span>\<span class="hljs-title">Notifiable</span>;

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Device</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span>
    </span>{
        <span class="hljs-keyword">use</span> <span class="hljs-title">Notifiable</span>;

        <span class="hljs-keyword">public</span> $timestamps = <span class="hljs-keyword">false</span>;

        <span class="hljs-keyword">protected</span> $fillable = [
            <span class="hljs-string">'uuid'</span>, 
            <span class="hljs-string">'btc_min_notify'</span>, 
            <span class="hljs-string">'btc_max_notify'</span>, 
            <span class="hljs-string">'eth_min_notify'</span>, 
            <span class="hljs-string">'eth_max_notify'</span>,
        ];

        <span class="hljs-keyword">protected</span> $cast = [
            <span class="hljs-string">'btc_min_notify'</span> => <span class="hljs-string">'float'</span>,
            <span class="hljs-string">'btc_max_notify'</span> => <span class="hljs-string">'float'</span>,
            <span class="hljs-string">'eth_min_notify'</span> => <span class="hljs-string">'float'</span>,
            <span class="hljs-string">'eth_max_notify'</span> => <span class="hljs-string">'float'</span>
        ];

        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">scopeAffected</span><span class="hljs-params">($query, string $currency, $currentPrice)</span>
        </span>{
            <span class="hljs-keyword">return</span> $query->where(<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($q)</span> <span class="hljs-title">use</span> <span class="hljs-params">($currency, $currentPrice)</span> </span>{
                $q->where(<span class="hljs-string">"${currency}_min_notify"</span>, <span class="hljs-string">'>'</span>, <span class="hljs-number">0</span>)
                  ->where(<span class="hljs-string">"${currency}_min_notify"</span>, <span class="hljs-string">'>'</span>, $currentPrice);
            })->orWhere(<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($q)</span> <span class="hljs-title">use</span> <span class="hljs-params">($currency, $currentPrice)</span> </span>{
                $q->where(<span class="hljs-string">"${currency}_max_notify"</span>, <span class="hljs-string">'>'</span>, <span class="hljs-number">0</span>)
                  ->where(<span class="hljs-string">"${currency}_max_notify"</span>, <span class="hljs-string">'<'</span>, $currentPrice);
            });
        }
    }
```

In the model above, we have set the `$timestamps` property to `false` to make sure that Eloquent does not try to update the `created_at` and `updated_at` fields, which is the normal behavior.

We also have the `scopeAffected` method which is an example of an [Eloquent scope](https://laravel.com/docs/5.6/eloquent#local-scopes). We use this to get the affected devices after a price change has occurred on a currency. So if, for instance, BTC’s price drops, this method will check the devices and the settings to see the devices that need to be notified of this change.

> Local scopes allow you to define common sets of constraints that you may easily re-use throughout your application. For example, you may need to frequently retrieve all users that are considered "popular". To define a scope, prefix an Eloquent model method with `scope`. - [Laravel documentation](https://laravel.com/docs/5.6/eloquent#local-scopes).

We will use this scope later in our application when we need to know what devices to send push notifications to.

### Creating the routes

Open the `routes/api.php` file and replace the contents of the file with the following code:

```
    <span class="hljs-comment">// File: routes/api.php</span>
    <span class="hljs-meta"><?php</span>

    <span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Device</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Request</span>;
```

Next, let’s add the first route. Append the code below to the routes file:

```
    <span class="hljs-comment">// File: routes/api.php</span>
    Route::get(<span class="hljs-string">'/settings'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(Request $request)</span> </span>{
        <span class="hljs-keyword">return</span> Device::whereUuid($request->query(<span class="hljs-string">'u'</span>))->firstOrFail()[<span class="hljs-string">'settings'</span>];
    });
```

In the route above, we are returning the settings for the device supplied in the `u` query parameter. This means if a registered device hits the `/settings` endpoint and passes the device UUID through the `u` parameter, the settings for that device will be returned.

Next, in the same routes file, paste the following at the bottom of the file:

```
    Route::post(<span class="hljs-string">'/settings'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(Request $request)</span> </span>{
        $settings = $request->validate([
            <span class="hljs-string">'btc_min_notify'</span> => <span class="hljs-string">'int|min:0'</span>,
            <span class="hljs-string">'btc_max_notify'</span> => <span class="hljs-string">'int|min:0'</span>,
            <span class="hljs-string">'eth_min_notify'</span> => <span class="hljs-string">'int|min:0'</span>,
            <span class="hljs-string">'eth_max_notify'</span> => <span class="hljs-string">'int|min:0'</span>,
        ]);

        $settings = array_filter($settings, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($value)</span> </span>{ <span class="hljs-keyword">return</span> $value > <span class="hljs-number">0</span>; });

        $device = Device::firstOrNew([<span class="hljs-string">'uuid'</span> => $request->query(<span class="hljs-string">'u'</span>)]);
        $device->fill($settings);
        $saved = $device->save();

        <span class="hljs-keyword">return</span> response()->json([
            <span class="hljs-string">'status'</span> => $saved ? <span class="hljs-string">'success'</span> : <span class="hljs-string">'failure'</span>
        ], $saved ? <span class="hljs-number">200</span> : <span class="hljs-number">400</span>);
    });
```

Above, we have defined the route for the `POST /settings` route. This route saves settings to the database. It will create a new entry if the setting does not already exist or will update the existing one if it does.

That’s all for the routes.

### Creating the jobs, events, and notifiers

Next, we need to create the [Laravel job](https://laravel.com/docs/5.6/queues#creating-jobs) that will run at intervals to check if there is a change in the currency price.

Run the command below to create a new Laravel job:

```
    $ php artisan make:job CheckPrices

```

This will create a new `CheckPrices` class in the `app` directory. Open that class and replace the contents with the following:

```
    <span class="hljs-meta"><?php</span>

    <span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Jobs</span>;

    <span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Device</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Bus</span>\<span class="hljs-title">Queueable</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">SerializesModels</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">InteractsWithQueue</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Contracts</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">ShouldQueue</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Foundation</span>\<span class="hljs-title">Bus</span>\<span class="hljs-title">Dispatchable</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Events</span>\<span class="hljs-title">CurrencyUpdated</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Notifications</span>\<span class="hljs-title">CoinPriceChanged</span>;

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckPrices</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ShouldQueue</span>
    </span>{
        <span class="hljs-keyword">use</span> <span class="hljs-title">Dispatchable</span>, <span class="hljs-title">InteractsWithQueue</span>, <span class="hljs-title">Queueable</span>, <span class="hljs-title">SerializesModels</span>;

        <span class="hljs-keyword">protected</span> $supportedCurrencies = [<span class="hljs-string">'ETH'</span>, <span class="hljs-string">'BTC'</span>];

        <span class="hljs-comment">/**
         * Execute the job.
         *
         * <span class="hljs-doctag">@return</span> void
         */</span>
        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handle</span><span class="hljs-params">()</span>
        </span>{
            $payload = <span class="hljs-keyword">$this</span>->getPricesForSupportedCurrencies();

            <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">empty</span>($payload)) {
                <span class="hljs-keyword">$this</span>->triggerPusherUpdate($payload);
                <span class="hljs-keyword">$this</span>->triggerPossiblePushNotification($payload);
            }
        }

        <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">triggerPusherUpdate</span><span class="hljs-params">($payload)</span>
        </span>{
            event(<span class="hljs-keyword">new</span> CurrencyUpdated($payload));
        }

        <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">triggerPossiblePushNotification</span><span class="hljs-params">($payload)</span>
        </span>{
            <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">$this</span>->supportedCurrencies <span class="hljs-keyword">as</span> $currency) {
                $currentPrice = $payload[$currency][<span class="hljs-string">'current'</span>];

                $currency = strtolower($currency);

                <span class="hljs-keyword">foreach</span> (Device::affected($currency, $currentPrice)->get() <span class="hljs-keyword">as</span> $device) {
                    $device->notify(<span class="hljs-keyword">new</span> CoinPriceChanged($currency, $device, $payload));
                }
            }
        }

        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getPricesForSupportedCurrencies</span><span class="hljs-params">()</span>: <span class="hljs-title">array</span>
        </span>{
            $payload = [];

            <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">$this</span>->supportedCurrencies <span class="hljs-keyword">as</span> $currency) {
                <span class="hljs-keyword">if</span> (config(<span class="hljs-string">'app.debug'</span>) === <span class="hljs-keyword">true</span>) {
                    $response = [
                        $currency => [
                            <span class="hljs-string">'USD'</span> => (float) rand(<span class="hljs-number">100</span>, <span class="hljs-number">15000</span>)
                        ]
                    ];
                } <span class="hljs-keyword">else</span> {
                    $url = <span class="hljs-string">"https://min-api.cryptocompare.com/data/pricehistorical?fsym={$currency}&tsyms=USD&ts={$timestamp}"</span>;

                    $response = json_decode(file_get_contents($url), <span class="hljs-keyword">true</span>);
                }

                <span class="hljs-keyword">if</span> (json_last_error() === JSON_ERROR_NONE) {
                    $currentPrice = $response[$currency][<span class="hljs-string">'USD'</span>];

                    $previousPrice = cache()->get(<span class="hljs-string">"PRICE_${currency}"</span>, <span class="hljs-keyword">false</span>);

                    <span class="hljs-keyword">if</span> ($previousPrice == <span class="hljs-keyword">false</span> <span class="hljs-keyword">or</span> $previousPrice !== $currentPrice) {
                        $payload[$currency] = [
                            <span class="hljs-string">'current'</span> => $currentPrice,
                            <span class="hljs-string">'previous'</span> => $previousPrice,
                        ];
                    }

                    cache()->put(<span class="hljs-string">"PRICE_${currency}"</span>, $currentPrice, (<span class="hljs-number">24</span> * <span class="hljs-number">60</span> * <span class="hljs-number">60</span>));
                }
            }

            <span class="hljs-keyword">return</span> $payload;
        }
    }
```

In the class above, we implement the `ShouldQueue` interface. This makes it so that the job can and will be queued. In a production server, queueing jobs makes your application faster as it queues jobs that might take a while to execute for later execution.

We have four methods in this class. The first one is the `handle` method. This one is called automatically when the job is executed. In this method, we fetch the prices for the available currencies and then check if the price has changed. If it has, we publish a Pusher Channel event and then check if there are any devices that need to be notified based on the user’s settings. If there are any, we send a push notification to that device.

We have the `triggerPusherUpdate` method which triggers a `CurrencyUpdated` event. We will create this event in the next section. We also have a `triggerPossiblePushNotification` method which gets the list of devices which should be notified of the currency change and then notifies the user using the `CoinPriceChanged` class, which we will create in the next section.

Lastly, we have the `getPricesForSupportedCurrencies` method which just fetches the current price of a currency. In this method, we have a debug mode that simulates the current price of a currency.

To make sure this class we just created is scheduled properly, open the `app/Console/Kernel.php` file and in the `schedule` method, add the following code to the `schedule` method:

`    $schedule->job(<span class="hljs-keyword">new</span> \App\Jobs\CheckPrices)->everyMinute();`Now every time we run the command `php artisan schedule:run` all the jobs in this `schedule` method will be run. Normally, in a production environment, we will need to add the schedule command as a cronjob, however, we will run this command manually.

The next thing to do will be to create the notifiers and events. In your terminal, run the following commands:

```
    $ php artisan make:event CurrencyUpdated
    $ php artisan make:notification CoinPriceChanged

```

This will create a class in the `Events` and `Notifications` directories.

 In the [event](https://laravel.com/docs/5.6/events) class, `CurrencyUpdated` paste the following code:

```
    <span class="hljs-meta"><?php</span>

    <span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Events</span>;

    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Broadcasting</span>\<span class="hljs-title">Channel</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">SerializesModels</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Foundation</span>\<span class="hljs-title">Events</span>\<span class="hljs-title">Dispatchable</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Broadcasting</span>\<span class="hljs-title">InteractsWithSockets</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Contracts</span>\<span class="hljs-title">Broadcasting</span>\<span class="hljs-title">ShouldBroadcast</span>;

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CurrencyUpdated</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ShouldBroadcast</span>
    </span>{
        <span class="hljs-keyword">use</span> <span class="hljs-title">Dispatchable</span>, <span class="hljs-title">InteractsWithSockets</span>, <span class="hljs-title">SerializesModels</span>;

        <span class="hljs-keyword">public</span> $payload;

        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-params">($payload)</span>
        </span>{
            <span class="hljs-keyword">$this</span>->payload = $payload;
        }

        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">broadcastOn</span><span class="hljs-params">()</span>
        </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Channel(<span class="hljs-string">'currency-update'</span>);
        }

        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">broadcastAs</span><span class="hljs-params">()</span>
        </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-string">'currency.updated'</span>;
        }
    }
```

In the event class above, we have the `broadcastOn` method that specifies the Pusher channel we want to broadcast an event on. We also have the `broadcastAs` method which specifies the name of the event we want to broadcast to the channel.

In the `CoinPriceChanged` [notification](https://laravel.com/docs/5.6/notifications) class, replace the contents with the following code:

```
    <span class="hljs-meta"><?php</span>

    <span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Notifications</span>;

    <span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Device</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Bus</span>\<span class="hljs-title">Queueable</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Neo</span>\<span class="hljs-title">PusherBeams</span>\<span class="hljs-title">PusherBeams</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Neo</span>\<span class="hljs-title">PusherBeams</span>\<span class="hljs-title">PusherMessage</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Notifications</span>\<span class="hljs-title">Notification</span>;

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CoinPriceChanged</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Notification</span>
    </span>{
        <span class="hljs-keyword">use</span> <span class="hljs-title">Queueable</span>;

        <span class="hljs-keyword">private</span> $currency;
        <span class="hljs-keyword">private</span> $device;
        <span class="hljs-keyword">private</span> $payload;

        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-params">(string $currency, Device $device, array $payload)</span>
        </span>{
            <span class="hljs-keyword">$this</span>->currency = $currency;
            <span class="hljs-keyword">$this</span>->device = $device;
            <span class="hljs-keyword">$this</span>->payload = $payload;
        }

        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">via</span><span class="hljs-params">($notifiable)</span>
        </span>{
            <span class="hljs-keyword">return</span> [PusherBeams::class];
        }

        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toPushNotification</span><span class="hljs-params">($notifiable)</span>
        </span>{
            $currentPrice = <span class="hljs-keyword">$this</span>->payload[strtoupper(<span class="hljs-keyword">$this</span>->currency)][<span class="hljs-string">'current'</span>];

            $previousPrice = <span class="hljs-keyword">$this</span>->payload[strtoupper(<span class="hljs-keyword">$this</span>->currency)][<span class="hljs-string">'current'</span>];

            $direction = $currentPrice > $previousPrice ? <span class="hljs-string">'climbed'</span> : <span class="hljs-string">'dropped'</span>;

            $currentPriceFormatted = number_format($currentPrice);

            <span class="hljs-keyword">return</span> PusherMessage::create()
                    ->iOS()
                    ->sound(<span class="hljs-string">'success'</span>)
                    ->title(<span class="hljs-string">"Price of {$this->currency} has {$direction}"</span>)
                    ->body(<span class="hljs-string">"The price of {$this->currency} has {$direction} and is now \${$currentPriceFormatted}"</span>);
        }

        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pushNotificationInterest</span><span class="hljs-params">()</span>
        </span>{
            $uuid = strtolower(str_replace(<span class="hljs-string">'-'</span>, <span class="hljs-string">'_'</span>, <span class="hljs-keyword">$this</span>->device->uuid));

            <span class="hljs-keyword">return</span> <span class="hljs-string">"{$uuid}_{$this->currency}_changed"</span>;
        }
    } 
```

In the class above we have the `toPushNotification` class which prepares the push notification using the Pusher Beams library. We also have the `pushNotificationInterest` method which sets the name for the interest of the push notification depending on the currency and device ID.

That’s all for the backend, now just run the command below to start the server:

```
    $ php artisan serve

```

This will start a PHP server with our application running. Also if you need to manually trigger a currency change, run the command below:

```
    $ php artisan schedule:run

```

Now that we are done with the backend, we can create the application using Swift and Xcode.

## Conclusion

In this part of the article, we have created the backend for our cryptocurrency alert application. [In the next part](https://dev.to/neo/create-a-cryptocurrency-tracking-app-with-push-notifications-using-swift-and-laravel---part-2-the-ios-app-251a), we will be seeing how we can create the application that will consume the API we just created in this part.

The source code to this application is available on [GitHub](https://github.com/neoighodaro/cryptocurrency-alert-ios-app).

This post first appeared on the [Pusher blog](https://pusher.com/tutorials/cryptocurrency-tracking-swift-laravel-part-1).