Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
rouzwelt committed Jan 10, 2025
1 parent ad2600a commit 99a5600
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 97 deletions.
77 changes: 11 additions & 66 deletions packages/sushi/src/router/liquidity-providers/AlgebraV1Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ import { DataFetcherOptions } from '../data-fetcher.js'
import { getCurrencyCombinations } from '../get-currency-combinations.js'
import { memoizer } from '../memoizer.js'
import {
NUMBER_OF_SURROUNDING_TICKS,
PoolFilter,
StaticPoolUniV3,
UniswapV3BaseProvider,
V3Pool,
bitmapIndex,
} from './UniswapV3Base.js'

export abstract class AlgebraV1BaseProvider extends UniswapV3BaseProvider {
Expand Down Expand Up @@ -182,16 +180,14 @@ export abstract class AlgebraV1BaseProvider extends UniswapV3BaseProvider {

staticPools.forEach((pool, i) => {
if (globalState === undefined || !globalState[i]) return
let thisPoolTickSpacing = this.DEFAULT_TICK_SPACING
if (poolsTickSpacing !== undefined && Array.isArray(poolsTickSpacing)) {
if (poolsTickSpacing[i] !== undefined) {
const ts = poolsTickSpacing[i]
if (typeof ts === 'number') {
thisPoolTickSpacing = ts
} else {
if (ts?.status === 'success') {
thisPoolTickSpacing = ts.result
}
let tickSpacing = this.DEFAULT_TICK_SPACING
if (poolsTickSpacing?.[i] !== undefined) {
const ts = poolsTickSpacing[i]
if (typeof ts === 'number') {
tickSpacing = ts
} else {
if (ts?.status === 'success') {
tickSpacing = ts.result
}
}
}
Expand All @@ -201,72 +197,21 @@ export abstract class AlgebraV1BaseProvider extends UniswapV3BaseProvider {
return
const fee = globalState[i]!.result?.[2] // fee
if (!fee) return
const activeTick =
Math.floor(tick / thisPoolTickSpacing) * thisPoolTickSpacing
const activeTick = this.getActiveTick(tick, tickSpacing)
if (typeof activeTick !== 'number') return
this.TICK_SPACINGS[pool.address.toLowerCase()] = thisPoolTickSpacing
existingPools.push({
...pool,
fee,
sqrtPriceX96,
activeTick,
tickSpacing,
ticks: new Map(),
})
})

return existingPools
}

override getIndexes(existingPools: V3Pool[]): [number[], number[]] {
const minIndexes = existingPools.map((pool) =>
bitmapIndex(
pool.activeTick - NUMBER_OF_SURROUNDING_TICKS,
this.TICK_SPACINGS[pool.address.toLowerCase()]!,
),
)
const maxIndexes = existingPools.map((pool) =>
bitmapIndex(
pool.activeTick + NUMBER_OF_SURROUNDING_TICKS,
this.TICK_SPACINGS[pool.address.toLowerCase()]!,
),
)
return [minIndexes, maxIndexes]
}

override handleTickBoundries(
i: number,
pool: V3Pool,
poolTicks: {
index: number
DLiquidity: bigint
}[],
minIndexes: number[],
maxIndexes: number[],
) {
const lowerUnknownTick =
minIndexes[i]! * this.TICK_SPACINGS[pool.address.toLowerCase()]! * 256 -
this.TICK_SPACINGS[pool.address.toLowerCase()]!
console.assert(
poolTicks.length === 0 || lowerUnknownTick < poolTicks[0]!.index,
'Error 236: unexpected min tick index',
)
poolTicks.unshift({
index: lowerUnknownTick,
DLiquidity: 0n,
})
const upperUnknownTick =
(maxIndexes[i]! + 1) *
this.TICK_SPACINGS[pool.address.toLowerCase()]! *
256
console.assert(
poolTicks[poolTicks.length - 1]!.index < upperUnknownTick,
'Error 244: unexpected max tick index',
)
poolTicks.push({
index: upperUnknownTick,
DLiquidity: 0n,
})
}

override getStaticPools(t1: Token, t2: Token): StaticPoolUniV3[] {
const allCombinations = getCurrencyCombinations(this.chainId, t1, t2)
const currencyCombinations: [Token, Token][] = []
Expand Down
114 changes: 83 additions & 31 deletions packages/sushi/src/router/liquidity-providers/UniswapV3Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ChainId } from '../../chain/index.js'
import { SushiSwapV3FeeAmount, TICK_SPACINGS } from '../../config/index.js'
import { Currency, Token, Type } from '../../currency/index.js'
import { computeSushiSwapV3PoolAddress } from '../../pool/index.js'
import { RToken, UniV3Pool } from '../../tines/index.js'
import { CLTick, RToken, UniV3Pool } from '../../tines/index.js'
import { DataFetcherOptions } from '../data-fetcher.js'
import { getCurrencyCombinations } from '../get-currency-combinations.js'
import { memoizer } from '../memoizer.js'
Expand Down Expand Up @@ -36,8 +36,20 @@ export interface V3Pool {
fee: UniV3FeeType[keyof UniV3FeeType]
sqrtPriceX96: bigint
activeTick: number
tickSpacing: number
ticks: Map<number, CLTick[]>
}

export const tickSpacingAbi = [
{
inputs: [],
name: 'tickSpacing',
outputs: [{ internalType: 'int24', name: '', type: 'int24' }],
stateMutability: 'view',
type: 'function',
},
] as const

export const NUMBER_OF_SURROUNDING_TICKS = 1000 // 10% price impact

export const bitmapIndex = (tick: number, tickSpacing: number) => {
Expand Down Expand Up @@ -83,13 +95,9 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
}
}

getActiveTick = (
tickCurrent: number,
feeAmount: UniV3FeeType[keyof UniV3FeeType],
) =>
typeof tickCurrent === 'number' && feeAmount
? Math.floor(tickCurrent / this.TICK_SPACINGS[feeAmount]!) *
this.TICK_SPACINGS[feeAmount]!
getActiveTick = (tickCurrent: number, tickSpacing?: number) =>
typeof tickCurrent === 'number' && typeof tickSpacing === 'number'
? Math.floor(tickCurrent / tickSpacing) * tickSpacing
: undefined

async fetchPoolData(
Expand Down Expand Up @@ -173,6 +181,39 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
return undefined
})

const tickSpacingData = {
multicallAddress: this.client.chain?.contracts?.multicall3
?.address as Address,
allowFailure: true,
blockNumber: options?.blockNumber,
contracts: staticPools.map(
(pool) =>
({
address: pool.address as Address,
chainId: this.chainId,
abi: tickSpacingAbi,
functionName: 'tickSpacing',
}) as const,
),
}
const tickSpacings = options?.memoize
? await (multicallMemoize(tickSpacingData) as Promise<any>).catch((e) => {
console.warn(
`${this.getLogPrefix()} - INIT: multicall failed, message: ${
e.message
}`,
)
return undefined
})
: await this.client.multicall(tickSpacingData).catch((e) => {
console.warn(
`${this.getLogPrefix()} - INIT: multicall failed, message: ${
e.message
}`,
)
return undefined
})

const existingPools: V3Pool[] = []

staticPools.forEach((pool, i) => {
Expand All @@ -181,12 +222,25 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
const tick = slot0[i]!.result?.[1]
if (!sqrtPriceX96 || sqrtPriceX96 === 0n || typeof tick !== 'number')
return
const activeTick = this.getActiveTick(tick, pool.fee)
let tickSpacing = this.TICK_SPACINGS[pool.fee]!
if (typeof tickSpacings?.[i] !== 'undefined') {
const ts = tickSpacings[i]
if (typeof ts === 'number') {
tickSpacing = ts
} else {
if (ts?.status === 'success') {
tickSpacing = ts.result
}
}
}
const activeTick = this.getActiveTick(tick, tickSpacing)
if (typeof activeTick !== 'number') return
existingPools.push({
...pool,
sqrtPriceX96,
activeTick,
tickSpacing,
ticks: new Map(),
})
})

Expand All @@ -197,31 +251,33 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
const minIndexes = existingPools.map((pool) =>
bitmapIndex(
pool.activeTick - NUMBER_OF_SURROUNDING_TICKS,
this.TICK_SPACINGS[pool.fee]!,
pool.tickSpacing,
),
)
const maxIndexes = existingPools.map((pool) =>
bitmapIndex(
pool.activeTick + NUMBER_OF_SURROUNDING_TICKS,
this.TICK_SPACINGS[pool.fee]!,
pool.tickSpacing,
),
)
return [minIndexes, maxIndexes]
}

handleTickBoundries(
i: number,
pool: V3Pool,
poolTicks: {
index: number
DLiquidity: bigint
}[],
minIndexes: number[],
maxIndexes: number[],
) {
handleTickBoundries(tick: number, pool: V3Pool): CLTick[] {
const currentTickIndex = bitmapIndex(tick, pool.tickSpacing)
if (!pool.ticks.has(currentTickIndex)) return []
let minIndex
let maxIndex
for (minIndex = currentTickIndex; pool.ticks.has(minIndex); --minIndex);
for (maxIndex = currentTickIndex + 1; pool.ticks.has(maxIndex); ++maxIndex);
if (maxIndex - minIndex <= 1) return []

let poolTicks: CLTick[] = []
for (let i = minIndex + 1; i < maxIndex; ++i)
poolTicks = poolTicks.concat(pool.ticks.get(i)!)

const lowerUnknownTick =
minIndexes[i]! * this.TICK_SPACINGS[pool.fee]! * 256 -
this.TICK_SPACINGS[pool.fee]!
(minIndex + 1) * pool.tickSpacing * 256 - pool.tickSpacing
console.assert(
poolTicks.length === 0 || lowerUnknownTick < poolTicks[0]!.index,
'Error 236: unexpected min tick index',
Expand All @@ -230,8 +286,7 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
index: lowerUnknownTick,
DLiquidity: 0n,
})
const upperUnknownTick =
(maxIndexes[i]! + 1) * this.TICK_SPACINGS[pool.fee]! * 256
const upperUnknownTick = maxIndex * pool.tickSpacing * 256
console.assert(
poolTicks[poolTicks.length - 1]!.index < upperUnknownTick,
'Error 244: unexpected max tick index',
Expand All @@ -240,6 +295,8 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
index: upperUnknownTick,
DLiquidity: 0n,
})

return poolTicks
}

async fetchPoolsForToken(
Expand Down Expand Up @@ -448,12 +505,7 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
)
return

const poolTicks = ticks[i]!.map((tick) => ({
index: tick.tick,
DLiquidity: tick.liquidityNet,
})).sort((a, b) => a.index - b.index)

this.handleTickBoundries(i, pool, poolTicks, minIndexes, maxIndexes)
const poolTicks = this.handleTickBoundries(pool.activeTick, pool)
//console.log(pool.fee, TICK_SPACINGS[pool.fee], pool.activeTick, minIndexes[i], maxIndexes[i], poolTicks)

const v3Pool = new UniV3Pool(
Expand Down

0 comments on commit 99a5600

Please sign in to comment.