Skip to content

Commit

Permalink
Merge branch 'stage' into JP69/asset-noek-add
Browse files Browse the repository at this point in the history
  • Loading branch information
JeremyParish69 authored Sep 18, 2023
2 parents 5163a71 + 4b8f4c2 commit 4ebf190
Show file tree
Hide file tree
Showing 27 changed files with 701 additions and 100 deletions.
38 changes: 34 additions & 4 deletions packages/pools/src/__tests__/concentrated.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export class MockTickProvider implements TickDataProvider {
'[{"liquidity_net":"1063928513.516692280118630934","tick_index":"244"},{"liquidity_net":"12821176827.612857487321385327","tick_index":"507"},{"liquidity_net":"-19112293.184876715840844082","tick_index":"975"},{"liquidity_net":"-7042487.204272221556955330","tick_index":"1070"},{"liquidity_net":"119846363299223.491923667407418441","tick_index":"1176"},{"liquidity_net":"-12821176827.612857487321385327","tick_index":"1331"},{"liquidity_net":"25864763042758566.825780314141787151","tick_index":"1642"},{"liquidity_net":"789067578720062952.312030597659307660","tick_index":"1767"},{"liquidity_net":"5548573714963426149.345245435735691668","tick_index":"1918"},{"liquidity_net":"-789067578720062952.312030597659307660","tick_index":"1968"},{"liquidity_net":"-7533671.157383740445274322","tick_index":"2118"},{"liquidity_net":"-5548573714963426149.345245435735691668","tick_index":"2133"},{"liquidity_net":"-119846363299223.491923667407418441","tick_index":"2438"},{"liquidity_net":"-13690973.612258627731976066","tick_index":"2593"},{"liquidity_net":"75212224210553284471974.853997539381387792","tick_index":"2677"},{"liquidity_net":"-25864763042758566.825780314141787151","tick_index":"2798"},{"liquidity_net":"-991724173.842077641035110916","tick_index":"2841"},{"liquidity_net":"-1063928513.516692280118630934","tick_index":"2889"},{"liquidity_net":"-75212224210553284471974.853997539381387792","tick_index":"2954"},{"liquidity_net":"2300427651236616516001198205.268726763564344440","tick_index":"3361"},{"liquidity_net":"-2300427651236616516001198205.268726763564344440","tick_index":"3390"}]'
) as LiquidityDepth[],
isMaxTicks: true,
currentLiquidity: new Dec(100),
currentTick: new Int(0),
};
} else {
// token0
Expand All @@ -32,6 +34,8 @@ export class MockTickProvider implements TickDataProvider {
'[{"liquidity_net":"13690973.612258627731976066","tick_index":"-420"},{"liquidity_net":"7042487.204272221556955330","tick_index":"-770"},{"liquidity_net":"7533671.157383740445274322","tick_index":"-923"},{"liquidity_net":"991724173.842077641035110916","tick_index":"-1014"},{"liquidity_net":"19112293.184876715840844082","tick_index":"-1073"}]'
) as LiquidityDepth[],
isMaxTicks: true,
currentLiquidity: new Dec(100),
currentTick: new Int(0),
};
}
}
Expand All @@ -42,17 +46,27 @@ export class MockTickProvider implements TickDataProvider {
): Promise<TickDepths> {
// TODO: verify
if (token.denom === pool.token1) {
return { allTicks: [], isMaxTicks: false };
return {
allTicks: [],
isMaxTicks: false,
currentLiquidity: new Dec(100),
currentTick: new Int(0),
};
} else {
// token0
return { allTicks: [], isMaxTicks: false };
return {
allTicks: [],
isMaxTicks: false,
currentLiquidity: new Dec(100),
currentTick: new Int(0),
};
}
}
}

export class MockAmountProvider implements AmountsDataProvider {
async getPoolAmounts(): Promise<{ token0Amount: Int; token1Amount: Int }> {
return { token0Amount: new Int(100), token1Amount: new Int(100) };
return { token0Amount: new Int(0), token1Amount: new Int(0) };
}
}

Expand All @@ -70,7 +84,7 @@ class TestPool extends ConcentratedLiquidityPool {
}

const raw1: ConcentratedLiquidityPoolRaw = JSON.parse(
'{"@type":"/osmosis.concentratedliquidity.v1beta1.Pool","address":"osmo1lzwv0glchfcw0fpwzdwfdsepmvluv6z6eh4qunxdml33sj06q3yq7xwtde","id":"4","current_tick_liquidity":"141421356.237309510000200000","token0":"uion","token1":"uosmo","current_sqrt_price":"0.014142135623730951","current_tick":"-350000","tick_spacing":"1","precision_factor_at_price_one":"-4","swap_fee":"0.010000000000000000","last_liquidity_update":"2023-03-21T02:07:13.890847048Z"}'
'{"@type":"/osmosis.concentratedliquidity.v1beta1.Pool","address":"osmo1lzwv0glchfcw0fpwzdwfdsepmvluv6z6eh4qunxdml33sj06q3yq7xwtde","id":"4","current_tick_liquidity":"141421356.2373095000200000","token0":"uion","token1":"uosmo","current_sqrt_price":"0.014142135623730951","current_tick":"-350000","tick_spacing":"1","precision_factor_at_price_one":"-4","swap_fee":"0.0000000000000000","last_liquidity_update":"2023-03-21T02:07:13.890847048Z"}'
);

