Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
rouzwelt committed Jun 26, 2024
1 parent 57ebbb6 commit 1718798
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { PublicClient } from 'viem'
import { ChainId } from '../../chain/index.js'
// import {
// PANCAKESWAP_V3_FEE_SPACING_MAP,
// PancakeSwapV3FeeAmount,
// } from '../../config/index.js'
import { LiquidityProviders } from './LiquidityProvider.js'
import { UniswapV3BaseProvider } from './UniswapV3Base.js'

export class PancakeSwapV3Provider extends UniswapV3BaseProvider {
// override FEE = PancakeSwapV3FeeAmount
// override TICK_SPACINGS = PANCAKESWAP_V3_FEE_SPACING_MAP
constructor(chainId: ChainId, web3Client: PublicClient) {
const factory = {
[ChainId.ARBITRUM]: '0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9',
Expand Down
79 changes: 47 additions & 32 deletions packages/sushi/src/router/liquidity-providers/UniswapV3Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,44 @@ import { memoizer } from '../memoizer.js'
import { type PoolCode, UniV3PoolCode } from '../pool-codes/index.js'
import { LiquidityProvider } from './LiquidityProvider.js'

export interface UniV3FeeType {
readonly LOWEST: number
readonly LOW: number
readonly MEDIUM: number
readonly HIGH: number
}

export type UniV3TickSpacingType = {
readonly [key: UniV3FeeType[keyof UniV3FeeType]]: number
}

interface StaticPool {
address: Address
token0: Token
token1: Token
fee: SushiSwapV3FeeAmount
fee: keyof UniV3TickSpacingType
}

interface V3Pool {
address: Address
token0: Token
token1: Token
fee: SushiSwapV3FeeAmount
fee: keyof UniV3TickSpacingType
sqrtPriceX96: bigint
activeTick: number
}

export const NUMBER_OF_SURROUNDING_TICKS = 1000 // 10% price impact

const getActiveTick = (tickCurrent: number, feeAmount: SushiSwapV3FeeAmount) =>
typeof tickCurrent === 'number' && feeAmount
? Math.floor(tickCurrent / TICK_SPACINGS[feeAmount]) *
TICK_SPACINGS[feeAmount]
: undefined

const bitmapIndex = (tick: number, tickSpacing: number) => {
return Math.floor(tick / tickSpacing / 256)
}

type PoolFilter = { has: (arg: string) => boolean }

export abstract class UniswapV3BaseProvider extends LiquidityProvider {
TICK_SPACINGS: UniV3TickSpacingType = TICK_SPACINGS
FEE: UniV3FeeType = SushiSwapV3FeeAmount
poolsByTrade: Map<string, string[]> = new Map()
pools: Map<string, PoolCode> = new Map()

Expand Down Expand Up @@ -76,6 +83,15 @@ 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]!
: undefined

async fetchPoolsForToken(
t0: Token,
t1: Token,
Expand Down Expand Up @@ -165,7 +181,7 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
const tick = slot0[i]!.result?.[1]
if (!sqrtPriceX96 || sqrtPriceX96 === 0n || typeof tick !== 'number')
return
const activeTick = getActiveTick(tick, pool.fee)
const activeTick = this.getActiveTick(tick, pool.fee)
if (typeof activeTick !== 'number') return
existingPools.push({
...pool,
Expand Down Expand Up @@ -287,13 +303,13 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
const minIndexes = existingPools.map((pool) =>
bitmapIndex(
pool.activeTick - NUMBER_OF_SURROUNDING_TICKS,
TICK_SPACINGS[pool.fee],
this.TICK_SPACINGS[pool.fee]!,
),
)
const maxIndexes = existingPools.map((pool) =>
bitmapIndex(
pool.activeTick + NUMBER_OF_SURROUNDING_TICKS,
TICK_SPACINGS[pool.fee],
this.TICK_SPACINGS[pool.fee]!,
),
)

Expand Down Expand Up @@ -383,7 +399,8 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
})).sort((a, b) => a.index - b.index)

const lowerUnknownTick =
minIndexes[i]! * TICK_SPACINGS[pool.fee] * 256 - TICK_SPACINGS[pool.fee]
minIndexes[i]! * this.TICK_SPACINGS[pool.fee]! * 256 -
this.TICK_SPACINGS[pool.fee]!
console.assert(
poolTicks.length === 0 || lowerUnknownTick < poolTicks[0]!.index,
'Error 236: unexpected min tick index',
Expand All @@ -393,7 +410,7 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
DLiquidity: 0n,
})
const upperUnknownTick =
(maxIndexes[i]! + 1) * TICK_SPACINGS[pool.fee] * 256
(maxIndexes[i]! + 1) * this.TICK_SPACINGS[pool.fee]! * 256
console.assert(
poolTicks[poolTicks.length - 1]!.index < upperUnknownTick,
'Error 244: unexpected max tick index',
Expand Down Expand Up @@ -435,25 +452,23 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider {
getStaticPools(t1: Token, t2: Token): StaticPool[] {
const currencyCombinations = getCurrencyCombinations(this.chainId, t1, t2)

const allCurrencyCombinationsWithAllFees: [
Type,
Type,
SushiSwapV3FeeAmount,
][] = currencyCombinations.reduce<
[Currency, Currency, SushiSwapV3FeeAmount][]
>((list, [tokenA, tokenB]) => {
if (tokenA !== undefined && tokenB !== undefined) {
return list.concat([
[tokenA, tokenB, SushiSwapV3FeeAmount.LOWEST],
[tokenA, tokenB, SushiSwapV3FeeAmount.LOW],
[tokenA, tokenB, SushiSwapV3FeeAmount.MEDIUM],
[tokenA, tokenB, SushiSwapV3FeeAmount.HIGH],
])
}
return []
}, [])

const filtered: [Token, Token, SushiSwapV3FeeAmount][] = []
const allCurrencyCombinationsWithAllFees: [Type, Type, number][] =
currencyCombinations.reduce<[Currency, Currency, number][]>(
(list, [tokenA, tokenB]) => {
if (tokenA !== undefined && tokenB !== undefined) {
return list.concat([
[tokenA, tokenB, this.FEE.LOWEST],
[tokenA, tokenB, this.FEE.LOW],
[tokenA, tokenB, this.FEE.MEDIUM],
[tokenA, tokenB, this.FEE.HIGH],
])
}
return []
},
[],
)

const filtered: [Token, Token, number][] = []
allCurrencyCombinationsWithAllFees.forEach(
([currencyA, currencyB, feeAmount]) => {
if (currencyA && currencyB && feeAmount) {
Expand Down
Loading

0 comments on commit 1718798

Please sign in to comment.