Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
rouzwelt committed Nov 1, 2024
1 parent 0f62029 commit 68913ae
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 40 deletions.
13 changes: 6 additions & 7 deletions packages/sushi/src/router/liquidity-providers/AlgebraV1Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,8 @@ export abstract class AlgebraV1BaseProvider extends UniswapV3BaseProvider {

const existingPools: V3Pool[] = []

for (let i = 0; i < staticPools.length; i++) {
if (globalState === undefined || !globalState[i]) continue
const pool = staticPools[i]!
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) {
Expand All @@ -199,20 +198,20 @@ export abstract class AlgebraV1BaseProvider extends UniswapV3BaseProvider {
const sqrtPriceX96 = globalState[i]!.result?.[0] // price
const tick = globalState[i]!.result?.[1] // tick
if (!sqrtPriceX96 || sqrtPriceX96 === 0n || typeof tick !== 'number')
continue
return
const fee = globalState[i]!.result?.[2] // fee
if (!fee) continue
if (!fee) return
const activeTick =
Math.floor(tick / thisPoolTickSpacing) * thisPoolTickSpacing
if (typeof activeTick !== 'number') continue
if (typeof activeTick !== 'number') return
this.TICK_SPACINGS[pool.address.toLowerCase()] = thisPoolTickSpacing
existingPools.push({
...pool,
fee,
sqrtPriceX96,
activeTick,
})
}
})

return existingPools
}
Expand Down
156 changes: 128 additions & 28 deletions packages/sushi/src/router/liquidity-providers/Camelot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,30 @@ import { type PoolCode } from '../pool-codes/index.js'
import { LiquidityProviders } from './LiquidityProvider.js'
import { UniswapV2BaseProvider } from './UniswapV2Base.js'

type IsStableSwap =
| (
| boolean
| {
error?: undefined
result: boolean
status: 'success'
}
| {
error: Error
result?: undefined
status: 'failure'
}
)[]
| undefined

