Solutions Guide: How To Deploy Hatchfi Using Firebase's Serverless Framework

Solutions Guide: How To Deploy Hatchfi Using Firebase's Serverless Framework

Summary

This guide will help you set up and deploy a headless version of Hatchfi's API using Firebase's serverless framework. Headless means without our Link UI for those interested in building their own UI experience for connecting their users' crypto wallets and accounts.  

By the end of this guide, you’ll have completed the following:

  • Setup a Firebase function
  • Authenticate via a Token
  • Connect a user's crypto wallet or account
  • Query your user's wallet or account data from the Hatchfi database via our API
  • Deploy a serverless function of Hatchfi for you to start using in your production applications

Getting Started

You’ll need a few things to get started with Hatchfi and Firebase. For more info on the following, please visit our documentation:

  • Hatchfi Credentials
  • Client Id
  • API Key
  • Secret Key
  • Firebase
  • Spark, a free version, is fine for a simple use case
  • Functions, which are super easy to set up

Setting up Firebase Serverless Functions

Once you’ve created your Firebase project and installed everything you need to run functions locally, we need to spin up an express server inside our cloud functions to make things a little easier. There are a few plus sides to doing this, and Firebase recommends it for our use case. We also get to avoid CORS.

const functions = require("firebase-functions");
const axios = require("axios");
const express = require("express");
const cors = require("cors");
const app = express();

app.use(cors({ origin: true }));
exports.api = functions.https.onRequest(app);

Now that you’ve got this setup, we can serve the api inside an emulator, allowing us to make real-time changes.

firebase serve --only functions

If you’re on a new Mac, Monterey OS, you’ll need to adjust the port that firebase serves. You can do this by adding -p 5001 to the end of the command above. It’d look like this: firebase serve --only functions -p 5001

Endpoints

Now that the emulator is serving your API, we can start testing out Hatchfi’s endpoints.

Authentication

You will require authentication for both Frontend and Backend use cases. For example, if you’d like to use Hatchfi Link, you’ll be required to return a token to the frontend from your server. If you’re not using Link, you’ll still need to use a token to authorize creating a connection to a provider.

// This goes below the export in the previous snippet.

// This example assumes you're calling this method from the frontend,
// if you aren't you can pass the userID in from whatever way you'd like.
app.post("/auth", async (req, res) => {
  const options = {
    method: "POST",
    url: "<https://devapi.hatchfi.co/v1/auth/login>",
    headers: {
      "X-Hatchfi-Api": "API-KEY-HERE",
      "X-Hatchfi-Secret": "SECRET-KEY-HERE",
      "X-Hatchfi-User-Id": req.body.userId,
      "Content-Type": "application/json",
    },
  };

  axios
    .request(options)
    .then(function (response) {
      res.send(response.data);
    })
    .catch(function (error) {
      console.error(error);
      res.send(error.message);
    });
});

// Returns this object
{
	"userId": "hatchfidevtest111",
	"token": "eyJhb...KyTaylBn8"
}

Connecting a user crypto account  

Connecting an account without Hatchfi Link is pretty simple. In the case below, we assume we’re going to pass an address provider type, in a real-world scenario, you’d have a switch or some other if/else catch for the different auth types (token, passPhrase, oauth)

app.post("/connect", async (req, res) => {
  let selectedProvider = req.body.provider;
  let address = req.body.address;
  let userToken = req.body.token;

  const options = {
    method: "POST",
    url: `https://devapi.hatchfi.co/v1/link/${selectedProvider}`,
    headers: {
      "X-Hatchfi-Token": userToken,
      "Content-Type": "application/json",
    },
    data: { address: address },
  };

  axios
    .request(options)
    .then(function (response) {
      res.send(response.data);
    })
    .catch(function (error) {
      res.send(error);
    });
});

// On success, this returns this object
{
	"status": "success",
	"accountId": "8efd9a54-3bd2-4baa-a178-a35e3bd929f5",
	"balances": {
		"status": "success"
	},
	"transactions": {
		"status": "success"
	}
}

Here’s how we call this method from our REST tool, Insomnia; you’ll notice that we’re calling the /api/connect an endpoint that we defined above:

curl --request POST \\
  --url <http://localhost:5000/hatchfi/us-central1/api/connect> \\
  --header 'Content-Type: application/json' \\
  --data '{
	"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJoYXRjaGZpZGV2dGVzdDExMSIsImlhdCI6MTY1NCwiZXhwIjoxNjU0MzYxOTY0fQ.yL-XDFBg-9G0ci9QlfbazkTrBFQ8J9L3s2fGpyB-728",
	"address": "0x416a3bf5227b35985d975386215a47ca67f21dc9",
	"provider": "ethereum"
}'

Querying all accounts

Querying all accounts is great for general purposes, like displaying or running the data through a verifier/checker algorithm. With Hatchfi, it’s easy to query accounts and connections.

