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

@lunarislab/dex-pathfinder

v1.0.2

Published

A library made for interacting with decentralized exchanges in a fully decentralized context

Downloads

65

Readme

dex-pathfinder

dex-pathfinder is a JavaScript library designed for interacting with decentralized exchanges (DEX) such as Uniswap. It's goal is to find best return for a given pair of tokens without relying in any trusted entity. It run fully local and facilitates fetching and indexing token pairs directly from the Ethereum blockchain (or any evm chain) and supports flexible storage options thanks to level interface.

Currently only compatible with uniswapV2 interfaces

Installation

To install dex-pathfinder, use npm or yarn:

npm install @lunarislab/dex-pathfinder

How it works?

First of all, the library need to sync to the blockchain, this step could be really heavy in requests calls if you use a RPC provider.

So in the future commits, we'll provide some templates files if you want to speed up this step. But if you want to make it yourself, consider using the param 'requestsPerSeconds' correctly as it can burn your usage limit.

Once all pairs are fetched, they'll be indexed and you'll be able to use the pathfinder.

import { Client } from 'dex-pathfinder';
import { Level } from "level";

const viem = {
    public: createPublicClient(config),
    wallet: createWalletClient(config)
};

const client = new Client({
    viem,
    // this need to be set correctly
    requestsPerSeconds: 50,
    // the more router you have, the more pairs you'll fetch.
    routers: [
        {
            address: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
            type: "UniswapV2Router"
        }
    ],
    storage: Level, // you can use any level implementation
    storagefolder: "./src/data" // optional, to store the databases in a specific folder.
});

// this is necessary before any call
await client.init();

// this will launch the sync process
client.sync();

You can monitor the sync process using listeners, here is an example using ora.

const spinner = ora({
    color: "cyan",
    text: `Fetching pairs...`
}).start();

client.pairsFetcher.uniswapV2.on('fetchedPair', (data) => {
    spinner.text = `[${data.router.type}] - Fetching ${data.pair.address} ${data.progress}/${data.total}`
});
client.pairsFetcher.uniswapV2.on('indexedPair', (data) => {
    spinner.text = `[${data.router.type}] - Indexing... ${data.pair.address} ${data.progress}/${data.total}`
});

The module will also listen all new blocks and update all pairs reserves to keep it up to date. If you close the client, it will restart at where it was closed and read all missing blocks to be up to date again.

Usage

Once all the fetching process is done and indexed, you can use the swap function to find the best path to swap between two tokens.

Note that depending on your params, it can be really heavy in calculations. The depth and minPoolSize params are here to let you control the precision.

The more deph, and the less minPoolSize, the more precise it will be. But it will also take longer to find a path. Lowering theses params will rely on more probabilistic results, but with less calculations.

I recommend using less than 6 as depth, but it depend on your hardware.

   (async () => {
       const tokenA = "0x39AA39c021dfbaE8faC545936693aC917d5E7563";
       const tokenB = "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643";

       // this is just a simulation, you'll need to send a tx to do the swap
       const swap = await client.swap({
           inputToken: tokenA,
           outputToken: tokenB,
           inputAmount: 100000n,
           // the maximum length of path, not recommed to set it too high
           // as complexity of calculations will increase exponentially
           depth: 3
           // this is not yet implemented, it will be the minimum
           // liquidity required to use a pool in a swap, quoted in eth.
           minPoolSize: 100n,
       });

       // this will return a swap object with a list of paths,
       // path[0] is the most profitable one, path[1] is the second most profitable one, etc...
       console.log(swap);
   })();

To understand how it find paths, you have to understand how pairs are indexed. The index create a graph where each node is a token and all links are a pair.

Once we have a graph it allow applying a pathfinding algorithm (DFS in that case), similar to algorithms used for GPS, and find all existing paths. Then instead of calculating distances like GPS, we just need to calculate the return for each paths and sort them.

The project is currently under heavy development, and not yet ready for production usage.

Today it has some limitations, for example it dont filter frozen pools, so some paths could be just unusable, it will be partially fixed with the minPoolSize option, but a blacklist/whitelist system will be implemented too to allow you to select pools you want to use or not.