• Stars
    star
    165
  • Rank 228,906 (Top 5 %)
  • Language
    JavaScript
  • License
    ISC License
  • Created over 3 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Node.js library to calculate Uniswap V3 ratios (prices) from token pairs.

UniV3Prices

A Node.js library to calculate Uniswap V3 ratios (prices) and liquidity (reserves).

NPM Version CircleCI codecov Discord Twitter Follow



Check out the other Uniswap and crypto libraries, that depend on this library and this library depends on:

☎ī¸ @thanpolas/uniswap-chain-queries for fetching on-chain data for ERC20 tokens, Uniswap V2 (and clones) and Uniswap V3.
🔧 @thanpolas/crypto-utils for calculating and formatting tokens and fractions.



Features

This library will allow you to:

Install

Install the module using NPM:

npm install @thanpolas/univ3prices --save

Quick Start

const univ3prices = require('@thanpolas/univ3prices');

const price = univ3prices([USDC.decimals, USDT.decimals], sqrtPrice).toAuto();

console.log(price);
// "1.00212"

sqrtPrice(tokenDecimals, sqrtRatioX96)

The default function; calculates Uniswap V3 Liquidity Pool (LP) ratios (prices) for Token Pairs.

  • tokenDecimals {Array<number|string>} An Array tuple with 2 elements, the token0 and token1 decimal place values.
  • sqrtPrice {string} The Square Root price value of the LP.

ℹī¸ :: This is the default function available by directly requiring the library (const uniV3Prices = require('univ3prices')) or as a property (const { sqrtPrice } = require('univ3prices')).

ℹī¸ :: See the How to Get the sqrtPrice and Tick values for a guide on how to get those values.

The sqrtPrice() returns an object that contains four functions depending on the output type you wish to have. The calculation functions are from the crypto-utils, find a brief description below.

toAuto(optOptions)

Does automatic decimal calculation and applies appropriate function. If result is above 1 then toFixed() is applied, if under 1 then toSignificant() is applied. View toAuto() documentation on crypto-utils.

  • optOptions {Object=} Calculation and Formatting options from the crypto-utils package.
  • Returns {string} an optimally formatted value.
// prepare a sqrtPrice value, by emulating a 10 / 7 division.
const sqrtPrice = encodeSqrtRatioX96(10e18, 7e18);

univ3Price([18, 18], sqrtPrice).toAuto();
// '0.7'

univ3Price([18, 18], sqrtPrice).toAuto({ reverse: true });
// '1.42857'

univ3Price([18, 18], sqrtPrice).toSignificant({
    reverse: true,
    decimalPlaces: 3,
});
// '1.439'

toSignificant(optOptions)

calculates the value to significant digits. View the toSignificant() documentation on crypto-utils

  • optOptions {Object=} Calculation and Formatting options from the crypto-utils package.
  • Returns string, the last significant decimals, default 5.

toSignificant Examples - Defaults

// prepare a sqrtPrice value, by emulating a 7 / 10 division.
const sqrtPrice = encodeSqrtRatioX96(7e18, 10e18);

univ3Price([18, 18], sqrtPrice).toSignificant();
// '1.4286'

univ3Price([18, 18], sqrtPrice).toSignificant({ decimalPlaces: 3 });
// '1.43'

univ3Price([18, 18], sqrtPrice).toSignificant({ decimalPlaces: 2 });
// '1.4'

toFixed(optOptions)

Calculates to fixed decimals. View the toSignificant() documentation on crypto-utils

  • optOptions {Object=} Calculation and Formatting options from the crypto-utils package.
  • Returns string, ration with fixed decimals, default 5.

toFixed Examples

// prepare a sqrtPrice value, by emulating a 7 / 10 division.
const sqrtPrice = encodeSqrtRatioX96(7e18, 10e18);
// and a sqrtPrice value emulating  20000000 / 1  division.
const sqrtPrice_20m = encodeSqrtRatioX96(20000000e18, 1e18);