describe("ConcentratedLiquidityPool", () => {
Expand Down Expand Up @@ -152,6 +166,8 @@ describe("ConcentratedLiquidityPool.getTokenOutByTokenIn", () => {
tickDataProvider.getTickDepthsTokenOutGivenIn.mockResolvedValueOnce({
allTicks: mockTicks,
isMaxTicks: false,
currentLiquidity: mockClPool.current_tick_liquidity,
currentTick: new Int(0),
});

const tokenIn = { denom: "uosmo", amount: new Int(1_000_000) };
Expand All @@ -170,22 +186,32 @@ describe("ConcentratedLiquidityPool.getTokenOutByTokenIn", () => {
.mockResolvedValueOnce({
allTicks: [],
isMaxTicks: false,
currentLiquidity: mockClPool.current_tick_liquidity,
currentTick: new Int(0),
})
.mockResolvedValueOnce({
allTicks: [],
isMaxTicks: false,
currentLiquidity: mockClPool.current_tick_liquidity,
currentTick: new Int(0),
})
.mockResolvedValueOnce({
allTicks: [],
isMaxTicks: false,
currentLiquidity: mockClPool.current_tick_liquidity,
currentTick: new Int(0),
})
.mockResolvedValueOnce({
allTicks: [],
isMaxTicks: false,
currentLiquidity: mockClPool.current_tick_liquidity,
currentTick: new Int(0),
})
.mockResolvedValueOnce({
allTicks: mockTicks.slice(0, 1),
isMaxTicks: false,
currentLiquidity: mockClPool.current_tick_liquidity,
currentTick: new Int(0),
});

const tokenIn = { denom: "uosmo", amount: new Int(1_000_000) };
Expand All @@ -204,10 +230,14 @@ describe("ConcentratedLiquidityPool.getTokenOutByTokenIn", () => {
.mockResolvedValueOnce({
allTicks: [],
isMaxTicks: false,
currentLiquidity: new Dec(100),
currentTick: new Int(0),
})
.mockResolvedValueOnce({
allTicks: [],
isMaxTicks: true,
currentLiquidity: new Dec(100),
currentTick: new Int(0),
});

const tokenIn = { denom: "uosmo", amount: new Int(1_000_000) };
Expand Down
50 changes: 39 additions & 11 deletions packages/pools/src/concentrated/fetch-tick-data-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,27 @@ import {
} from "./pool";

type TickDepthsResponse = {
current_liquidity: string;
current_tick: string;
liquidity_depths: {
liquidity_net: string;
tick_index: string;
}[];
};

type SerializedTickDepthsResponse = {
currentLiquidity: Dec;
currentTick: Int;
depths: LiquidityDepth[];
};

/** Default tick data provider that fetches ticks for a single CL pool with `fetch` if the environment supports it, if not a fetcher can be supplied.
* It is assumed this instance follows the instance of the pool.
* Stores some cache data statically, assuming ticks are being fetched from a single query node. */
export class FetchTickDataProvider implements TickDataProvider {
protected _currentLiquidity: Dec = new Dec(0);
protected _currentTick: Int = new Int(0);

protected _zeroForOneTicks: LiquidityDepth[] = [];
protected _oneForZeroTicks: LiquidityDepth[] = [];

Expand Down Expand Up @@ -128,6 +139,8 @@ export class FetchTickDataProvider implements TickDataProvider {
// check if has fetched all ticks, if so return existing ticks
if (isMaxTicks) {
return {
currentLiquidity: this._currentLiquidity,
currentTick: this._currentTick,
allTicks: prevTicks,
isMaxTicks: true,
};
Expand Down Expand Up @@ -168,24 +181,31 @@ export class FetchTickDataProvider implements TickDataProvider {
currentTickLiquidity: pool.currentTickLiquidity,
}).boundTickIndex;

const depths = await this.fetchTicks(
const { depths, currentLiquidity, currentTick } = await this.fetchTicks(
tokenInDenom,
initialEstimatedTick
);

this._currentLiquidity = currentLiquidity;
this._currentTick = currentTick;
setTicks(depths);
setLatestBoundTickIndex(initialEstimatedTick);
} else if (getMoreTicks) {
// have fetched ticks, but requested to get more
const nextBoundIndex = rampNextQueryTick(
zeroForOne,
pool.currentTick,
this._currentTick,
prevBoundIndex,
this.nextTicksRampMultiplier
);

const depths = await this.fetchTicks(tokenInDenom, nextBoundIndex);
const { depths, currentLiquidity, currentTick } = await this.fetchTicks(
tokenInDenom,
nextBoundIndex
);

this._currentLiquidity = currentLiquidity;
this._currentTick = currentTick;
setTicks(depths);
setLatestBoundTickIndex(nextBoundIndex);
}
Expand All @@ -196,6 +216,8 @@ export class FetchTickDataProvider implements TickDataProvider {
const allTicks = zeroForOne ? this._zeroForOneTicks : this._oneForZeroTicks;

return {
currentLiquidity: this._currentLiquidity,
currentTick: this._currentTick,
allTicks,
isMaxTicks: false,
};
Expand All @@ -206,7 +228,7 @@ export class FetchTickDataProvider implements TickDataProvider {
async fetchTicks(
tokenInDenom: string,
boundTick: Int
): Promise<LiquidityDepth[]> {
): Promise<SerializedTickDepthsResponse> {
const requestKey = [this.poolId, tokenInDenom, boundTick]
.map((p) => p.toString())
.join("_");
Expand All @@ -226,17 +248,23 @@ export class FetchTickDataProvider implements TickDataProvider {

const response = await request;

const depths = serializeTickDepths(response);
const serializedResponse = serializeRequest(response);
FetchTickDataProvider._inFlightTickRequests.delete(requestKey);
return depths;
return serializedResponse;
}
}

function serializeTickDepths(tickDepths: TickDepthsResponse): LiquidityDepth[] {
return tickDepths.liquidity_depths.map((depth) => ({
tickIndex: new Int(depth.tick_index),
netLiquidity: new Dec(depth.liquidity_net),
}));
function serializeRequest(
response: TickDepthsResponse
): SerializedTickDepthsResponse {
return {
currentLiquidity: new Dec(response.current_liquidity),
currentTick: new Int(response.current_tick),
depths: response.liquidity_depths.map((depth) => ({
tickIndex: new Int(depth.tick_index),
netLiquidity: new Dec(depth.liquidity_net),
})),
};
}

/**
Expand Down
37 changes: 14 additions & 23 deletions packages/pools/src/concentrated/pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export interface ConcentratedLiquidityPoolRaw {
}

export type TickDepths = {
currentLiquidity: Dec;
currentTick: Int;
allTicks: LiquidityDepth[];
isMaxTicks: boolean;
};
Expand Down Expand Up @@ -93,10 +95,6 @@ export class ConcentratedLiquidityPool implements BasePool, RoutablePool {
return new Dec(0);
}

get currentTick(): Int {
return new Int(this.raw.current_tick);
}

/** amountToken1/amountToken0 or token 1 per token 0 */
get currentSqrtPrice(): BigDec {
return new BigDec(this.raw.current_sqrt_price);
Expand All @@ -106,16 +104,6 @@ export class ConcentratedLiquidityPool implements BasePool, RoutablePool {
return new Dec(this.raw.current_tick_liquidity);
}

get currentTickLiquidityXY(): [Dec, Dec] {
const baseAmount = new BigDec(this.currentTickLiquidity)
.quo(this.currentSqrtPrice)
.toDec();
const quoteAmount = new BigDec(this.currentTickLiquidity)
.mul(this.currentSqrtPrice)
.toDec();
return [baseAmount, quoteAmount];
}

get tickSpacing(): number {
const ts = parseInt(this.raw.tick_spacing);
if (isNaN(ts)) {
Expand Down Expand Up @@ -196,7 +184,7 @@ export class ConcentratedLiquidityPool implements BasePool, RoutablePool {
let calcResult = undefined;
do {
const needMoreTicks = calcResult === "no-more-ticks";
const { allTicks, isMaxTicks } =
const { allTicks, isMaxTicks, currentLiquidity } =
await this.tickDataProvider.getTickDepthsTokenOutGivenIn(
this,
tokenIn,
Expand All @@ -206,7 +194,7 @@ export class ConcentratedLiquidityPool implements BasePool, RoutablePool {
calcResult = ConcentratedLiquidityMath.calcOutGivenIn({
tokenIn: new Coin(tokenIn.denom, tokenIn.amount),
tokenDenom0: this.raw.token0,
poolLiquidity: this.currentTickLiquidity,
poolLiquidity: currentLiquidity,
inittedTicks: allTicks,
curSqrtPrice: this.currentSqrtPrice,
swapFee,
Expand Down Expand Up @@ -302,17 +290,20 @@ export class ConcentratedLiquidityPool implements BasePool, RoutablePool {
let calcResult = undefined;
do {
const needMoreTicks = calcResult === "no-more-ticks";
const { allTicks: inittedTicks, isMaxTicks } =
await this.tickDataProvider.getTickDepthsTokenInGivenOut(
this,
tokenOut,
needMoreTicks
);
const {
allTicks: inittedTicks,
isMaxTicks,
currentLiquidity,
} = await this.tickDataProvider.getTickDepthsTokenInGivenOut(
this,
tokenOut,
needMoreTicks
);

calcResult = ConcentratedLiquidityMath.calcInGivenOut({
tokenOut: new Coin(tokenOut.denom, tokenOut.amount),
tokenDenom0: this.raw.token0,
poolLiquidity: this.currentTickLiquidity,
poolLiquidity: currentLiquidity,
inittedTicks,
curSqrtPrice: this.currentSqrtPrice,
swapFee,
Expand Down
Loading

0 comments on commit 4ebf190

Please sign in to comment.