Skip to content

Commit

Permalink
chore: bump sor to 3.46.0 - feat: implement best swap route with v4 r…
Browse files Browse the repository at this point in the history
  • Loading branch information
jsy1218 authored Aug 29, 2024
1 parent 31e08ac commit e429e64
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 22 deletions.
22 changes: 18 additions & 4 deletions lib/handlers/injector-sor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
NodeJSCache,
OnChainGasPriceProvider,
OnChainQuoteProvider,
PROTOCOL_V4_QUOTER_ADDRESSES,
QUOTER_V2_ADDRESSES,
setGlobalLogger,
Simulator,
Expand Down Expand Up @@ -104,6 +105,7 @@ const DEFAULT_TOKEN_LIST = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org'
export interface RequestInjected<Router> extends BaseRInj {
chainId: ChainId
metric: IMetric
v4PoolProvider: IV4PoolProvider
v3PoolProvider: IV3PoolProvider
v2PoolProvider: IV2PoolProvider
tokenProvider: ITokenProvider
Expand All @@ -122,6 +124,7 @@ export type ContainerDependencies = {
gasPriceProvider: IGasPriceProvider
tokenProviderFromTokenList: ITokenProvider
blockedTokenListProvider: ITokenListProvider
v4PoolProvider: IV4PoolProvider
v3PoolProvider: IV3PoolProvider
v2PoolProvider: IV2PoolProvider
tokenProvider: ITokenProvider
Expand Down Expand Up @@ -358,8 +361,12 @@ export abstract class InjectorSOR<Router, QueryParams> extends Injector<
SUCCESS_RATE_FAILURE_OVERRIDES[chainId],
BLOCK_NUMBER_CONFIGS[chainId],
// We will only enable shadow sample mixed quoter on Base
(useMixedRouteQuoter: boolean) =>
useMixedRouteQuoter ? MIXED_ROUTE_QUOTER_V1_ADDRESSES[chainId] : QUOTER_V2_ADDRESSES[chainId]
(useMixedRouteQuoter: boolean, protocol: Protocol) =>
useMixedRouteQuoter
? MIXED_ROUTE_QUOTER_V1_ADDRESSES[chainId]
: protocol === Protocol.V3
? QUOTER_V2_ADDRESSES[chainId]
: PROTOCOL_V4_QUOTER_ADDRESSES[chainId]
)
const targetQuoteProvider = new OnChainQuoteProvider(
chainId,
Expand All @@ -375,8 +382,12 @@ export abstract class InjectorSOR<Router, QueryParams> extends Injector<
GAS_ERROR_FAILURE_OVERRIDES[chainId],
SUCCESS_RATE_FAILURE_OVERRIDES[chainId],
BLOCK_NUMBER_CONFIGS[chainId],
(useMixedRouteQuoter: boolean) =>
useMixedRouteQuoter ? MIXED_ROUTE_QUOTER_V1_ADDRESSES[chainId] : NEW_QUOTER_V2_ADDRESSES[chainId],
(useMixedRouteQuoter: boolean, protocol: Protocol) =>
useMixedRouteQuoter
? MIXED_ROUTE_QUOTER_V1_ADDRESSES[chainId]
: protocol === Protocol.V3
? NEW_QUOTER_V2_ADDRESSES[chainId]
: PROTOCOL_V4_QUOTER_ADDRESSES[chainId],
(chainId: ChainId, useMixedRouteQuoter: boolean, optimisticCachedRoutes: boolean) =>
useMixedRouteQuoter
? `ChainId_${chainId}_ShadowMixedQuoter_OptimisticCachedRoutes${optimisticCachedRoutes}_`
Expand Down Expand Up @@ -447,6 +458,8 @@ export abstract class InjectorSOR<Router, QueryParams> extends Injector<
ChainId.BLAST,
]

const v4Supported = [ChainId.SEPOLIA]

return {
chainId,
dependencies: {
Expand Down Expand Up @@ -478,6 +491,7 @@ export abstract class InjectorSOR<Router, QueryParams> extends Injector<
tokenValidatorProvider,
tokenPropertiesProvider,
v2Supported,
v4Supported,
},
}
})
Expand Down
5 changes: 5 additions & 0 deletions lib/handlers/quote/injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ export class QuoteHandlerInjector extends InjectorSOR<