univ3Price([18, 18], sqrtPrice).toFixed();
// '1.42857'

univ3Price([18, 18], sqrtPrice).toFixed({ decimalPlaces: 3 });
// '1.429'

univ3Price([18, 18], sqrtPrice).toFixed({ decimalPlaces: 2 });
// '1.43'

// This time use the 20m ratio
univ3Price([18, 18], sqrtPrice_20m).toFixed({ decimalPlaces: 2 });
// '20000000.00'

toFraction()

Returns the raw fraction tuple Array; contains the numerator and denominator in BigInt type of the token pairs.

toFraction() Examples

const JSBI = require('jsbi');
// prepare a sqrtPrice value, by emulating a 10 / 7 division.
const sqrtPrice = encodeSqrtRatioX96(10e18, 7e18);

const fraction = univ3Price([18, 18], sqrtPrice).toFraction();

const [numerator, denominator] = fraction;

numerator instanceOf JSBI; // true
denominator instanceOf JSBI; // true

How to get the sqrtPrice and tick Values From Uniswap

In regards to the sqrtPrice and tick values. there are two primary ways to get it:

Using the Liquidity Pool Contract

Query the Liquidity Pool contract of interest and use the slot0() method.

This method will return a collection of properties, the ones you care about is sqrtPriceX96 or tick.

Using the Subgraph

Use the Uniswap V3 Subgraph that is publicly available and fetch the sqrtPrice or tick property from the Pool schema.


univ3prices.tickPrice(tokenDecimals, tick)

calculates Uniswap V3 Liquidity Pool (LP) ratios (prices) for Token Pairs using the current tick value.

  • tokenDecimals {Array<number|string>} An Array tuple with 2 elements, the token0 and token1 decimal place values.
  • tick {string} The current tick value.

ℹī¸ :: See the How to Get the sqrtPrice and Tick values for a guide on how to get those values.

The univ3prices.tickPrice() returns an object that contains four functions depending on the output type you wish to have, and has the exact same functions as the default function:


univ3prices.getAmountsForCurrentLiquidity(tokenDecimals, liquidity, sqrtPrice, tickSpacing, optOpts)

Calculates the reserves for the current sqrt price value.

  • tokenDecimals {Array<number|string>} An Array tuple with 2 elements, the token0 and token1 decimal place values.

  • liquidity {string} The liquidity value of the LP.

  • tickSpacing {string} The tick spacing value of the LP.

  • optOptions {Object=} A set of optional options:

  • Returns {Array} A tuple array containing the amount of each token in the defined liquidity range.

ℹī¸ :: This function is a wrapper to getAmountsForLiquidityRange(), will automatically calculate the liquidity range expressed as sqrtRatioAX96 and sqrtRatioBX96.

Examples for univ3prices.getAmountsForCurrentLiquidity

Standard example:

const tokenDecimals = [
    '18', // decimals of DAI
    '18', // decimals of WETH
];
// Get the reserves for the DAI/WETH Liquidity Pool.
const [token0Reserves, token1Reserves] = getAmountsForCurrentLiquidity(
    tokenDecimals,
    '2830981547246997099758055', // Current liquidity value of the pool
    '1550724133884968571999296281', // Current sqrt price value of the pool
    '60', // the tickSpacing value from the pool
);
// The total amount of DAI available in this liquidity range
expect(token0Reserves).toEqual('116596.90182');
// The total amount of WETH available in this liquidity range
expect(token1Reserves).toEqual('121.40391');

Widening the liquidity range by having a step of 5:

// Get the reserves for the DAI/WETH Liquidity Pool.
const [token0Reserves, token1Reserves] = getAmountsForCurrentLiquidity(
    tokenDecimals,
    '2830981547246997099758055', // Current liquidity value of the pool
    '1550724133884968571999296281', // Current sqrt price value of the pool
    '60', // the tickSpacing value from the pool
    {tickStep: 5} // Choose 5 steps of tickSpacing (60 * 5) for low and high tick values.
);
// The total amount of DAI available in this liquidity range
expect(token0Reserves).toEqual('2268131.86622');
// The total amount of WETH available in this liquidity range
expect(token1Reserves).toEqual('944.51034');
});

