Hubble Public data - TypeScript API

Overview

Hubble Public API

Hubble Public API is a TypeScript API that serves public data of the Hubble Protocol.

Development

Local API Setup

You will need to use npm to install the dependencies. You will also need to install Netlify CLI to run and debug locally.

We are using private nodes without rate limit for fetching mainnet-beta and devnet chain data. You will have to add an .env file in the root of this repository with the correct environment variables inside. Please take a look at the example .env.example file:

cd hubble-public-api
cp .env.example .env
# edit .env with actual endpoints with your favorite editor
# nano .env  
# code .env
# ...

Run the application by launching a Netlify development server:

cd hubble-public-api
npm run netlify

Local DynamoDB Setup

Our scheduled Netlify function snapshot.ts saves metrics to DynamoDB. If you want to test this locally without using actual AWS service you can use docker to run a local DynamoDB instance:

# go to docker folder
cd hubble-public-api/docker

# spin up DynamoDB locally with persistent database data in hubble-public-api/docker/dynamodb/data/shared-local-instance.db
docker-compose up 

# create required tables - this is only required once after first setup, all the data will be persisted on disk
chmod +x create-dynamodb-tables.sh
./create-dynamodb-tables.sh

Local instance will be started on http://localhost:8000.

Before you can invoke the Netlify functions you will also have to add this environment variable to .env file (see .env.example):

DYNAMODB_ENDPOINT=http://localhost:8000

Deployment

Netlify Status

All of the API routes should be added to the src/netlify/functions folder. Deployments are done automatically by using Netlify.

Everything that gets pushed to the master branch will be deployed to the production URL: https://api.hubbleprotocol.io.

Make sure to add environment variables MAINNET_ENDPOINT and DEVNET_ENDPOINT using Netlify site settings UI.

Usage

Metrics

Get mainnet-beta metrics of Hubble Protocol:

GET https://api.hubbleprotocol.io/metrics

You may also specify the environment (mainnet-beta[default],devnet,localnet,testnet) by using an env query parameter:

GET https://api.hubbleprotocol.io/metrics?env=devnet

Metrics History

Get mainnet-beta metrics of Hubble Protocol:

GET https://api.hubbleprotocol.io/history

You may also specify the environment (mainnet-beta[default],devnet,localnet,testnet) by using an env query parameter:

GET https://api.hubbleprotocol.io/history?env=devnet

History endpoint will only return the historical data of the past month by default. If you need more/less data you can also use either the from or/and to query parameters to query by date. Both dates should be specified in their epoch form.

GET https://api.hubbleprotocol.io/history?from=1644414557599&to=1644414562241

Config

Runtime config specifies all of the public configuration used by Hubble (accounts, public keys, program ids...).

Get runtime config of all environments:

GET https://api.hubbleprotocol.io/config

You may also filter by environment (mainnet-beta[default],devnet,localnet,testnet) by using an env query parameter:

