npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@duality-labs/duality-front-end-sdk

v0.1.4

Published

Component hooks and tools to interact with the Duality Dex chain and indexer for front ends

Downloads

5

Readme

Duality Front End SDK

A collection of useful component hooks and tools to interact with the Duality Dex chain and indexer for front ends.

Get Started

npm install @duality-labs/duality-front-end-sdk

Using indexer data

See also:

  • https://github.com/duality-labs/hapi-indexer
  • https://hadron.notion.site/Indexer-API-a2eabb732292453196332cb2727e53f7

Subscribing to indexer data updates may seem complicated at first, given that the event stream returns partial updates and these updates need to be accumulated into a usable data state. The exposed classes here should help:

  • IndexerStream<DataRow>
  • IndexerStreamAccumulateSingleDataSet<DataRow, DataSet>
  • IndexerStreamAccumulateDualDataSet<DataRow, DataSet>
  • where DataRow is a TypeScript interface of an endpoint's row data shape
  • where DataSet is a Map type defining data accumulation from rows into a map

A set of abstracted functions for higher level usage includes functions that mimic fetch behavior, awaiting for all requested data before resolving:

  • fetchSingleDataSetFromIndexer<DataRow>
  • fetchDualDataSetFromIndexer<DataRow>

And React hook implementations to track a cumulative data state with each update

  • useIndexerStreamOfSingleDataSet<DataRow>
  • useIndexerStreamOfDualDataSet<DataRow>

Indexer usage Examples

This allows an abstraction of examples such as the following

A simple fetch replacement, including abortController option:

import { fetchSingleDataSetFromIndexer } from '@duality-labs/duality-front-end-sdk';

type TimeSeriesRow = [unixTime: number, values: number[]];
type TimeSeriesDataSet = Map<TimeSeriesRow['0'], TimeSeriesRow['1']>

async function getSortedTimeseries(url: string): Promise<TimeSeriesRow[]> {
  const data: TimeSeriesDataSet =
    await fetchSingleDataSetFromIndexer<TimeSeriesRow>(url);
  return Array.from(data)
    // sort by index (chronological timestamp)
    .sort(([a], [b]) => a - b);
}

or using an AbortController in a bad practice React useEffect fetch (demonstrating cleanup)

import { fetchSingleDataSetFromIndexer } from '@duality-labs/duality-front-end-sdk';

useEffect(() => {
  const abortController = new AbortController();
  fetchSingleDataSetFromIndexer<TimeSeriesRow>(url, { abortController })
    .then((data: TimeSeriesDataSet): TimeSeriesRow[] => {
      return (
        Array.from(data)
          // sort by index (chronological timestamp)
          .sort(([a], [b]) => a - b)
      );
    })
    .then(setData);
  // cleanup by aborting the fetch
  return () => abortController.abort();
}, [url]);

Subscribing to updates using base data accumulation Class:

import { IndexerStreamAccumulateSingleDataSet } from '@duality-labs/duality-front-end-sdk';

// to pass update data to a higher-level `onRealtimeCallback` function
new IndexerStreamAccumulateSingleDataSet<TimeSeriesRow>(url, {
  onUpdate: (dataUpdates) => {
    // note: TradingView data needs to be in chronological order
    // and our indexer API delivers results in reverse-chronological order
    const chronologicalUpdates = dataUpdates.reverse();
    for (const row of chronologicalUpdates) {
      // translate indexer API data row into TradingView candle object
      onRealtimeCallback(getBarFromTimeSeriesRow(row));
    }
  },
});

Subscribing to updates using data accumulation React Hooks:

import { useMemo } from 'react';
import { useIndexerStreamOfSingleDataSet } from '@duality-labs/duality-front-end-sdk';

export type TokenPairReserves = [
  token0: string,
  token1: string,
  reserve0: number,
  reserve1: number
];
type DataRow = [index: number, values: TokenPairReserves];

type TokenPairsState = {
  data: TokenPairReserves[] | undefined;
  error: Error | null;
};

export default function useTokenPairs(): TokenPairsState {
  const { data, error } =
    useIndexerStreamOfSingleDataSet<DataRow>(`${indexerAPI}/liquidity/pairs`);

  const values: TokenPairReserves[] | undefined = useMemo(() => {
    if (data) {
      const values = Array.from(data)
        .sort(([a], [b]) => a - b)
        .map((row) => row[1]);
      return values;
    }
  }, [data]);

  // return state
  return { data: values, error: error || null };
}

Subscribing to updates of a multiple dataset endpoint with React Hooks

import { useIndexerStreamOfDualDataSet } from '@duality-labs/duality-front-end-sdk';

type ReserveDataRow = [tickIndex: number, reserves: number];
type ReserveDataSet = Map<ReserveDataRow['0'], ReserveDataRow['1']>;

// add convenience method to fetch liquidity maps of a pair
export function useTokenPairMapLiquidity([tokenIdA, tokenIdB]: [string?, string? ]): {
  // note that two data sets are returned by useIndexerStreamOfDualDataSet
  data?: [ReserveDataSet, ReserveDataSet];
  error?: unknown;
} {
  // stream data from indexer
  return useIndexerStreamOfDualDataSet<ReserveDataRow>(
    tokenIdA && tokenIdB && `${indexerAPI}/liquidity/pair/${tokenIdA}/${tokenIdB}`,
    {
      // remove entries of value 0 from the accumulated map, they are not used
      mapEntryRemovalValue: 0,
    }
  );
}