Where to Find The Values for the Liquidity Function

Query directly the Liquidity Pool contract you care about (i.e. this is the DAI/WETH pool) and call the functions:

  • slot0() To get a list of values including the sqrtPriceX96.
  • liquidity() To get the liquidity value.
  • tickSpacing() To get the tick spacing value.

univ3prices.getAmountsForLiquidityRange(sqrtPrice, sqrtPriceA, sqrtPriceB, liquidity)

Calculates the reserves for a range of sqrt price.

  • sqrtPrice {string} The Square Root price value of the LP.
  • sqrtPriceA {string} The Square Root price representing the low tick boundary.
  • sqrtPriceB {string} The Square Root price representing the high tick boundary.
  • liquidity {string} The liquidity value.
  • Returns {Array} A tuple array containing the amount of each token in the defined liquidity range.

Examples for univ3prices.getAmountsForLiquidityRange

const [amount0, amount1] = getAmountsForLiquidityRange(
    encodePriceSqrt(1, 1), // generate sqrt price for range
    encodePriceSqrt(100, 110),
    encodePriceSqrt(110, 100),
    2148,
);

expect(Number(amount0)).toEqual(99); // Amount of token0
expect(Number(amount1)).toEqual(99); // Amount of token1

Tick Math Functions

univ3prices.tickMath.getSqrtRatioAtTick(tick)

Calculates the sqrt ratio at the given tick.

  • tick {string} The tick value to calculate the sqrt ratio for.
  • Returns {string} The sqrt ratio.

univ3prices.tickMath.getTickAtSqrtRatio(sqrtPrice)

Calculates the tick at the given sqrt ratio.

  • sqrtPrice {string} The sqrt price to calculate the tick for.
  • Returns {string} The tick.

Utility Functions

The following utility functions are available in the univ3prices.utils path:

  • encodeSqrtRatioX96(amount0, amount1) Convert a value pair to sqrt price.
  • sqrt(value) Computes the floor(sqrt(value)).
  • tickRange(tick, tickSpacing, optTickStep) Will calculate the low and high tick ranges for a given tick, optionally multiplying the spacing with the step for a wider range.
  • expDecs(decimals) Will return the exponent of the given decimals number.
  • biConv(value) Will safely convert any value to JSBI and not touch values that are of JSBI type.

Constants

The following constants are available in the univ3prices.constants path:

  • RESOLUTION :: Fixed point resolution of 96 as a bigint.
  • NEGATIVE_ONE :: -1 as a bigint.
  • ZERO :: 0 as a bigint.
  • ONE :: 1 as a bigint.
  • TWO :: 2 as a bigint.
  • Q32 :: Power of 2 at 32.
  • Q96 :: Power of 2 at 96.
  • Q192 :: Power of 2 at 192.
  • MaxUint256 :: Maximum signed integer value.
  • MIN_TICK :: Minimum tick value.
  • MAX_TICK :: Maximum tick value.
  • MIN_SQRT_RATIO :: Minimum sqrt price (ratio) value.
  • MAX_SQRT_RATIO :: Maximum sqrt price (ratio) value.
  • Rounding :: The Rounding enumeration from the crypto-utils package.

Acknowledgements & Credits

This library has been a study and break down, to understand how Uniswap V3 works. It acts both as a library for you to use and a way for you to understand, in simpler terms, how price is calculated.

In particular, the Uniswap V3 SDK's Pool Class and the Uniswap SDK Core's Price and Fraction classes were reverse engineered and rewritten in a functional manner. Most of the tests where also ported directly from the excellently tested SDK and Core packages.

Thank you goes to [JNP][jnp] who helped me understand how to work with tick and sqrt ranges.

Thank you goes to Georgios Konstantopoulos who helped me with liquidity calculations and code review.