export class CamelotProvider extends UniswapV2BaseProvider {
// Camelot has a slightly different getReserves() abi
// so needs to be overriden
override getReservesAbi = parseAbi([
'function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint16 _token0FeePercent, uint16 _token1FeePercent)',
])
FEE_DENOMINATOR = 100_000n
FEE_INFO: [bigint, `0x${string}`] | undefined = undefined
constructor(chainId: ChainId, web3Client: PublicClient) {
const factory = {
[ChainId.ARBITRUM]: '0x6EcCab422D763aC031210895C81787E87B43A652',
Expand All @@ -36,7 +53,38 @@ export class CamelotProvider extends UniswapV2BaseProvider {
): Promise<any> {
const multicallMemoize = await memoizer.fn(this.client.multicall)

const multicallData = {
if (!this.FEE_INFO) {
try {
this.FEE_INFO = (await this.client.readContract({
address: this.factory[
this.chainId as keyof typeof this.factory
]! as `0x${string}`,
abi: [
{
constant: true,
inputs: [],
name: 'feeInfo',
outputs: [
{
internalType: 'uint256',
name: '_ownerFeeShare',
type: 'uint256',
},
{ internalType: 'address', name: '_feeTo', type: 'address' },
],
payable: false,
stateMutability: 'view',
type: 'function',
},
] as const,
functionName: 'feeInfo',
})) as any
} catch (_error) {
/**/
}
}

const getReservesData = {
multicallAddress: this.client.chain?.contracts?.multicall3
?.address as Address,
allowFailure: true,
Expand All @@ -52,15 +100,15 @@ export class CamelotProvider extends UniswapV2BaseProvider {
),
}
const reserves = options?.memoize
? await (multicallMemoize(multicallData) as Promise<any>).catch((e) => {
? await (multicallMemoize(getReservesData) as Promise<any>).catch((e) => {
console.warn(
`${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${
e.message
}`,
)
return undefined
})
: await this.client.multicall(multicallData).catch((e) => {
: await this.client.multicall(getReservesData).catch((e) => {
console.warn(
`${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${
e.message
Expand All @@ -69,31 +117,83 @@ export class CamelotProvider extends UniswapV2BaseProvider {
return undefined
})

if (reserves !== undefined && Array.isArray(reserves)) {
reserves.forEach(
(reserve: {
result?: [bigint, bigint, number, number] | undefined
status: 'failure' | 'success'
}) => {
if (
reserve &&
reserve.status === 'success' &&
reserve.result !== undefined
) {
if (reserve.result?.[0]) {
reserve.result[0] -=
(reserve.result[0] * BigInt(reserve.result[2])) /
this.FEE_DENOMINATOR
}
if (reserve.result?.[1]) {
reserve.result[1] -=
(reserve.result[1] * BigInt(reserve.result[3])) /
this.FEE_DENOMINATOR
}
}
},
)
const stableSwapData = {
multicallAddress: this.client.chain?.contracts?.multicall3
?.address as Address,
allowFailure: true,
blockNumber: options?.blockNumber,
contracts: poolCodesToCreate.map(
(poolCode) =>
({
address: poolCode.pool.address as Address,
chainId: this.chainId,
abi: [
{
constant: true,
inputs: [],
name: 'stableSwap',
outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
stateMutability: 'view',
type: 'function',
payable: false,
},
] as const,
functionName: 'stableSwap',
}) as const,
),
}
return reserves
const stableSwap: IsStableSwap = options?.memoize
? await (multicallMemoize(stableSwapData) as Promise<any>).catch((e) => {
console.warn(
`${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${
e.message
}`,
)
return undefined
})
: await this.client.multicall(stableSwapData).catch((e) => {
console.warn(
`${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${
e.message
}`,
)
return undefined
})

return [reserves, stableSwap]
}

override handleCreatePoolCode(
poolCodesToCreate: PoolCode[],
contractData: [any[], IsStableSwap],
validUntilTimestamp: number,
) {
const [reserves, stableSwaps] = contractData
poolCodesToCreate.forEach((poolCode, i) => {
const thisStableSwap = stableSwaps?.[i]
const isStableSwap =
typeof thisStableSwap === 'boolean'
? thisStableSwap
: thisStableSwap?.status === 'success'
? thisStableSwap?.result
: undefined
const pool = poolCode.pool
const res0 = reserves?.[i]?.result?.[0]
const res1 = reserves?.[i]?.result?.[1]

if (res0 !== undefined && res1 !== undefined) {
if (isStableSwap && this.FEE_INFO && pool.fee) {
try {
;(pool.fee as any) +=
(Number(this.FEE_INFO[0]) / Number(this.FEE_DENOMINATOR)) *
pool.fee
} catch {}
}
pool.updateReserves(res0, res1)
this.onDemandPools.set(pool.address, { poolCode, validUntilTimestamp })
} else {
// Pool doesn't exist?
}
})
}
}
14 changes: 10 additions & 4 deletions packages/sushi/src/router/liquidity-providers/UniswapV2Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,17 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider {
})

const reserves = await this.getReserves(poolCodesToCreate, options)
this.handleCreatePoolCode(poolCodesToCreate, reserves, validUntilTimestamp)
// console.debug(
// `${this.getLogPrefix()} - ON DEMAND: Created and fetched reserves for ${created} pools, extended 'lifetime' for ${updated} pools`
// )
}

handleCreatePoolCode(
poolCodesToCreate: PoolCode[],
reserves: any[],
validUntilTimestamp: number,
) {
poolCodesToCreate.forEach((poolCode, i) => {
const pool = poolCode.pool
const res0 = reserves?.[i]?.result?.[0]
Expand All @@ -282,10 +292,6 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider {
// console.error(`${this.getLogPrefix()} - ERROR FETCHING RESERVES, initialize on demand pool: ${pool.address}`)
}
})

// console.debug(
// `${this.getLogPrefix()} - ON DEMAND: Created and fetched reserves for ${created} pools, extended 'lifetime' for ${updated} pools`
// )
}

async updatePools() {
Expand Down
4 changes: 4 additions & 0 deletions packages/sushi/src/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ export class Router {
gasPrice: number,
providers?: LiquidityProviders[], // all providers if undefined
poolFilter?: PoolFilter,
flows?: number | number[],
pickRoute?: 'single' | 'multi',
): MultiRoute {
const networks: NetworkInfo[] = [
{
Expand Down Expand Up @@ -195,6 +197,8 @@ export class Router {
pools,
networks,
gasPrice,
flows,
pickRoute,
)

return {
Expand Down
8 changes: 7 additions & 1 deletion packages/sushi/src/tines/MultiRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export function findMultiRouteExactIn(
baseTokenOrNetworks: RToken | NetworkInfo[],
gasPrice?: number,
flows?: number | number[],
pickRoute?: 'single' | 'multi',
): MultiRoute {
try {
pools = deduplicatePools(pools)
Expand All @@ -112,7 +113,12 @@ export function findMultiRouteExactIn(
if (bestFlowNumber === 1) return outSingle

const outMulti = g.findBestRouteExactIn(from, to, amountIn, bestFlowNumber)
return getBetterRouteExactIn(outSingle, outMulti)
if (pickRoute) {
if (pickRoute === 'single') return outSingle
else return outMulti
} else {
return getBetterRouteExactIn(outSingle, outMulti)
}
} catch (_e) {
return NoWayMultiRoute(from, to)
}
Expand Down

0 comments on commit 68913ae

Please sign in to comment.