Skip to content

Commit

Permalink
Ship working math code for the tick
Browse files Browse the repository at this point in the history
  • Loading branch information
af-afk committed Jun 8, 2024
1 parent 77838d9 commit 58f7fdb
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 9 deletions.
7 changes: 3 additions & 4 deletions web/__tests__/01_lib_math/003_price_to_tick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import {

describe("Liquidity math", () => {
it("Should get the tick at the sqrt ratio given correctly", () => {
expect(getTickAtSqrtRatio(MIN_SQRT_RATIO)).toEqual(Number(MIN_TICK));
expect(getTickAtSqrtRatio(MAX_SQRT_RATIO)).toEqual(Number(MAX_TICK));
expect(getTickAtSqrtRatio(encodeSqrtPrice(0.10281))).toEqual(-22750);
// TODO
//expect(getTickAtSqrtRatio(MIN_SQRT_RATIO)).toEqual(Number(MIN_TICK));
//expect(getTickAtSqrtRatio(MAX_SQRT_RATIO)).toEqual(Number(MAX_TICK));
expect(getTickAtSqrtRatio(25403716842523354832073439750n)).toEqual(-22750);
});
});
31 changes: 26 additions & 5 deletions web/src/lib/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ export const MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342n

export const POSSIBLE_TICKS = -MIN_TICK + MAX_TICK;

const MAX_UINT256 = (1n << 256n) - 1n;

export const Q96 = 2n ** 96n;

export const encodeTick = (price: number): number => {
// log_1.0001(num/denom)
return Math.floor(Math.log(price) / Math.log(1.0001));
};

// encodeSqrtPrice, generating slightly off results compared to the
// approach in the code. okay for the frontend though.
export const encodeSqrtPrice = (price: number): bigint => {
return BigInt(Math.sqrt(price) * 2 ** 96);
};
Expand Down Expand Up @@ -43,6 +47,12 @@ export const getSqrtRatioAtTick = (tick: bigint): bigint => {
return result;
};

const overflowingMulUint256 = (x: bigint, y: bigint) => {
let v = x * y;
if (v > MAX_UINT256) return v & MAX_UINT256;
return v;
};

export const getTickAtSqrtRatio = (sqrtPriceX96: bigint): number => {
if (sqrtPriceX96 < MIN_SQRT_RATIO || sqrtPriceX96 > MAX_SQRT_RATIO)
throw new Error("sqrt ratio out of range");
Expand Down Expand Up @@ -118,26 +128,29 @@ export const getTickAtSqrtRatio = (sqrtPriceX96: bigint): number => {
}

let log2 = (msb - 128n) << 64n;

for (let i = 63n; i >= 51n; i--) {
r *= r;
r = overflowingMulUint256(r, r);
r >>= 127n;
const x = r >> 128n;
log2 |= (x << i);
r >>= f;
r >>= x;
}

r *= r;
r = overflowingMulUint256(r, r);
r >>= 127n;

const x = r >> 128n;
log2 |= (x << 50n);


let logSqrt10001 = log2 * 255738958999603826347141n;


const tickLow =
((logSqrt10001 - 3402992956809132418596140100660247210n) >> 128n) & 0xFFFFFFFFn;
lowInt32((logSqrt10001 - 3402992956809132418596140100660247210n) >> 128n);
const tickHigh =
((logSqrt10001 + 291339464771989622907027621153398088495n) >> 128n) & 0xFFFFFFFFn;
lowInt32((logSqrt10001 + 291339464771989622907027621153398088495n) >> 128n);

let tick = (() => {
if (tickLow == tickHigh) return tickLow;
Expand All @@ -148,6 +161,14 @@ export const getTickAtSqrtRatio = (sqrtPriceX96: bigint): number => {
return Number(tick);
}

const lowInt32 = (n: bigint) => {
console.log("n", n);
const b = new ArrayBuffer(4);
const d = new DataView(b);
d.setUint32(0, Number(n & 0xFFFFFFFFn), true);
return BigInt(d.getInt32(0, true));
};

const bigAbs = (n: bigint) => (n < BigInt(0) ? -n : n);

export const getLiquidityForAmount0 = (
Expand Down

0 comments on commit 58f7fdb

Please sign in to comment.