Skip to content

Commit

Permalink
feat: v4 subgraph on Sepelia in routing cron (#808)
Browse files Browse the repository at this point in the history
chore(logging): add logging for 500 errors (#806)

* chore(logging): log 500 error details

* add exception error log

* npm run fix:prettier

Co-authored-by: xrsv <[email protected]>
  • Loading branch information
jsy1218 and xrsv authored Aug 9, 2024
1 parent 73ab9fb commit 35d347f
Show file tree
Hide file tree
Showing 11 changed files with 284 additions and 96 deletions.
29 changes: 28 additions & 1 deletion lib/cron/cache-config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { Protocol } from '@uniswap/router-sdk'
import { V2SubgraphProvider, V3SubgraphProvider } from '@uniswap/smart-order-router'
import { V2SubgraphProvider, V3SubgraphProvider, V4SubgraphProvider } from '@uniswap/smart-order-router'
import { ChainId } from '@uniswap/sdk-core'

// during local cdk stack update, the env vars are not populated
// make sure to fill in the env vars below
// process.env.ALCHEMY_QUERY_KEY = ''

export const v4SubgraphUrlOverride = (chainId: ChainId) => {
switch (chainId) {
case ChainId.SEPOLIA:
return `https://subgraph.satsuma-prod.com/${process.env.ALCHEMY_QUERY_KEY}/uniswap/uniswap-v4-sepolia-test/api`
default:
return undefined
}
}

export const v3SubgraphUrlOverride = (chainId: ChainId) => {
switch (chainId) {
case ChainId.MAINNET:
Expand Down Expand Up @@ -54,6 +63,10 @@ export const v2SubgraphUrlOverride = (chainId: ChainId) => {
}
}

// TODO: ROUTE-225 - follow up on v4 subgraph pools filtering threshold
const v4TrackedEthThreshold = 0 // Pools need at least 0 of trackedEth to be selected
const v4UntrackedUsdThreshold = 0 // Pools need at least 0k USD (untracked) to be selected (for metrics only)

export const v3TrackedEthThreshold = 0.01 // Pools need at least 0.01 of trackedEth to be selected
const v3UntrackedUsdThreshold = 25000 // Pools need at least 25K USD (untracked) to be selected (for metrics only)

Expand Down Expand Up @@ -311,4 +324,18 @@ export const chainProtocols = [
v2SubgraphUrlOverride(ChainId.BLAST)
),
},
{
protocol: Protocol.V4,
chainId: ChainId.SEPOLIA,
timeout: 90000,
provider: new V4SubgraphProvider(
ChainId.SEPOLIA,
3,
90000,
true,
v4TrackedEthThreshold,
v4UntrackedUsdThreshold,
v4SubgraphUrlOverride(ChainId.SEPOLIA)
),
},
]
9 changes: 4 additions & 5 deletions lib/handlers/marshalling/cached-route-marshaller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { CachedRoute } from '@uniswap/smart-order-router'
import { MixedRoute, V2Route, V3Route } from '@uniswap/smart-order-router/build/main/routers'
import { CachedRoute, SupportedRoutes } from '@uniswap/smart-order-router'
import { MarshalledRoute, RouteMarshaller } from './route-marshaller'

export interface MarshalledCachedRoute {
Expand All @@ -8,15 +7,15 @@ export interface MarshalledCachedRoute {
}

export class CachedRouteMarshaller {
public static marshal(cachedRoute: CachedRoute<V3Route | V2Route | MixedRoute>): MarshalledCachedRoute {
public static marshal(cachedRoute: CachedRoute<SupportedRoutes>): MarshalledCachedRoute {
return {
route: RouteMarshaller.marshal(cachedRoute.route),
percent: cachedRoute.percent,
}
}

public static unmarshal(marshalledCachedRoute: MarshalledCachedRoute): CachedRoute<V3Route | V2Route | MixedRoute> {
return new CachedRoute<V3Route | V2Route | MixedRoute>({
public static unmarshal(marshalledCachedRoute: MarshalledCachedRoute): CachedRoute<SupportedRoutes> {
return new CachedRoute<SupportedRoutes>({
route: RouteMarshaller.unmarshal(marshalledCachedRoute.route),
percent: marshalledCachedRoute.percent,
})
Expand Down
2 changes: 1 addition & 1 deletion lib/handlers/marshalling/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ export * from './cached-route-marshaller'
export * from './cached-routes-marshaller'
export * from './currency-amount-marshaller'
export * from './pair-marshaller'
export * from './pool-marshaller'
export * from './v3/pool-marshaller'
export * from './route-marshaller'
export * from './token-marshaller'
72 changes: 56 additions & 16 deletions lib/handlers/marshalling/route-marshaller.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { MixedRoute, V2Route, V3Route } from '@uniswap/smart-order-router/build/main/routers'
import { MixedRoute, V2Route, V3Route, V4Route } from '@uniswap/smart-order-router/build/main/routers'
import { Protocol } from '@uniswap/router-sdk'
import { MarshalledToken, TokenMarshaller } from './token-marshaller'
import { MarshalledPair, PairMarshaller } from './pair-marshaller'
import { MarshalledPool, PoolMarshaller } from './pool-marshaller'
import { Pool } from '@uniswap/v3-sdk'
import { MarshalledPool as V3MarshalledPool, PoolMarshaller as V3PoolMarshaller } from './v3/pool-marshaller'
import { MarshalledPool as V4MarshalledPool, PoolMarshaller as V4PoolMarshaller } from './v4/pool-marshaller'
import { Pool as V3Pool } from '@uniswap/v3-sdk'
import { Pool as V4Pool } from '@uniswap/v4-sdk'
import { SupportedRoutes } from '@uniswap/smart-order-router'
import { Pair } from '@uniswap/v2-sdk'

export interface MarshalledV2Route {
protocol: Protocol
Expand All @@ -16,20 +20,27 @@ export interface MarshalledV3Route {
protocol: Protocol
input: MarshalledToken
output: MarshalledToken
pools: MarshalledPool[]
pools: V3MarshalledPool[]
}

export interface MarshalledV4Route {
protocol: Protocol
input: MarshalledToken
output: MarshalledToken
pools: V4MarshalledPool[]
}

export interface MarshalledMixedRoute {
protocol: Protocol
input: MarshalledToken
output: MarshalledToken
pools: (MarshalledPool | MarshalledPair)[]
pools: (V4MarshalledPool | V3MarshalledPool | MarshalledPair)[]
}

export type MarshalledRoute = MarshalledV2Route | MarshalledV3Route | MarshalledMixedRoute

export class RouteMarshaller {
public static marshal(route: V3Route | V2Route | MixedRoute): MarshalledRoute {
public static marshal(route: SupportedRoutes): MarshalledRoute {
switch (route.protocol) {
case Protocol.V2:
return {
Expand All @@ -43,25 +54,42 @@ export class RouteMarshaller {
protocol: Protocol.V3,
input: TokenMarshaller.marshal(route.input),
output: TokenMarshaller.marshal(route.output),
pools: route.pools.map((pool) => PoolMarshaller.marshal(pool)),
pools: route.pools.map((pool) => V3PoolMarshaller.marshal(pool)),
}
case Protocol.V4:
return {
protocol: Protocol.V4,
// TODO: ROUTE-217 - Support native currency routing in V4
// token.wrapped is wrong for V4
// Probably need to use the token symbol for native, and still use address for non-native tokens
// Check later CELO token, which is both native and ERC20, which one to use
input: TokenMarshaller.marshal(route.input.wrapped),
output: TokenMarshaller.marshal(route.output.wrapped),
pools: route.pools.map((pool) => V4PoolMarshaller.marshal(pool)),
}
case Protocol.MIXED:
return {
protocol: Protocol.MIXED,
input: TokenMarshaller.marshal(route.input),
output: TokenMarshaller.marshal(route.output),
pools: route.pools.map((tpool) => {
if (tpool instanceof Pool) {
return PoolMarshaller.marshal(tpool)
} else {
if (tpool instanceof V3Pool) {
return V3PoolMarshaller.marshal(tpool)
} else if (tpool instanceof V4Pool) {
return V4PoolMarshaller.marshal(tpool)
} else if (tpool instanceof Pair) {
return PairMarshaller.marshal(tpool)
} else {
throw new Error(`Unsupported pool type ${JSON.stringify(tpool)}`)
}
}),
}
default:
throw new Error(`Unsupported protocol ${JSON.stringify(route)}`)
}
}

public static unmarshal(marshalledRoute: MarshalledRoute): V3Route | V2Route | MixedRoute {
public static unmarshal(marshalledRoute: MarshalledRoute): SupportedRoutes {
switch (marshalledRoute.protocol) {
case Protocol.V2:
const v2Route = marshalledRoute as MarshalledV2Route
Expand All @@ -73,17 +101,29 @@ export class RouteMarshaller {
case Protocol.V3:
const v3Route = marshalledRoute as MarshalledV3Route
return new V3Route(
v3Route.pools.map((marshalledPool) => PoolMarshaller.unmarshal(marshalledPool)),
v3Route.pools.map((marshalledPool) => V3PoolMarshaller.unmarshal(marshalledPool)),
TokenMarshaller.unmarshal(v3Route.input),
TokenMarshaller.unmarshal(v3Route.output)
)
case Protocol.V4:
const v4Route = marshalledRoute as MarshalledV4Route
return new V4Route(
v4Route.pools.map((marshalledPool) => V4PoolMarshaller.unmarshal(marshalledPool)),
TokenMarshaller.unmarshal(v4Route.input),
TokenMarshaller.unmarshal(v4Route.output)
)
case Protocol.MIXED:
const mixedRoute = marshalledRoute as MarshalledMixedRoute
const tpools = mixedRoute.pools.map((tpool) => {
if (tpool.protocol === Protocol.V2) {
return PairMarshaller.unmarshal(tpool as MarshalledPair)
} else {
return PoolMarshaller.unmarshal(tpool as MarshalledPool)
switch (tpool.protocol) {
case Protocol.V2:
return PairMarshaller.unmarshal(tpool as MarshalledPair)
case Protocol.V3:
return V3PoolMarshaller.unmarshal(tpool as V3MarshalledPool)
case Protocol.V4:
return V4PoolMarshaller.unmarshal(tpool as V4MarshalledPool)
default:
throw new Error(`Unsupported protocol ${JSON.stringify(tpool)}`)
}
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Pool } from '@uniswap/v3-sdk'
import { FeeAmount } from '@uniswap/v3-sdk/dist/constants'
import { MarshalledToken, TokenMarshaller } from './token-marshaller'
import { MarshalledToken, TokenMarshaller } from '../token-marshaller'
import { Protocol } from '@uniswap/router-sdk'

export interface MarshalledPool {
Expand Down
47 changes: 47 additions & 0 deletions lib/handlers/marshalling/v4/pool-marshaller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Pool } from '@uniswap/v4-sdk'
import { FeeAmount } from '@uniswap/v3-sdk/dist/constants'
import { MarshalledToken, TokenMarshaller } from '../token-marshaller'
import { Protocol } from '@uniswap/router-sdk'

export interface MarshalledPool {
protocol: Protocol
token0: MarshalledToken
token1: MarshalledToken
fee: FeeAmount
tickSpacing: number
hooks: string
sqrtRatioX96: string
liquidity: string
tickCurrent: number
}

export class PoolMarshaller {
public static marshal(pool: Pool): MarshalledPool {
return {
protocol: Protocol.V4,
// TODO: ROUTE-217 - Support native currency routing in V4
// V4 we should not just wrap
token0: TokenMarshaller.marshal(pool.token0.wrapped),
token1: TokenMarshaller.marshal(pool.token1.wrapped),
fee: pool.fee,
tickSpacing: pool.tickSpacing,
hooks: pool.hooks,
sqrtRatioX96: pool.sqrtRatioX96.toString(),
liquidity: pool.liquidity.toString(),
tickCurrent: pool.tickCurrent,
}
}

public static unmarshal(marshalledPool: MarshalledPool): Pool {
return new Pool(
TokenMarshaller.unmarshal(marshalledPool.token0),
TokenMarshaller.unmarshal(marshalledPool.token1),
marshalledPool.fee,
marshalledPool.tickSpacing,
marshalledPool.hooks,
marshalledPool.sqrtRatioX96,
marshalledPool.liquidity,
marshalledPool.tickCurrent
)
}
}
2 changes: 1 addition & 1 deletion lib/handlers/pools/pool-caching/v3/cache-dynamo-pool.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DynamoCaching, DynamoCachingProps } from '../cache-dynamo'
import { Pool } from '@uniswap/v3-sdk'
import { log, metric, MetricLoggerUnit } from '@uniswap/smart-order-router'
import { PoolMarshaller } from '../../../marshalling/pool-marshaller'
import { PoolMarshaller } from '../../../marshalling/v3/pool-marshaller'

interface DynamoCachingV3PoolProps extends DynamoCachingProps {}

Expand Down
21 changes: 14 additions & 7 deletions lib/handlers/quote/quote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
SwapOptions,
SwapRoute,
} from '@uniswap/smart-order-router'
import { Pool } from '@uniswap/v3-sdk'
import { Pool as V3Pool } from '@uniswap/v3-sdk'
import { Pool as V4Pool } from '@uniswap/v4-sdk'
import JSBI from 'jsbi'
import _ from 'lodash'
import { APIGLambdaHandler, ErrorResponse, HandleRequestParams, Response } from '../handler'
Expand All @@ -35,6 +36,7 @@ import { SwapOptionsFactory } from './SwapOptionsFactory'
import { GlobalRpcProviders } from '../../rpc/GlobalRpcProviders'
import { adhocCorrectGasUsed } from '../../util/estimateGasUsed'
import { adhocCorrectGasUsedUSD } from '../../util/estimateGasUsedUSD'
import { Pair } from '@uniswap/v2-sdk'

export class QuoteHandler extends APIGLambdaHandler<
ContainerInjected,
Expand Down Expand Up @@ -502,20 +504,23 @@ export class QuoteHandler extends APIGLambdaHandler<
edgeAmountOut = type == 'exactIn' ? quote.quotient.toString() : amount.quotient.toString()
}

if (nextPool instanceof Pool) {
if (nextPool instanceof V4Pool) {
// TODO - ROUTE-220: Support V4 Pool
throw new Error(`V4 pools are not supported in quote response deserialization ${JSON.stringify(nextPool)}`)
} else if (nextPool instanceof V3Pool) {
curRoute.push({
type: 'v3-pool',
address: v3PoolProvider.getPoolAddress(nextPool.token0, nextPool.token1, nextPool.fee).poolAddress,
tokenIn: {
chainId: tokenIn.chainId,
decimals: tokenIn.decimals.toString(),
address: tokenIn.address,
address: tokenIn.wrapped.address,
symbol: tokenIn.symbol!,
},
tokenOut: {
chainId: tokenOut.chainId,
decimals: tokenOut.decimals.toString(),
address: tokenOut.address,
address: tokenOut.wrapped.address,
symbol: tokenOut.symbol!,
},
fee: nextPool.fee.toString(),
Expand All @@ -525,7 +530,7 @@ export class QuoteHandler extends APIGLambdaHandler<
amountIn: edgeAmountIn,
amountOut: edgeAmountOut,
})
} else {
} else if (nextPool instanceof Pair) {
const reserve0 = nextPool.reserve0
const reserve1 = nextPool.reserve1

Expand All @@ -535,15 +540,15 @@ export class QuoteHandler extends APIGLambdaHandler<
tokenIn: {
chainId: tokenIn.chainId,
decimals: tokenIn.decimals.toString(),
address: tokenIn.address,
address: tokenIn.wrapped.address,
symbol: tokenIn.symbol!,
buyFeeBps: this.deriveBuyFeeBps(tokenIn, reserve0, reserve1, enableFeeOnTransferFeeFetching),
sellFeeBps: this.deriveSellFeeBps(tokenIn, reserve0, reserve1, enableFeeOnTransferFeeFetching),
},
tokenOut: {
chainId: tokenOut.chainId,
decimals: tokenOut.decimals.toString(),
address: tokenOut.address,
address: tokenOut.wrapped.address,
symbol: tokenOut.symbol!,
buyFeeBps: this.deriveBuyFeeBps(tokenOut, reserve0, reserve1, enableFeeOnTransferFeeFetching),
sellFeeBps: this.deriveSellFeeBps(tokenOut, reserve0, reserve1, enableFeeOnTransferFeeFetching),
Expand Down Expand Up @@ -593,6 +598,8 @@ export class QuoteHandler extends APIGLambdaHandler<
amountIn: edgeAmountIn,
amountOut: edgeAmountOut,
})
} else {
throw new Error(`Unsupported pool type ${JSON.stringify(nextPool)}`)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import {
metric,
MetricLoggerUnit,
routeToString,
SupportedRoutes,
} from '@uniswap/smart-order-router'
import { AWSError, DynamoDB, Lambda } from 'aws-sdk'
import { ChainId, Currency, CurrencyAmount, Fraction, Token, TradeType } from '@uniswap/sdk-core'
import { Protocol } from '@uniswap/router-sdk'
import { PairTradeTypeChainId } from './model/pair-trade-type-chain-id'
import { CachedRoutesMarshaller } from '../../marshalling/cached-routes-marshaller'
import { MixedRoute, V2Route, V3Route } from '@uniswap/smart-order-router/build/main/routers'
import { PromiseResult } from 'aws-sdk/lib/request'

interface ConstructorParams {
Expand Down Expand Up @@ -208,7 +208,7 @@ export class DynamoRouteCachingProvider extends IRouteCachingProvider {
return CachedRoutesMarshaller.unmarshal(cachedRoutesJson)
})

const routesMap: Map<string, CachedRoute<V3Route | V2Route | MixedRoute>> = new Map()
const routesMap: Map<string, CachedRoute<SupportedRoutes>> = new Map()
let blockNumber: number = 0
let originalAmount: string = ''

Expand Down
Loading

0 comments on commit 35d347f

Please sign in to comment.