Giter Club home page Giter Club logo

dai-apy-tracker's Introduction

DAI APY Tracker

This is a simple containerised full-stack application to comparing historical DAI interest rates across several on-chain protocols.

The current protocols supported are:

  • Compound Finance
  • Aave

The app is designed to scale in two respects:

  • a large number of users
  • a growing amount of data stored over time

Installation

Clone the repo and do make install. Then do make run and open localhost:3000 in your browser.

Architecture

The app is containerised using Docker Compose. It provisions a Redis server, a Postgres database, and a web service.

The web services consists of a React front-end (in src/client) and a back-end server (src/server). The server is responsible for

  • serving the React front-end
  • serving some API functions for the front-end to consume
  • running a worker to check for the latest rates periodically

The database uses TimescaleDB, which is a Postgres extensions designed to make reading and writing time series data simple and crazy performant at high scales.

Most of the code is well-modularised into different components in src/lib:

  • cache provides an interface to the Redis server.
  • db provides an interface to the Postgres server.
  • crypto provides an interface to data on the blockchain.
  • misc provides some small utilities.

None of these components depend on each other.

Scalability

The app was designed for massive scalability in terms of two things:

  • a large number of users
  • a growing amount of data stored over time

As such, I minimised the data transfer, disk storage, compute, and memory, requirements to as asymptotically small as possible.

Data transfer is linear with respect number of users, thanks to caching and using the client to update in real-time instead of pushing real-time updates from the server. Data transfer is also minimised by downsampling historical data to only a 5-minute resolution.

Memory usage is mainly composed of the in-memory Redis cache and is reduced through downsampling the cached historical data.

Compute is also minimised thanks to heavy caching, only needing to query the most recent rates every 10 minutes or so using TimescaleDB’s performant writes and queries, and the historical rates only every day.

Data storage is minimised by compressing of data older than a year using TimescaleDB. It can be distributed across disks transparently too.

Infrastructure cost on something like AWS could cut to small fraction by using spot instances, as no requests need to served synchronously that are not cached, and operations run quickly and idempotently.

Design decisions

I decided to make the server periodically check the chain for updates, instead of clients checking and posting the results to the server, as the latter would be a security threat: clients could post fake data.

However, the clients do check for updates on their own too. The client only gets an initial load of recent data before then periodically checking for real time data. This dramatically lessens the data transfer load on the server because the server doesn’t have to push real-time data to clients.

I decided to make two API endpoints: /recents and /historical. The client first sees the data returned by /recents. It contains a week of data and is refreshed quickly, every 10 minutes. The data catches up to real-time almost instantly on the client side and continues to update.

If the user wishes, they can click a button to load data from the /historical endpoint, which loads in all the data the server has stored. This endpoint might end up serving a lot more data, but is cached, and only updates every day, making this efficient.

If we only had one end-point, then we could not cache efficiently. We don’t want the recents data getting too old, so we’d have to update it every 10 minutes or less, but dragging in all of the historical data would be expensive. Thus, splitting into two endpoints greatly improves scalability.

As it is, the server only has to expose two easily-cacheable endpoints: /recents and /historical. The CDN can take the brunt of user requests; the server only has to be checked every 10 minutes for the /recents data and every day for the /historical data.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.