Finally, thank you goes to Jorropo.eth who has accompanied and helped me in the weeks long journey of discovering how to calculate Uniswap's V3 sqrt ratios, on Uniswap's Discord. He also gave the following excellent explanation as to why the Token Pair reserves are square rooted:

This is so the difference gets exponentially written.

Let's assume ticks were just 100$ in size, so you have one from 0-100, 100-200, ... A token that is price at 250$ would need to do +20% in price to cross a tick. But a token priced 25050$ it's bearly +0.2%.

Having them SQRT makes the ratio constant. So in any cases it's just let's say any 1% of price change, cross a tick.

This spreads them each 1% appart (so fewer and fewer ticks), instead of each 100$ appart.

Maintenance & Development

Update Node Version

When a new node version should be supported, updated the following:

  • /package.json
  • /.nvmrc
  • /.circleci/config.yml

Releasing

  1. Update the changelog bellow ("Release History").
  2. Ensure you are on master and your repository is clean.
  3. Type: npm run release for patch version jump.
    • npm run release:minor for minor version jump.
    • npm run release:major for major major jump.

Release History

  • v3.0.2, 07 Sep 2021
  • v3.0.1, 06 Sep 2021
    • Updated all dependencies to latest and especially jsbi to ^3.2.1 so users won't suffer from the broken 3.2.0 release.
  • v3.0.0, 22 Aug 2021
    • Breaking Changed signature of `getAmountsForCurrentLiquidity()``, it now uses a tuple for the decimals and added formatting options for the result. By default liquidity values will now have 5 decimal places instead of 1
    • Breaking Changed signature of sqrtPrice() and tickPrice(), they now use a tuple for the decimals and reversing the price has been decoupled to formatting.
    • Breaking Decoupled and replaced fraction calculation and formatting functions to crypto-utils package (toSignificant() and toFixed() functions).
    • Replaced internal fraction and formatting functions with crypto-utils package.
    • Fixed bug with priceRange() utility that affected the liquidity calculation when the tickSpacing argument was used, thank you @sydneyhenrard.
  • v2.0.1, 06 Aug 2021
    • Fixed order of price calculation for sqrtPrice().
  • v2.0.0, 06 Aug 2021
    • Implemented the liquidity calculation functions getAmountsForCurrentLiquidity() and getAmountsForLiquidityRange().
    • Implemented Tick Math functions at tickMath.getSqrtRatioAtTick() and tickMath.getTickAtSqrtRatio.
    • Added sqrtPrice function on the API (same as the default export).
    • New constant values added (ZERO, ONE, TWO, MaxUint256, MIN_TICK, MAX_TICK, MIN_SQRT_RATIO, MAX_SQRT_RATIO).
    • New utils functions added (tickRange, expDecs, biConv).
    • Breaking Moved utility functions (encodeSqrtRatioX96() and sqrt()) into the utils namespace.
    • Breaking Moved constants (Rounding, Q96 and Q192) into the constants namespace.
    • Breaking Renamed output function .toScalar() to .toFraction().
    • Internal change of toFixed() and toSignificant() to accept a tuple Array instead of an Object.
  • v1.1.0, 31 Jul 2021
    • Added tickPrice() function to calculate price based on current tick value.
    • Refactored the default price calculation function with better variable names.
    • Fixed a decimal miscalculation issue on pairs with different decimal values.
  • v1.0.0, 19 Jul 2021
    • Big Bang

License

Copyright Š Thanos Polychronakis and Authors, Licensed under ISC.

More Repositories

1

logality

Versatile JSON Logger
JavaScript
124
star
2

grunt-closure-tools

Google Closure Tools for grunt
JavaScript
95
star
3

mantri

Javascript Dependency System Extraordinaire
JavaScript
84
star
4

uniswap-chain-queries

On chain queries for Uniswap V2 and V3
JavaScript
56
star
5

generator-closure

Closure Library generator using Yeoman
JavaScript
50
star
6

Practice

A Collection of Best Practices
37
star
7

grunt-github-pages

Push to gh-pages no problem
JavaScript
28
star
8

nodeON

node.js web application scaffolding
JavaScript
27
star
9

crypto-utils

Crypto utilities for tokens and formatting
JavaScript
23
star
10

middlewarify

Apply the middleware pattern to any property or function
JavaScript
20
star
11

ready.js

Watch multiple async operations and trigger listeners when all are complete
JavaScript
20
star
12

degenking

Utility library for fetching and working with DFK Heroes.
JavaScript
20
star
13

entity

MVCe
JavaScript
17
star
14

server2js

Transfer data objects from server to javascript on page load.
JavaScript
15
star
15

crude

CRUD automation for node
JavaScript
14
star
16

superstartup

The Super Startup Javascript library! User system, metrics, sharing widgets and star dust!
JavaScript
12
star
17

profy

Stress test your apps and measure performance
JavaScript
12
star
18

thanpolas.github.com

My personal site
CSS
11
star
19

cip

Classical Inheritance Pattern at its best.
JavaScript
9
star
20

govbot

Governance bot for DAOs
JavaScript
8
star
21

gitfox

A github client for firefox OS
JavaScript
7
star
22

kansas

Usage limited API to go!
JavaScript
6
star
23

perf-promises

Performance of promises
JavaScript
5
star
24

redis-simple-store

A Simple key/value store for arbitrary values based on redis.
JavaScript
5
star
25

calendarth

Fetch a public Google Calendar using AJAX
JavaScript
5
star
26

shell_helpers

A collection of helping shell scripts
Perl
4
star
27

idify

Get a guaranteed unique Id using Redis SET
JavaScript
4
star
28

nodeON-helpers

A collection of helper funcs
JavaScript
3
star
29

sublime-autoDocBlockr

Automatic Document Block insertion plugin for sublime text2
Python
3
star
30

grunt-services

Start and Stop database services
JavaScript
3
star
31

qunit2node

QUnit adapter for nodeunit
JavaScript
3
star
32

ffmpeg-binary-linux-64bit

Provides staticly compiled binaries for linux environments.
JavaScript
3
star
33

Modernizr-CJS

Mdernizer tests in Common Module Format
JavaScript
3
star
34

discord-bot-template

A discord.js bot template for quick bot turnaround
JavaScript
3
star
35

kansas-express

Express middleware for Kansas
JavaScript
2
star
36

nodeON-error

Error Objects for everybody!
JavaScript
2
star
37

node-asset-pipeline

Asset management for node
JavaScript
2
star
38

study-aave-flashloan

A Study for AAVE flashloans
Solidity
2
star
39

__proto__

A heavily personalized Node.js library starting project
JavaScript
2
star
40

httplink

Link HTTP Header constructor for your Restfull APIs
JavaScript
1
star
41

thanpolas

1
star
42

backup-scripts

backup scripts
Perl
1
star
43

listenshiprepeat.com

listenshiprepeat.com website sources
HTML
1
star
44

adref-agent

A ping agent written in node.js for the Adref service.
JavaScript
1
star
45

mantri-cli

The mantri command line interface.
JavaScript
1
star
46

ss

Superstartup library showcase
JavaScript
1
star
47

nodeON-base

The nodeON Base modules to inherit from.
JavaScript
1
star
48

closure-boilerplate

A google closure boilerplate repo, fork to construct a google closure based project
JavaScript
1
star
49

nodeON-file

A collection of file helpers.
JavaScript
1
star
50

gulp-closure-tools

Closure Tools for Gulp
JavaScript
1
star
51

crude-ownuser

A plugin for Crude enforcing own user policy on all routes.
JavaScript
1
star
52

task-closure-tools

The Closure Tools task (Compiler, Builder, Deps)
JavaScript
1
star
53

myStash

Nothing to see here, move on
Python
1
star
54

mithrion

Movement sensor music composer
JavaScript
1
star
55

nodeON-express-error

The nodeON Express Error Handler
JavaScript
1
star
56

try_git

1
star