const {
provider,
v4PoolProvider,
v4SubgraphProvider,
v3PoolProvider,
multicallProvider,
tokenProvider,
Expand Down Expand Up @@ -115,6 +117,8 @@ export class QuoteHandlerInjector extends InjectorSOR<
router = new AlphaRouter({
chainId,
provider,
v4SubgraphProvider,
v4PoolProvider,
v3SubgraphProvider,
multicall2Provider: multicallProvider,
v3PoolProvider,
Expand All @@ -141,6 +145,7 @@ export class QuoteHandlerInjector extends InjectorSOR<
log,
metric,
router,
v4PoolProvider,
v3PoolProvider,
v2PoolProvider,
tokenProvider,
Expand Down
42 changes: 37 additions & 5 deletions lib/handlers/quote/quote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import JSBI from 'jsbi'
import _ from 'lodash'
import { APIGLambdaHandler, ErrorResponse, HandleRequestParams, Response } from '../handler'
import { ContainerInjected, RequestInjected } from '../injector-sor'
import { QuoteResponse, QuoteResponseSchemaJoi, V2PoolInRoute, V3PoolInRoute } from '../schema'
import { QuoteResponse, QuoteResponseSchemaJoi, SupportedPoolInRoute } from '../schema'
import {
DEFAULT_ROUTING_CONFIG_BY_CHAIN,
FEE_ON_TRANSFER_SPECIFIC_CONFIG,
Expand Down Expand Up @@ -235,6 +235,7 @@ export class QuoteHandler extends APIGLambdaHandler<
chainId,
tokenProvider,
tokenListProvider,
v4PoolProvider: v4PoolProvider,
v3PoolProvider: v3PoolProvider,
v2PoolProvider: v2PoolProvider,
metric,
Expand Down Expand Up @@ -482,13 +483,13 @@ export class QuoteHandler extends APIGLambdaHandler<
metric.putMetric('SimulationNotSupported', 1, MetricLoggerUnit.Count)
}

const routeResponse: Array<(V3PoolInRoute | V2PoolInRoute)[]> = []
const routeResponse: Array<SupportedPoolInRoute[]> = []

for (const subRoute of route) {
const { amount, quote, tokenPath } = subRoute

const pools = subRoute.protocol == Protocol.V2 ? subRoute.route.pairs : subRoute.route.pools
const curRoute: (V3PoolInRoute | V2PoolInRoute)[] = []
const curRoute: SupportedPoolInRoute[] = []
for (let i = 0; i < pools.length; i++) {
const nextPool = pools[i]
const tokenIn = tokenPath[i]
Expand All @@ -505,8 +506,36 @@ export class QuoteHandler extends APIGLambdaHandler<
}

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)}`)
curRoute.push({
type: 'v4-pool',
address: v4PoolProvider.getPoolId(
nextPool.token0,
nextPool.token1,
nextPool.fee,
nextPool.tickSpacing,
nextPool.hooks
).poolId,
tokenIn: {
chainId: tokenIn.chainId,
decimals: tokenIn.decimals.toString(),
address: tokenIn.wrapped.address,
symbol: tokenIn.symbol!,
},
tokenOut: {
chainId: tokenOut.chainId,
decimals: tokenOut.decimals.toString(),
address: tokenOut.wrapped.address,
symbol: tokenOut.symbol!,
},
fee: nextPool.fee.toString(),
tickSpacing: nextPool.tickSpacing.toString(),
hooks: nextPool.hooks.toString(),
liquidity: nextPool.liquidity.toString(),
sqrtRatioX96: nextPool.sqrtRatioX96.toString(),
tickCurrent: nextPool.tickCurrent.toString(),
amountIn: edgeAmountIn,
amountOut: edgeAmountOut,
})
} else if (nextPool instanceof V3Pool) {
curRoute.push({
type: 'v3-pool',
Expand Down Expand Up @@ -679,6 +708,9 @@ export class QuoteHandler extends APIGLambdaHandler<
case Protocol.V3:
protocols.push(Protocol.V3)
break
case Protocol.V4:
protocols.push(Protocol.V4)
break
case Protocol.MIXED:
if (chainId === ChainId.MAINNET || !excludeV2) {
protocols.push(Protocol.MIXED)
Expand Down
2 changes: 1 addition & 1 deletion lib/handlers/quote/schema/quote-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const QuoteQueryParamsJoi = Joi.object({
minSplits: Joi.number().max(7).optional(),
forceCrossProtocol: Joi.boolean().optional(),
forceMixedRoutes: Joi.boolean().optional(),
protocols: Joi.stringArray().items(Joi.string().valid('v2', 'v3', 'mixed')).optional(),
protocols: Joi.stringArray().items(Joi.string().valid('v2', 'v3', 'v4', 'mixed')).optional(),
simulateFromAddress: Joi.string().alphanum().max(42).optional(),
permitSignature: Joi.string().optional(),
permitNonce: Joi.string().optional(),
Expand Down
19 changes: 18 additions & 1 deletion lib/handlers/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@ export type TokenInRoute = {
sellFeeBps?: string
}

export type SupportedPoolInRoute = V2PoolInRoute | V3PoolInRoute | V4PoolInRoute

export type V4PoolInRoute = {
type: 'v4-pool'
address: string
tokenIn: TokenInRoute
tokenOut: TokenInRoute
sqrtRatioX96: string
liquidity: string
tickCurrent: string
fee: string
tickSpacing: string
hooks: string
amountIn?: string
amountOut?: string
}

export type V3PoolInRoute = {
type: 'v3-pool'
address: string
Expand Down Expand Up @@ -94,7 +111,7 @@ export type QuoteResponse = {
simulationStatus: RoutingApiSimulationStatus
gasPriceWei: string
blockNumber: string
route: Array<(V3PoolInRoute | V2PoolInRoute)[]>
route: Array<SupportedPoolInRoute[]>
routeString: string
methodParameters?: MethodParameters
hitsCachedRoutes?: boolean
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
"@uniswap/router-sdk": "^1.10.0",
"@uniswap/sdk-core": "^5.3.0",
"@types/semver": "^7.5.8",
"@uniswap/smart-order-router": "3.45.0",
"@uniswap/smart-order-router": "3.46.0",
"@uniswap/token-lists": "^1.0.0-beta.33",
"@uniswap/universal-router-sdk": "^2.2.4",
"@uniswap/v2-sdk": "^4.3.2",
Expand Down
17 changes: 14 additions & 3 deletions test/mocha/e2e/quote.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import {
USDC_NATIVE_OPTIMISM,
USDC_NATIVE_POLYGON,
USDT_MAINNET,
V4_SEPOLIA_TEST_OP,
V4_SEPOLIA_TEST_USDC,
WBTC_MAINNET,
} from '@uniswap/smart-order-router'
import {
Expand Down Expand Up @@ -2482,6 +2484,7 @@ describe('quote', function () {
[ChainId.MAINNET]: () => USDC_ON(1),
[ChainId.GOERLI]: () => USDC_ON(ChainId.GOERLI),
[ChainId.SEPOLIA]: () => USDC_ON(ChainId.SEPOLIA),
[ChainId.SEPOLIA]: () => V4_SEPOLIA_TEST_OP,
[ChainId.OPTIMISM]: () => USDC_ON(ChainId.OPTIMISM),
[ChainId.OPTIMISM]: () => USDC_NATIVE_OPTIMISM,
[ChainId.OPTIMISM_GOERLI]: () => USDC_ON(ChainId.OPTIMISM_GOERLI),
Expand Down Expand Up @@ -2514,6 +2517,7 @@ describe('quote', function () {
[ChainId.MAINNET]: () => DAI_ON(1),
[ChainId.GOERLI]: () => DAI_ON(ChainId.GOERLI),
[ChainId.SEPOLIA]: () => DAI_ON(ChainId.SEPOLIA),
[ChainId.SEPOLIA]: () => V4_SEPOLIA_TEST_USDC,
[ChainId.OPTIMISM]: () => DAI_ON(ChainId.OPTIMISM),
[ChainId.OPTIMISM_GOERLI]: () => DAI_ON(ChainId.OPTIMISM_GOERLI),
[ChainId.OPTIMISM_SEPOLIA]: () => USDC_ON(ChainId.OPTIMISM_SEPOLIA),
Expand Down Expand Up @@ -2563,6 +2567,11 @@ describe('quote', function () {
const wrappedNative = WNATIVE_ON(chain)

it(`${wrappedNative.symbol} -> erc20`, async () => {
if (chain === ChainId.SEPOLIA && erc1.equals(V4_SEPOLIA_TEST_OP)) {
// there's no WETH/USDC v4 pool on Sepolia
return
}

// Current WETH/USDB pool (https://blastscan.io/address/0xf52b4b69123cbcf07798ae8265642793b2e8990c) has low WETH amount
const amount = chain === ChainId.BLAST ? (type === 'exactOut' ? '0.002' : '0.01') : '1'

Expand Down Expand Up @@ -2620,8 +2629,8 @@ describe('quote', function () {
}
})

it(`erc20 -> erc20`, async () => {
if (chain === ChainId.SEPOLIA) {
it(`${erc1.symbol} -> ${erc2.symbol}`, async () => {
if (chain === ChainId.SEPOLIA && !erc1.equals(V4_SEPOLIA_TEST_OP)) {
// Sepolia doesn't have sufficient liquidity on DAI pools yet
return
}
Expand All @@ -2635,6 +2644,7 @@ describe('quote', function () {
tokenOutAddress: erc2.address,
tokenOutChainId: chain,
amount: await getAmountFromToken(type, erc1, erc2, amount),
protocols: 'v2,v3,v4,mixed',
type,
}

Expand Down Expand Up @@ -2689,7 +2699,7 @@ describe('quote', function () {
}
})
it(`has quoteGasAdjusted values`, async () => {
if (chain === ChainId.SEPOLIA) {
if (chain === ChainId.SEPOLIA && !erc1.equals(V4_SEPOLIA_TEST_OP)) {
// Sepolia doesn't have sufficient liquidity on DAI pools yet
return
}
Expand All @@ -2703,6 +2713,7 @@ describe('quote', function () {
tokenOutAddress: erc2.address,
tokenOutChainId: chain,
amount: await getAmountFromToken(type, erc1, erc2, amount),
protocols: 'v2,v3,v4,mixed',
type,
}

Expand Down

0 comments on commit e429e64

Please sign in to comment.