Building a Crypto Price Tracker with Flutter
Tags: flutter, dart, mobile, codenjobs
Published: 2022-10-30 16:33:58

<h2><strong> Introduction</strong></h2>
In this article, we will be building a crypto currency price tracker using flutter and Coingecko API. Flutter is google UI framework used to develop beautiful and high performance app.

<br>

*Note: There are tons of other API similar to coingecko with similar JSON format such as coinmarket cap api, nomics api etc. I selected coingecko API because it does not require an API key so we can just dive straight into building our application.*

<p align = "center">
<img src= "https://raw.githubusercontent.com/Obikwelu/mediafile/main/blog%20media/tracker.jpg" width ="300" height="300"  />
</p>
<h2><strong>Building the app</strong></h2>

1.  I will name the app `price_tracker`

```cmd
flutter create price_tracker
```
2. Using JSON fomatter to fomat the api data, this is the forrmat of the http response we get from [Coingecko api](https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false). This will enable us understand the data and decide how to consume the API

```json
  {
    "id": "bitcoin",
    "symbol": "btc",
    "name": "Bitcoin",
    "image": "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579",
    "current_price": 20745,
    "market_cap": 398249682812,
    "market_cap_rank": 1,
    "fully_diluted_valuation": 435734103282,
    "total_volume": 28619200860,
    "high_24h": 20939,
    "low_24h": 20662,
    "price_change_24h": -9.171288688139612,
    "price_change_percentage_24h": -0.04419,
    "market_cap_change_24h": 605958922,
    "market_cap_change_percentage_24h": 0.15239,
    "circulating_supply": 19193456,
    "total_supply": 21000000,
    "max_supply": 21000000,
    "ath": 69045,
    "ath_change_percentage": -69.94973,
    "ath_date": "2021-11-10T14:24:11.849Z",
    "atl": 67.81,
    "atl_change_percentage": 30497.91006,
    "atl_date": "2013-07-06T00:00:00.000Z",
    "roi": null,
    "last_updated": "2022-10-30T12:11:45.415Z"
  }
```

3. Then create a model class `(CryptoTracker)` for JSON deserialization of the http response body. *Note use the `num` datatype for the currentPrice, marketCap and totalVolume because the values could be either int or double at any time.* 
Theen create an empty list (cryptoList) which after decoding the response from our request, will pass the necessary data into the list.

```dart

import 'dart:convert';

List<dynamic> cryptoTrackerFromJson(String str) => List<CryptoTracker>.from(
    json.decode(str).map((x) => CryptoTracker.fromJson(x)));
var cryptoList = [];

class CryptoTracker {
  CryptoTracker({
    required this.id,
    required this.symbol,
    required this.name,
    required this.image,
    required this.currentPrice,
    required this.marketCap,
  });

  String id;
  String symbol;
  String name;
  String image;
  num currentPrice;
  num marketCap;

  factory CryptoTracker.fromJson(Map<String, dynamic> json) => CryptoTracker(
        id: json["id"],
        symbol: json["symbol"],
        name: json["name"],
        image: json["image"],
        currentPrice: json["current_price"],
        marketCap: json["market_cap"],
      );
}

```

4. Create the homepage and write the API services function (`trackerData()`). Then pass the response to the cryptoList (we created this previously in our model file). 

```dart
 Future<List<dynamic>?> trackerData() async {
    String apiEndpoint =
        "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false";
    var url = Uri.parse(apiEndpoint);
    var response = await http.get(url);
    if (response.statusCode == 200) {
      var res = response.body;
      cryptoList = cryptoTrackerFromJson(res);
      setState(() {
        cryptoList;
      });
      return cryptoList;
    } else {
      return null;
    }
  }

```

5. In the initState pass the trackerData()to make sure the function is initialised when the homepage is opened. Also add a Timer to run the function after 4 seconds; this is to get the updated JSON response from the Coingecko API automatically without refreshing the application.

```dart

  void initState() {
    trackerData();
    Timer.periodic(const Duration(seconds: 4), (timer) => trackerData());

    super.initState();
  }
```

6. Then create the rest of the body and add a refresh indicator to be able  to refresh the app.

```dart
 @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("Crypto Price Tracker"),
          centerTitle: true,
          backgroundColor: Colors.black,
          elevation: 0.0,
          leading: const Icon(Icons.monetization_on_outlined),
        ),
        body: RefreshIndicator(
          onRefresh: trackerData,
          child: ListView.builder(
            itemCount: cryptoList.length,
            itemBuilder: (context, index) {
              if (cryptoList.isNotEmpty) {
                var snap = cryptoList[index];
                return CryptoCard(
                  name: snap.name,
                  symbol: snap.symbol,
                  image: snap.image,
                  currentPrice: snap.currentPrice.toDouble(),
                  marketCap: snap.marketCap.toDouble(),
                );
              } else {
                return const Center(
                  child: Text('Check your network,\n Pull to refresh'),
                );
              }
            },
          ),
        ));

```
7. Then create a custom crypto card widget which we pass into our home page to display the data recieved from the API.

```dart
import 'package:flutter/material.dart';

class CryptoCard extends StatelessWidget {
  CryptoCard({
    Key? key,
    required this.name,
    required this.symbol,
    required this.image,
    required this.currentPrice,
    required this.marketCap,
  }) : super(key: key);

  String name;
  String symbol;
  String image;
  double currentPrice;
  double marketCap;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 15, left: 10, right: 10),
      child: Container(
        decoration: BoxDecoration(
          color: Colors.grey,
          borderRadius: BorderRadius.circular(20),
        ),
        child: Column(
          mainAxisSize: MainAxisSize.max,
          children: [
            Row(
              children: [
                Padding(
                  padding: const EdgeInsets.all(15.0),
                  child: Container(
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(20),
                      //
                    ),
                    height: 60,
                    width: 60,
                    child: Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Image.network(image),
                    ),
                  ),
                ),
                Expanded(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      FittedBox(
                        fit: BoxFit.scaleDown,
                        child: Text(
                          name,
                          style: TextStyle(
                            color: Colors.grey[900],
                            fontSize: 25,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ),
                      Text(
                        symbol,
                        style: TextStyle(
                          color: Colors.grey[900],
                          fontSize: 20,
                        ),
                      ),
                    ],
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(15.0),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      Text(
                        "\$${currentPrice.toDouble().toString()}",
                        style: TextStyle(
                          color: Colors.grey[900],
                          fontSize: 20,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                const Text(
                  "Market Cap: ",
                  style: TextStyle(
                    color: Colors.black54,
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                Text(
                  "\$${marketCap.toDouble().toString()}",
                  style: const TextStyle(
                    color: Colors.white,
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ],
            )
          ],
        ),
      ),
    );
  }
}

```

Voila we have our crypto price tracker ready. 

<p align = "center">
<img src= "https://raw.githubusercontent.com/Obikwelu/mediafile/main/blog%20media/Price%20tracker.gif" />
</p>

*Final note: The data returned by the API is bulky but we picked the ones we will be working with and built a model to assist in consuming only the data we require. If you are building a production ready application, consider using an API that will return data at a faster rate as the API we consumed updated price and other data at a much slower rate.*

Download code:
[GitHub Link](https://github.com/codenjobs/Blogs/tree/main/Francis/price_tracker)

[Link to original article at CodenJobs](https://www.codenjobs.com/blog?&title=Building-a-Crypto-Price-Tracker-with-Flutter&id=6b632988-bd80-4052-90b5-7f6015e51ea2)

To know more about codenjobs click [CodenJobs]((https://www.codenjobs.com)


```
Want to Connect?

This article is also published at codenjobs.com .
```