app.post("/all-accounts", async (req, res) => {
  const options = {
    method: "GET",
    url: "<https://devapi.hatchfi.co/v1/accounts/>",
    headers: {
      "X-Hatchfi-Api": "API-KEY-HERE",
      "X-Hatchfi-Secret": "SECRET-KEY-HERE",
      "X-Hatchfi-User-Id": req.body.userId,
      "Content-Type": "application/json",
    },
  };

  axios
    .request(options)
    .then(function (response) {
      res.send(response.data);
    })
    .catch(function (error) {
      res.send(error);
    });
});

// The response is an array, with rather large objects in them:
[
	{
		"balances": [
			{
				"ticker": "ETH",
				"providerTicker": "ETH",
				"name": "Ethereum",
				"fiatTicker": "USD",
				"fiatValue": "1,018.303",
				"logo": null,
				"resourceType": null,
				"misc": [],
				"assetType": "ERC20",
				"amount": "0.5723749005119304",
				"decimals": 18
			},
			...
		],
		"blockchain": "ethereum",
		"resourceType": "account",
		"address": "0x416a3bf5227b35985d975386215a47ca67f21dc9",
		"ticker": "ETH",
		"id": "c512eeec-4482-438a-9859-ceddf72bcd49",
		"provider": "ethereum"
	},
...
]

Query a specific account

Querying a specific account is best for situations where you want to showcase a single account without needing all of the users' accounts. It’s almost identical to the call above. We need to include the accounts id

app.post("/specific-account", async (req, res) => {
  const options = {
    method: "GET",
    url: `https://devapi.hatchfi.co/v1/accounts/${req.body.accountId}`,
    headers: {
      "X-Hatchfi-Api": "API-KEY-HERE",
      "X-Hatchfi-Secret": "SECRET-KEY-HERE",
      "X-Hatchfi-User-Id": req.body.userId,
    },
  };

  axios
    .request(options)
    .then(function (response) {
      res.send(response.data);
    })
    .catch(function (error) {
      res.send(error);
    });
});

// You'll receive an object:
{
		"balances": [
			{
				"ticker": "ETH",
				"providerTicker": "ETH",
				"name": "Ethereum",
				"fiatTicker": "USD",
				"fiatValue": "1,018.303",
				"logo": null,
				"resourceType": null,
				"misc": [],
				"assetType": "ERC20",
				"amount": "0.5723749005119304",
				"decimals": 18
			},
			...
		],
		"blockchain": "ethereum",
		"resourceType": "account",
		"address": "0x416a3bf5227b35985d975386215a47ca67f21dc9",
		"ticker": "ETH",
		"id": "c512eeec-4482-438a-9859-ceddf72bcd49",
		"provider": "ethereum"
	}

Querying an account's transactions

When connecting an account, we query back as many transactions as we can - up to 10,000 at the moment. Querying them is as easy as adding /transactions to the end of the account API call.

app.post("/account-txns", async (req, res) => {
  const options = {
    method: "GET",
    url: `https://devapi.hatchfi.co/v1/accounts/${req.body.accountId}/transactions`,
    headers: {
      "X-Hatchfi-Api": "API-KEY-HERE",
      "X-Hatchfi-Secret": "SECRET-KEY-HERE",
      "X-Hatchfi-User-Id": req.body.userId,
    },
  };

  axios
    .request(options)
    .then(function (response) {
      res.send(response.data);
    })
    .catch(function (error) {
      res.send(error);
    });
});

// You'll receive an array of objects
[
	{
		"parts": [
			{
				"amount": "0.109",
				"direction": "sent",
				"fiatTicker": null,
				"fiatValue": null,
				"otherParties": [
					"0x7f268357a8c2552623316e2562d90e642bb538e5"
				],
				"providerTicker": "ETH",
				"ticker": "ETH",
				"resourceType": "part"
			}
		],
		"fees": [
			{
				"fiatTicker": null,
				"fiatValue": null,
				"resourceType": "fee",
				"type": "network",
				"ticker": "ETH",
				"providerTicker": "ETH",
				"amount": "0.004716167321969895"
			}
		],
		"misc": [],
		"fiatCalculatedAt": null,
		"resourceType": "transaction",
		"_id": "629b7389ecbe560016cf6c3b",
		"txId": "0xbb36e2ea69e12d037825328c347ba284408a6d51d1d4c9625ec9b87446505160",
		"accountId": "9da95808-79b3-4451-bce1-8a2bac92d8ea",
		"userId": "hatchfidevtest111",
		"status": "1",
		"transactionType": "other",
		"initiatedAt": 1654328380,
		"confirmedAt": 1654328380
	},
...
]

Conclusion

In this guide, you should have successfully set up and deployed Hatchfi on a serverless function on Firebase.  This guide specifically walks through setting Hatchfi up without our Hatchfi Link UI which allows product builders and developers to build their own account connection UI on top of Hatchfi's APIs for their own custom look.

Building crypto-powered financial products and want to share with us? We'd love to hear from you! Hit us up on Discord or reach out via email at contact@hatchfi.co.


About Hatchfi

Hatchfi is an API to connect your app to your users' cryptocurrency financial accounts with just a few lines of code.

Get started for free with up to 100 live connections here.

Hatchfi Discord Blog Docs Crunchbase