GET https://api.hubbleprotocol.io/config?env=devnet
Comments
  • Token metadata api

    Token metadata api

    Add a Fungible token standard endpoint for kTokens.

    Dynamic endpoint which validates the token mint passed is owned by Kamino.

    Reads on-chain metadata to dynamically generate the full token metadata json object.

    image

    image

    opened by elliotkennedy 3
  • Add endpoint for LDO reward eligible loans

    Add endpoint for LDO reward eligible loans

    • added an endpoint that does the calculations to determine which loans are eligible for the LDO rewards that we will be giving away, and returns a list of eligible loans, example response:
    {
        "eligibleLoans": [
            {
                "ldoRewardsEarned": "27.06558034194027710279586166731737367548",
                "userMetadataPubkey": "2aMCQhPcvM5C9eTX2iD1u2iNUdDU16dXgxyQZXiQoKpy",
                "daysEligible": "17"
            },
            {
                "ldoRewardsEarned": "448.4233536817963101223578623444636713705",
                "userMetadataPubkey": "2LBP1xjVcysoUXb99wdCbfTnA38iZ3ekY84NARvyFuhT",
                "daysEligible": "16"
            },
            {
                "ldoRewardsEarned": "14.26436918836496209361642456442660622802",
                "userMetadataPubkey": "FfynUA4N151HqZgiLe9euudgvFWZjndVYNVewMqZs4Sk",
                "daysEligible": "13"
            },
            {
                "ldoRewardsEarned": "4.10275919626439795178511491454672903063",
                "userMetadataPubkey": "B9XrBCPZxfva4soDPaUvffA59JDbtgeLGm5PvZA3eFNp",
                "daysEligible": "9"
            },
            {
                "ldoRewardsEarned": "4.760791725679126968189205379408029488192",
                "userMetadataPubkey": "7Feh1hRUwEwLLvCaFEzCXvy4LmAhTTDPQANVmC31BSCc",
                "daysEligible": "5"
            },
            {
                "ldoRewardsEarned": "9.408608130397856523428089231866073023064",
                "userMetadataPubkey": "2V58aFRBFyZtL722W6hDmZymby1CKj8DsAaHzFzrP7sK",
                "daysEligible": "4"
            },
            {
                "ldoRewardsEarned": "0.0003800870102556819328980033003807004054725",
                "userMetadataPubkey": "6ENGCRU8r18veWmTfL5pqyJ4pKKMrYmRwqv3wtPkGWyF",
                "daysEligible": "2"
            },
            {
                "ldoRewardsEarned": "0.000253391340170454621932002200253800270315",
                "userMetadataPubkey": "8YnYGFRBwvKxLDZ8zeiu3xAYHyvGX7ACcfkqPdst3Coz",
                "daysEligible": "2"
            },
            {
                "ldoRewardsEarned": "0.000253391340170454621932002200253800270315",
                "userMetadataPubkey": "GstvpDqjphN4h5D5VjYCMuPquqFaGF5A3Wzgk8qSau3r",
                "daysEligible": "2"
            },
            {
                "ldoRewardsEarned": "0.02275422751217285831616286027562521250584",
                "userMetadataPubkey": "8G2RTvrBZagG1aiHYo9p7y2oPT3ZydyiJ5dPybReLZko",
                "daysEligible": "1"
            },
            {
                "ldoRewardsEarned": "0.0001266867962706027747126839693115445704858",
                "userMetadataPubkey": "C34T6g9QwWWRnAGxbr4r51PDTvnHzNW3ZTJJo6vfakd1",
                "daysEligible": "1"
            },
            {
                "ldoRewardsEarned": "0.0001900301944059041620690259539673168557287",
                "userMetadataPubkey": "EjN1CptG8JzNhXzqZj7wzmNbmhpCgsskoXw5gn4TY2tM",
                "daysEligible": "1"
            }
        ]
    }
    
    • can specify a start/end date for the endpoint, e.g.: http://localhost:8888/staking/lido/eligible-loans?env=devnet&start=2022-06-01&end=2022-07-01 (start=inclusive, end=exclusive)
    • I decided to use a PostgreSQL function instead of using the knex ORM for this as it would be way too hard to understand/read, it's already a pretty wild query as it is
    • a loan is eligible for LDO rewards if it has:
      • at least 40% LTV during the entire time period you specified
      • at least 40% of the total collateral value is in STSOL or wstETH
      • the LTV and total collateral values use daily average value image
    opened by peroxy 2
  • Add list of wallets eligible for rewards

    Add list of wallets eligible for rewards

    Get a list of wallets that are eligible for strategy rewards on an hourly basis.

    Example request:

    AUTH=$(echo -ne "hubble:development" | base64 --wrap 0)
    curl --location --request POST 'localhost:8888/strategies/Cfuy5T6osdazUeLego5LFycBQebm9PP3H7VNdCndXXEN/rewards/eligible-shareholders' \
    --header 'Authorization: Basic $AUTH' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "startDate": "2020-01-01",
        "endDate": "2023-01-01",
        "rewardsPerHour": 100
    }'
    

    Example response:

    [
        {
            "hoursEligible": "3",
            "rewardsEarned": "0.6920133828985366495754907778709581302102",
            "ownerPubkey": "28Lv4bK1HzRBfzCPBoqYrsfM8UZhCdi7zPRHKs45ct7Z"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "14.67151819468679565449829183047105417672",
            "ownerPubkey": "4CRGrqi53CMQazYs2bZrgKvdfaMqTHXngjbby6QGMEdv"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "2.10781027876931696661140125613317233652",
            "ownerPubkey": "4iSRTaE8SmpaCUwHnTVkDBpFGaqVJJXtbBvijRdFapgq"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "1.651561718746190796557704461581694199193",
            "ownerPubkey": "5FF7oHV9fEkxdiHFsW7iGCewxsxBTjyeDRw7jpuUqCs1"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "1.5289899029648308223676575045726519328",
            "ownerPubkey": "5VG4J3QqLFcNV3V3tngduK71YU1o1HzA8AWZ6EAM9R2S"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "0.6019728353399104176068243781713969993244",
            "ownerPubkey": "7U1KsPGqNXYyHfD5qATHf9HwoGTUTwepSLWGcK7DuLxS"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "0.7959603756334293807045168509902168860761",
            "ownerPubkey": "7zqdN3cHqaBcTqs8hKR161HchtHkVHCvaMgBt4nrBNJd"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "0.5084591073254491241065462848373859950986",
            "ownerPubkey": "8npk5rpnndz3o2xu7Mzr3AzToCbcaXBv81SJq43NGQ7Y"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "0.00322882001716595281145829508101934442146",
            "ownerPubkey": "8tz9KYmEjhNxqagvJcn3F3vdM3soDL3F8C6tqeXQcCPp"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "16.56663366480422977741850826050680409527",
            "ownerPubkey": "93MxqvDvCdzQts1QpkAWPBj745rAVXqfAEyU5JvvtAj8"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "1.496720168908015555891348940694211033629",
            "ownerPubkey": "99EYUt3BYAXoLdsF1ZmgGNGiQJktfs9TFGvXjQ6XWhST"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "0.1540366899162579769334231721177979784293",
            "ownerPubkey": "9qeNMDH5PfJyC3wuaPwi1Jao2xH3Hhva2UkqrA1r7bqH"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "125.2240394414391017108542651903710335685",
            "ownerPubkey": "9xU7i4H3pY8LZkwspeLVNaQuL8PsAvyjpex1fnr28KxH"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "29.23267057030994915837691238972406812987",
            "ownerPubkey": "AGbz8HA7mTmDpfvrNFgRMcwtieN7t34FdStSBK6EvGtL"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "4.491901379864342628263182910009517441316",
            "ownerPubkey": "AzzTqxHhkKuRRmg6S9mjcK5R8SdeEnQoMSuNHdSVeZoG"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "0.000001794314870121125984669433309939679526021",
            "ownerPubkey": "BabJ4KTDUDqaBRWLFza3Ek3zEcjXaPDmeRGRwusQyLPS"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "5.208995792195113857381749039118748623113",
            "ownerPubkey": "D2X1i4YYELaAtM5XTRmSzs7cYzcAGEvHnHvChZtnhVFu"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "9.021709440647101432745778828682330519303",
            "ownerPubkey": "Dsr1eVDz7Jr93nNtmroSZjMNLeNzx9p9QN8ZM2dBggV2"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "60.04566876039430101157851282715459162389",
            "ownerPubkey": "EXQRUQFhAcMq8j6jJqJag7jSNRvLCkXjgTe8KAX3htCE"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "1.501643630656210797332318222825777210688",
            "ownerPubkey": "EkaNLzCbJpBWfkgu3q8uWuMJhfnnjXKzbed69LapSQeG"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "0.2994765888677721230170508097218264507158",
            "ownerPubkey": "EqRCPNx2uC5kvUngK3jXe1ncXoyCHj9D3KEnPYoJhWST"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "8.874742564713351477116484063889053346744",
            "ownerPubkey": "FJyrEGUbqLtNUdUYHS8KmtDnJAu18aYQL41W34tjz9Bw"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "0.008649451250906966944230028887343129467826",
            "ownerPubkey": "GkeDRfHcACap2CM9oaWrb3QUMG7pk6F6EMYca8Lu52t8"
        },
        {
            "hoursEligible": "3",
            "rewardsEarned": "15.29662102606239954932814755661922644976",
            "ownerPubkey": "J3o4j8vp4Ju1xdTWMMpBudSZUb48i8kkN2uLrTLhA7fD"
        },
        {
            "hoursEligible": "2",
            "rewardsEarned": "0.01996556016302472543496114497441574309743",
            "ownerPubkey": "GCtZ3UeX91ekKVUBq3UiC5LnXh2HjqBiryAUUPe6qLW1"
        }
    ]
    
    opened by peroxy 1
  • Update @hubbleprotocol/hubble-config and remove config files

    Update @hubbleprotocol/hubble-config and remove config files

    Update to latest version of @hubbleprotocol/hubble-config npm package and remove the src/models/*config.ts files that are not needed anymore and fix everything.

    enhancement 
    opened by peroxy 1
  • Add historical data to API

    Add historical data to API

    A lot of changes in this PR:

    • Split history data from the /metrics endpoint and move it to the dedicated /history endpoint. Since /metrics endpoint is called very frequently (every 5s in webapp) and contains live data I've decided to split it up since history will not have to be fetched as often as that and would be better suited to be cached on the client side. We only fetch history once every hour, so we can just invalidate the cache hourly on the client side.
    • As mentioned, history is fetched once every hour by the snapshot.ts Netlify scheduled function and saved to the AWS DynamoDB metrics table.
    • To avoid wasting our production AWS resources when testing locally I've set up a simple docker-compose configuration that let's the developer run a DynamoDB instance locally. The metrics table can be created by the helper script create-dynamodb-tables.sh (this can be run only once per machine, the DynamoDB tables and data will stay on the host machine by using docker volumes).

    Closes #2

    enhancement 
    opened by peroxy 1
  • Add memcmp filter for getUserVaults() in BorrowingClient

    Add memcmp filter for getUserVaults() in BorrowingClient

    This should be fixed to be more efficient and use memcmp filter (in BorrowingClient.ts):

      async getUserVaults() {
        //TODO: use memcmp filter and return the userdata we need, not everything like right now
        return (await this._client.account.userMetadata.all())
          .map((x) => x.account as UserMetadata)
          .filter((x) => {
            return x.borrowingMarketState.toString() === this._config.borrowing.accounts.borrowingMarketState.toString();
          });
      }
    
    enhancement 
    opened by peroxy 1
Releases(hubble-public-api/1.0.0)
🚌 A Node.js API to access public transport information in Lisbon using data provided by Carris Metropolitana

?? Carris Metropolitana API A Node.js REST API built to easily access and search public transport information in Lisbon using data provided by Carris

Márcia Martins 4 Jun 21, 2022
This project is built with JavaScript, Webpack, HTML & CSS, Leaderboard api. When user clicks on Refresh button it hits the api and responds with the data, The user can also post data to the api

leaderboad Description the project. this project is about the leaderboad i did during Microverse to build a website for adding Data to the API and fet

Emmanuel Moombe 4 May 30, 2022
Fun way to share some of your (already) public StackOverflow user data to the internet.

ProfileOverflow A simple app leveraging StackExchange APIs to show some StackOverflow accounts information. Made for fun during a weekend as practice.

Jacky Efendi 5 Sep 14, 2022
A small utility server to exchange data and messages between clients. Comes complete with E2E public key encryption

Zenotta Intercom A small utility server to exchange arbitrary data between clients. Comes complete with E2E public key encryption Official documentati

Zenotta AG 7 Oct 2, 2022
Authentication module for Guild.xyz Public API

Guild SDK for TypeScript | WIP Application • ę Twitter • Docs • Community Roadmap • Github • Summary The Guild SDK library is a Typescript library for

Agora.xyz 37 Dec 21, 2022
A wrapper client for Strike's public API.

node-strike A wrapper client for Strike's public API. Usage Import the wrapper and instantiate a client. import { NodeStrike } from 'node-strike'; //

hodlone 5 Apr 28, 2022
🍺 A public REST API for retrieving information about Systembolaget's products, and which products that are available in which store

?? systembolaget-api A public REST API for retrieving information about Systembolaget's products, and which products that are available in which store

Daniel Cronqvist 9 Nov 22, 2022
A simple Node.js code to get unlimited instagram public pictures by every user without api, without credentials.

Instagram Without APIs Instagram Scraping in August 2022, no credentials required This is a Node.js library, are you looking for the same in PHP? go t

Francesco Orsi 28 Dec 29, 2022
Type safe library for interacting with Mindbody's Public API (v6) and Webhooks

Mindbody API Type safe library for interacting with Mindbody's Public API (v6) and Webhooks ⚠️ Read before installing This library is typed according

SplitPass 4 Dec 9, 2022
JSON Visio is data visualization tool for your json data which seamlessly illustrates your data on graphs without having to restructure anything, paste directly or import file.

JSON Visio is data visualization tool for your json data which seamlessly illustrates your data on graphs without having to restructure anything, paste directly or import file.

Aykut Saraç 20.6k Jan 4, 2023
It shows an effective way to correct bus arrival information using data analytics based on Amazon Serverless such as Kiness Data Stream, Kinesis Data Firehose, S3, and Lambda.

Amazon Serverless를 이용한 실시간 버스 정보 수집 및 저장 본 github repository는 버스 정보를 주기적으로 수집하여 분석할 수 있도록, Amazon Serverless인 Amazon Kinesis Data Stream, Kinesis Data

John Park 4 Nov 13, 2022
A table component for your Mantine data-rich applications, supporting asynchronous data loading, column sorting, custom cell data rendering, row context menus, dark theme, and more.

Mantine DataTable A "dark-theme aware" table component for your Mantine UI data-rich applications, featuring asynchronous data loading support, pagina

Ionut-Cristian Florescu 331 Jan 4, 2023
科技风智慧城市 Demo: http://stonerao.com/public/city/

Three.js Setup Download Node.js. Run this followed commands: # Install dependencies (only the first time) npm install # Run the local server at local

rao_yan 120 Dec 2, 2022
Components and tools for building DeFi dapps on Solana + Anchor. Public domain license.

Solana DeFi Framework Components and tools for building DeFi dapps on Solana + Anchor. Public domain license. Status Pre-pre-pre-alpha. Contributing A

null 4 Mar 28, 2022
A yearly review of your public GitHub repository stats.

Repos Wrapped A yearly review of your public GitHub repository stats. View your stats Endpoints require trailing slashes Append your GitHub username t

Stephanie Eckles 10 Jul 29, 2022
Search your code and 2M+ public repositories on Sourcegraph directly within Raycast.

Sourcegraph for Raycast Search your code and 2M+ public repositories on Sourcegraph directly within Raycast. Install · Setup · Commands · Issues · Cha

Robert Lin 5 Jul 10, 2022
Allows the public to easily report and track the geolocation of anyone or anything they spot outside, using a mobile app or web frontend.

LIVE DEMO: https://armytracker.com/ (tracking the invading Russian army in Ukraine) Attention: - If you'd like to help the project either as a program

Michal Certicky 9 Mar 27, 2022
🪐 The IPFS gateway for NFT.Storage is not "another gateway", but a caching layer for NFTs that sits on top of existing IPFS public gateways.

nftstorage.link The IPFS gateway for nft.storage is not "another gateway", but a caching layer for NFT’s that sits on top of existing IPFS public gate

NFT.Storage 37 Dec 19, 2022