@ring-protocol/smart-order-router 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (606) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/LICENSE +674 -0
  3. package/README.md +307 -0
  4. package/build/main/index.d.ts +3 -0
  5. package/build/main/index.js +20 -0
  6. package/build/main/providers/cache-node.d.ts +10 -0
  7. package/build/main/providers/cache-node.js +33 -0
  8. package/build/main/providers/cache.d.ts +14 -0
  9. package/build/main/providers/cache.js +3 -0
  10. package/build/main/providers/caching/route/index.d.ts +2 -0
  11. package/build/main/providers/caching/route/index.js +19 -0
  12. package/build/main/providers/caching/route/model/cache-mode.d.ts +16 -0
  13. package/build/main/providers/caching/route/model/cache-mode.js +21 -0
  14. package/build/main/providers/caching/route/model/cached-route.d.ts +29 -0
  15. package/build/main/providers/caching/route/model/cached-route.js +77 -0
  16. package/build/main/providers/caching/route/model/cached-routes.d.ts +67 -0
  17. package/build/main/providers/caching/route/model/cached-routes.js +81 -0
  18. package/build/main/providers/caching/route/model/index.d.ts +3 -0
  19. package/build/main/providers/caching/route/model/index.js +20 -0
  20. package/build/main/providers/caching/route/route-caching-provider.d.ts +111 -0
  21. package/build/main/providers/caching/route/route-caching-provider.js +86 -0
  22. package/build/main/providers/caching-gas-provider.d.ts +23 -0
  23. package/build/main/providers/caching-gas-provider.js +41 -0
  24. package/build/main/providers/caching-subgraph-provider.d.ts +33 -0
  25. package/build/main/providers/caching-subgraph-provider.js +186 -0
  26. package/build/main/providers/caching-token-list-provider.d.ts +52 -0
  27. package/build/main/providers/caching-token-list-provider.js +147 -0
  28. package/build/main/providers/caching-token-provider.d.ts +24 -0
  29. package/build/main/providers/caching-token-provider.js +234 -0
  30. package/build/main/providers/eip-1559-gas-price-provider.d.ts +31 -0
  31. package/build/main/providers/eip-1559-gas-price-provider.js +71 -0
  32. package/build/main/providers/eth-estimate-gas-provider.d.ts +21 -0
  33. package/build/main/providers/eth-estimate-gas-provider.js +91 -0
  34. package/build/main/providers/eth-gas-station-info-gas-price-provider.d.ts +19 -0
  35. package/build/main/providers/eth-gas-station-info-gas-price-provider.js +36 -0
  36. package/build/main/providers/fewV2/ring-caching-pool-provider.d.ts +33 -0
  37. package/build/main/providers/fewV2/ring-caching-pool-provider.js +89 -0
  38. package/build/main/providers/fewV2/ring-caching-subgraph-provider.d.ts +19 -0
  39. package/build/main/providers/fewV2/ring-caching-subgraph-provider.js +24 -0
  40. package/build/main/providers/fewV2/ring-pool-provider.d.ts +63 -0
  41. package/build/main/providers/fewV2/ring-pool-provider.js +148 -0
  42. package/build/main/providers/fewV2/ring-quote-provider.d.ts +34 -0
  43. package/build/main/providers/fewV2/ring-quote-provider.js +90 -0
  44. package/build/main/providers/fewV2/ring-static-subgraph-provider.d.ts +24 -0
  45. package/build/main/providers/fewV2/ring-static-subgraph-provider.js +284 -0
  46. package/build/main/providers/fewV2/ring-subgraph-provider-with-fallback.d.ts +16 -0
  47. package/build/main/providers/fewV2/ring-subgraph-provider-with-fallback.js +23 -0
  48. package/build/main/providers/fewV2/ring-subgraph-provider.d.ts +52 -0
  49. package/build/main/providers/fewV2/ring-subgraph-provider.js +183 -0
  50. package/build/main/providers/fewV2/ring-uri-subgraph-provider.d.ts +4 -0
  51. package/build/main/providers/fewV2/ring-uri-subgraph-provider.js +8 -0
  52. package/build/main/providers/gas-price-provider.d.ts +10 -0
  53. package/build/main/providers/gas-price-provider.js +10 -0
  54. package/build/main/providers/index.d.ts +56 -0
  55. package/build/main/providers/index.js +73 -0
  56. package/build/main/providers/legacy-gas-price-provider.d.ts +7 -0
  57. package/build/main/providers/legacy-gas-price-provider.js +18 -0
  58. package/build/main/providers/multicall-provider.d.ts +83 -0
  59. package/build/main/providers/multicall-provider.js +15 -0
  60. package/build/main/providers/multicall-ringswap-provider.d.ts +35 -0
  61. package/build/main/providers/multicall-ringswap-provider.js +164 -0
  62. package/build/main/providers/multicall-uniswap-provider.d.ts +37 -0
  63. package/build/main/providers/multicall-uniswap-provider.js +164 -0
  64. package/build/main/providers/on-chain-gas-price-provider.d.ts +19 -0
  65. package/build/main/providers/on-chain-gas-price-provider.js +37 -0
  66. package/build/main/providers/on-chain-quote-provider.d.ts +260 -0
  67. package/build/main/providers/on-chain-quote-provider.js +702 -0
  68. package/build/main/providers/pool-provider.d.ts +45 -0
  69. package/build/main/providers/pool-provider.js +73 -0
  70. package/build/main/providers/portion-provider.d.ts +86 -0
  71. package/build/main/providers/portion-provider.js +118 -0
  72. package/build/main/providers/provider.d.ts +38 -0
  73. package/build/main/providers/provider.js +3 -0
  74. package/build/main/providers/simulation-provider.d.ts +46 -0
  75. package/build/main/providers/simulation-provider.js +138 -0
  76. package/build/main/providers/static-gas-price-provider.d.ts +7 -0
  77. package/build/main/providers/static-gas-price-provider.js +13 -0
  78. package/build/main/providers/subgraph-provider-with-fallback.d.ts +11 -0
  79. package/build/main/providers/subgraph-provider-with-fallback.js +25 -0
  80. package/build/main/providers/subgraph-provider.d.ts +56 -0
  81. package/build/main/providers/subgraph-provider.js +287 -0
  82. package/build/main/providers/swap-router-provider.d.ts +30 -0
  83. package/build/main/providers/swap-router-provider.js +42 -0
  84. package/build/main/providers/tenderly-simulation-provider.d.ts +63 -0
  85. package/build/main/providers/tenderly-simulation-provider.js +446 -0
  86. package/build/main/providers/token-fee-fetcher.d.ts +31 -0
  87. package/build/main/providers/token-fee-fetcher.js +114 -0
  88. package/build/main/providers/token-properties-provider.d.ts +31 -0
  89. package/build/main/providers/token-properties-provider.js +118 -0
  90. package/build/main/providers/token-provider.d.ts +167 -0
  91. package/build/main/providers/token-provider.js +414 -0
  92. package/build/main/providers/token-validator-provider.d.ts +42 -0
  93. package/build/main/providers/token-validator-provider.js +99 -0
  94. package/build/main/providers/uri-subgraph-provider.d.ts +21 -0
  95. package/build/main/providers/uri-subgraph-provider.js +65 -0
  96. package/build/main/providers/v2/caching-pool-provider.d.ts +33 -0
  97. package/build/main/providers/v2/caching-pool-provider.js +89 -0
  98. package/build/main/providers/v2/caching-subgraph-provider.d.ts +19 -0
  99. package/build/main/providers/v2/caching-subgraph-provider.js +24 -0
  100. package/build/main/providers/v2/pool-provider.d.ts +63 -0
  101. package/build/main/providers/v2/pool-provider.js +148 -0
  102. package/build/main/providers/v2/quote-provider.d.ts +34 -0
  103. package/build/main/providers/v2/quote-provider.js +90 -0
  104. package/build/main/providers/v2/static-subgraph-provider.d.ts +19 -0
  105. package/build/main/providers/v2/static-subgraph-provider.js +183 -0
  106. package/build/main/providers/v2/subgraph-provider-with-fallback.d.ts +16 -0
  107. package/build/main/providers/v2/subgraph-provider-with-fallback.js +23 -0
  108. package/build/main/providers/v2/subgraph-provider.d.ts +52 -0
  109. package/build/main/providers/v2/subgraph-provider.js +334 -0
  110. package/build/main/providers/v2/uri-subgraph-provider.d.ts +4 -0
  111. package/build/main/providers/v2/uri-subgraph-provider.js +8 -0
  112. package/build/main/providers/v3/caching-pool-provider.d.ts +32 -0
  113. package/build/main/providers/v3/caching-pool-provider.js +84 -0
  114. package/build/main/providers/v3/caching-subgraph-provider.d.ts +19 -0
  115. package/build/main/providers/v3/caching-subgraph-provider.js +24 -0
  116. package/build/main/providers/v3/gas-data-provider.d.ts +39 -0
  117. package/build/main/providers/v3/gas-data-provider.js +26 -0
  118. package/build/main/providers/v3/pool-provider.d.ts +77 -0
  119. package/build/main/providers/v3/pool-provider.js +108 -0
  120. package/build/main/providers/v3/static-subgraph-provider.d.ts +21 -0
  121. package/build/main/providers/v3/static-subgraph-provider.js +229 -0
  122. package/build/main/providers/v3/subgraph-provider-with-fallback.d.ts +12 -0
  123. package/build/main/providers/v3/subgraph-provider-with-fallback.js +19 -0
  124. package/build/main/providers/v3/subgraph-provider.d.ts +45 -0
  125. package/build/main/providers/v3/subgraph-provider.js +46 -0
  126. package/build/main/providers/v3/uri-subgraph-provider.d.ts +4 -0
  127. package/build/main/providers/v3/uri-subgraph-provider.js +8 -0
  128. package/build/main/providers/v4/caching-pool-provider.d.ts +24 -0
  129. package/build/main/providers/v4/caching-pool-provider.js +81 -0
  130. package/build/main/providers/v4/caching-subgraph-provider.d.ts +19 -0
  131. package/build/main/providers/v4/caching-subgraph-provider.js +24 -0
  132. package/build/main/providers/v4/euler-swap-hooks-subgraph-provider.d.ts +25 -0
  133. package/build/main/providers/v4/euler-swap-hooks-subgraph-provider.js +160 -0
  134. package/build/main/providers/v4/pool-provider.d.ts +58 -0
  135. package/build/main/providers/v4/pool-provider.js +115 -0
  136. package/build/main/providers/v4/static-subgraph-provider.d.ts +15 -0
  137. package/build/main/providers/v4/static-subgraph-provider.js +78 -0
  138. package/build/main/providers/v4/subgraph-provider-with-fallback.d.ts +5 -0
  139. package/build/main/providers/v4/subgraph-provider-with-fallback.js +12 -0
  140. package/build/main/providers/v4/subgraph-provider.d.ts +63 -0
  141. package/build/main/providers/v4/subgraph-provider.js +63 -0
  142. package/build/main/providers/v4/uri-subgraph-provider.d.ts +4 -0
  143. package/build/main/providers/v4/uri-subgraph-provider.js +8 -0
  144. package/build/main/routers/alpha-router/alpha-router.d.ts +483 -0
  145. package/build/main/routers/alpha-router/alpha-router.js +2267 -0
  146. package/build/main/routers/alpha-router/config.d.ts +4 -0
  147. package/build/main/routers/alpha-router/config.js +129 -0
  148. package/build/main/routers/alpha-router/entities/index.d.ts +1 -0
  149. package/build/main/routers/alpha-router/entities/index.js +18 -0
  150. package/build/main/routers/alpha-router/entities/route-with-valid-quote.d.ts +329 -0
  151. package/build/main/routers/alpha-router/entities/route-with-valid-quote.js +319 -0
  152. package/build/main/routers/alpha-router/functions/best-swap-route.d.ts +25 -0
  153. package/build/main/routers/alpha-router/functions/best-swap-route.js +597 -0
  154. package/build/main/routers/alpha-router/functions/calculate-ratio-amount-in.d.ts +3 -0
  155. package/build/main/routers/alpha-router/functions/calculate-ratio-amount-in.js +18 -0
  156. package/build/main/routers/alpha-router/functions/compute-all-routes.d.ts +16 -0
  157. package/build/main/routers/alpha-router/functions/compute-all-routes.js +158 -0
  158. package/build/main/routers/alpha-router/functions/get-candidate-pools.d.ts +192 -0
  159. package/build/main/routers/alpha-router/functions/get-candidate-pools.js +3025 -0
  160. package/build/main/routers/alpha-router/gas-models/fewV2/v2-heuristic-gas-model.d.ts +31 -0
  161. package/build/main/routers/alpha-router/gas-models/fewV2/v2-heuristic-gas-model.js +169 -0
  162. package/build/main/routers/alpha-router/gas-models/gas-costs.d.ts +12 -0
  163. package/build/main/routers/alpha-router/gas-models/gas-costs.js +200 -0
  164. package/build/main/routers/alpha-router/gas-models/gas-model.d.ts +111 -0
  165. package/build/main/routers/alpha-router/gas-models/gas-model.js +120 -0
  166. package/build/main/routers/alpha-router/gas-models/index.d.ts +5 -0
  167. package/build/main/routers/alpha-router/gas-models/index.js +22 -0
  168. package/build/main/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.d.ts +24 -0
  169. package/build/main/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.js +161 -0
  170. package/build/main/routers/alpha-router/gas-models/ring-gas-model.d.ts +111 -0
  171. package/build/main/routers/alpha-router/gas-models/ring-gas-model.js +169 -0
  172. package/build/main/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.d.ts +21 -0
  173. package/build/main/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.js +366 -0
  174. package/build/main/routers/alpha-router/gas-models/uniswapFewV3/v3-heuristic-gas-model.d.ts +26 -0
  175. package/build/main/routers/alpha-router/gas-models/uniswapFewV3/v3-heuristic-gas-model.js +41 -0
  176. package/build/main/routers/alpha-router/gas-models/uniswapFewV4/v4-heuristic-gas-model.d.ts +15 -0
  177. package/build/main/routers/alpha-router/gas-models/uniswapFewV4/v4-heuristic-gas-model.js +40 -0
  178. package/build/main/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.d.ts +31 -0
  179. package/build/main/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.js +169 -0
  180. package/build/main/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.d.ts +26 -0
  181. package/build/main/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.js +41 -0
  182. package/build/main/routers/alpha-router/gas-models/v4/v4-heuristic-gas-model.d.ts +15 -0
  183. package/build/main/routers/alpha-router/gas-models/v4/v4-heuristic-gas-model.js +40 -0
  184. package/build/main/routers/alpha-router/index.d.ts +4 -0
  185. package/build/main/routers/alpha-router/index.js +21 -0
  186. package/build/main/routers/alpha-router/quoters/base-quoter.d.ts +78 -0
  187. package/build/main/routers/alpha-router/quoters/base-quoter.js +77 -0
  188. package/build/main/routers/alpha-router/quoters/few-v2-quoter.d.ts +24 -0
  189. package/build/main/routers/alpha-router/quoters/few-v2-quoter.js +141 -0
  190. package/build/main/routers/alpha-router/quoters/index.d.ts +5 -0
  191. package/build/main/routers/alpha-router/quoters/index.js +22 -0
  192. package/build/main/routers/alpha-router/quoters/mixed-quoter.d.ts +34 -0
  193. package/build/main/routers/alpha-router/quoters/mixed-quoter.js +156 -0
  194. package/build/main/routers/alpha-router/quoters/model/index.d.ts +1 -0
  195. package/build/main/routers/alpha-router/quoters/model/index.js +18 -0
  196. package/build/main/routers/alpha-router/quoters/model/results/get-quotes-result.d.ts +6 -0
  197. package/build/main/routers/alpha-router/quoters/model/results/get-quotes-result.js +3 -0
  198. package/build/main/routers/alpha-router/quoters/model/results/get-routes-result.d.ts +6 -0
  199. package/build/main/routers/alpha-router/quoters/model/results/get-routes-result.js +3 -0
  200. package/build/main/routers/alpha-router/quoters/model/results/index.d.ts +2 -0
  201. package/build/main/routers/alpha-router/quoters/model/results/index.js +19 -0
  202. package/build/main/routers/alpha-router/quoters/uniswap-few-v3-quoter.d.ts +19 -0
  203. package/build/main/routers/alpha-router/quoters/uniswap-few-v3-quoter.js +118 -0
  204. package/build/main/routers/alpha-router/quoters/uniswap-few-v4-quoter.d.ts +18 -0
  205. package/build/main/routers/alpha-router/quoters/uniswap-few-v4-quoter.js +121 -0
  206. package/build/main/routers/alpha-router/quoters/v2-quoter.d.ts +24 -0
  207. package/build/main/routers/alpha-router/quoters/v2-quoter.js +141 -0
  208. package/build/main/routers/alpha-router/quoters/v3-quoter.d.ts +19 -0
  209. package/build/main/routers/alpha-router/quoters/v3-quoter.js +125 -0
  210. package/build/main/routers/alpha-router/quoters/v4-quoter.d.ts +18 -0
  211. package/build/main/routers/alpha-router/quoters/v4-quoter.js +121 -0
  212. package/build/main/routers/index.d.ts +4 -0
  213. package/build/main/routers/index.js +21 -0
  214. package/build/main/routers/legacy-router/bases.d.ts +225 -0
  215. package/build/main/routers/legacy-router/bases.js +132 -0
  216. package/build/main/routers/legacy-router/index.d.ts +1 -0
  217. package/build/main/routers/legacy-router/index.js +18 -0
  218. package/build/main/routers/legacy-router/legacy-router.d.ts +41 -0
  219. package/build/main/routers/legacy-router/legacy-router.js +291 -0
  220. package/build/main/routers/router.d.ts +195 -0
  221. package/build/main/routers/router.js +68 -0
  222. package/build/main/tsconfig.tsbuildinfo +1 -0
  223. package/build/main/types/other/commons.d.ts +16 -0
  224. package/build/main/types/other/commons.js +6 -0
  225. package/build/main/types/other/factories/Erc20__factory.d.ts +45 -0
  226. package/build/main/types/other/factories/Erc20__factory.js +240 -0
  227. package/build/main/types/other/factories/GasDataArbitrum__factory.d.ts +18 -0
  228. package/build/main/types/other/factories/GasDataArbitrum__factory.js +58 -0
  229. package/build/main/types/other/factories/IMixedRouteQuoterV1__factory.d.ts +41 -0
  230. package/build/main/types/other/factories/IMixedRouteQuoterV1__factory.js +156 -0
  231. package/build/main/types/other/factories/ITokenValidator__factory.d.ts +22 -0
  232. package/build/main/types/other/factories/ITokenValidator__factory.js +78 -0
  233. package/build/main/types/other/factories/MixedRouteQuoterV2__factory.d.ts +86 -0
  234. package/build/main/types/other/factories/MixedRouteQuoterV2__factory.js +477 -0
  235. package/build/main/types/other/factories/Permit2__factory.d.ts +87 -0
  236. package/build/main/types/other/factories/Permit2__factory.js +936 -0
  237. package/build/main/types/other/factories/StateView__factory.d.ts +32 -0
  238. package/build/main/types/other/factories/StateView__factory.js +383 -0
  239. package/build/main/types/other/factories/SwapRouter02__factory.d.ts +67 -0
  240. package/build/main/types/other/factories/SwapRouter02__factory.js +1098 -0
  241. package/build/main/types/other/factories/TokenFeeDetector__factory.d.ts +47 -0
  242. package/build/main/types/other/factories/TokenFeeDetector__factory.js +243 -0
  243. package/build/main/types/other/factories/V4Quoter__factory.d.ts +37 -0
  244. package/build/main/types/other/factories/V4Quoter__factory.js +312 -0
  245. package/build/main/types/v2/commons.d.ts +16 -0
  246. package/build/main/types/v2/commons.js +6 -0
  247. package/build/main/types/v2/factories/IUniswapV2Pair__factory.d.ts +35 -0
  248. package/build/main/types/v2/factories/IUniswapV2Pair__factory.js +671 -0
  249. package/build/main/types/v3/commons.d.ts +16 -0
  250. package/build/main/types/v3/commons.js +6 -0
  251. package/build/main/types/v3/factories/IERC20Metadata__factory.d.ts +35 -0
  252. package/build/main/types/v3/factories/IERC20Metadata__factory.js +242 -0
  253. package/build/main/types/v3/factories/IQuoterV2__factory.d.ts +41 -0
  254. package/build/main/types/v3/factories/IQuoterV2__factory.js +220 -0
  255. package/build/main/types/v3/factories/IUniswapV3PoolState__factory.d.ts +22 -0
  256. package/build/main/types/v3/factories/IUniswapV3PoolState__factory.js +266 -0
  257. package/build/main/types/v3/factories/UniswapInterfaceMulticall__factory.d.ts +61 -0
  258. package/build/main/types/v3/factories/UniswapInterfaceMulticall__factory.js +127 -0
  259. package/build/main/util/addresses.d.ts +34 -0
  260. package/build/main/util/addresses.js +140 -0
  261. package/build/main/util/amounts.d.ts +10 -0
  262. package/build/main/util/amounts.js +94 -0
  263. package/build/main/util/callData.d.ts +1 -0
  264. package/build/main/util/callData.js +6 -0
  265. package/build/main/util/chains.d.ts +75 -0
  266. package/build/main/util/chains.js +780 -0
  267. package/build/main/util/defaultBlocksToLive.d.ts +4 -0
  268. package/build/main/util/defaultBlocksToLive.js +57 -0
  269. package/build/main/util/fewAddress.d.ts +48 -0
  270. package/build/main/util/fewAddress.js +624 -0
  271. package/build/main/util/gas-factory-helpers.d.ts +38 -0
  272. package/build/main/util/gas-factory-helpers.js +596 -0
  273. package/build/main/util/hooksOptions.d.ts +5 -0
  274. package/build/main/util/hooksOptions.js +10 -0
  275. package/build/main/util/index.d.ts +10 -0
  276. package/build/main/util/index.js +27 -0
  277. package/build/main/util/intent.d.ts +6 -0
  278. package/build/main/util/intent.js +13 -0
  279. package/build/main/util/l2FeeChains.d.ts +2 -0
  280. package/build/main/util/l2FeeChains.js +18 -0
  281. package/build/main/util/log.d.ts +3 -0
  282. package/build/main/util/log.js +97 -0
  283. package/build/main/util/methodParameters.d.ts +5 -0
  284. package/build/main/util/methodParameters.js +176 -0
  285. package/build/main/util/metric.d.ts +48 -0
  286. package/build/main/util/metric.js +59 -0
  287. package/build/main/util/mixedRouteFilterOutV4Pools.d.ts +3 -0
  288. package/build/main/util/mixedRouteFilterOutV4Pools.js +17 -0
  289. package/build/main/util/onchainQuoteProviderConfigs.d.ts +42 -0
  290. package/build/main/util/onchainQuoteProviderConfigs.js +72 -0
  291. package/build/main/util/pool.d.ts +5 -0
  292. package/build/main/util/pool.js +46 -0
  293. package/build/main/util/protocols.d.ts +2 -0
  294. package/build/main/util/protocols.js +22 -0
  295. package/build/main/util/routes.d.ts +11 -0
  296. package/build/main/util/routes.js +159 -0
  297. package/build/main/util/serializeRouteIds.d.ts +2 -0
  298. package/build/main/util/serializeRouteIds.js +12 -0
  299. package/build/main/util/simple-perf-tracker.d.ts +27 -0
  300. package/build/main/util/simple-perf-tracker.js +171 -0
  301. package/build/main/util/tenderlySimulationErrorBreakDown.d.ts +3 -0
  302. package/build/main/util/tenderlySimulationErrorBreakDown.js +33 -0
  303. package/build/main/util/unsupported-tokens.d.ts +37 -0
  304. package/build/main/util/unsupported-tokens.js +1119 -0
  305. package/build/module/index.d.ts +3 -0
  306. package/build/module/index.js +4 -0
  307. package/build/module/providers/cache-node.d.ts +10 -0
  308. package/build/module/providers/cache-node.js +29 -0
  309. package/build/module/providers/cache.d.ts +14 -0
  310. package/build/module/providers/cache.js +2 -0
  311. package/build/module/providers/caching/route/index.d.ts +2 -0
  312. package/build/module/providers/caching/route/index.js +3 -0
  313. package/build/module/providers/caching/route/model/cache-mode.d.ts +16 -0
  314. package/build/module/providers/caching/route/model/cache-mode.js +18 -0
  315. package/build/module/providers/caching/route/model/cached-route.d.ts +29 -0
  316. package/build/module/providers/caching/route/model/cached-route.js +73 -0
  317. package/build/module/providers/caching/route/model/cached-routes.d.ts +67 -0
  318. package/build/module/providers/caching/route/model/cached-routes.js +74 -0
  319. package/build/module/providers/caching/route/model/index.d.ts +3 -0
  320. package/build/module/providers/caching/route/model/index.js +4 -0
  321. package/build/module/providers/caching/route/route-caching-provider.d.ts +111 -0
  322. package/build/module/providers/caching/route/route-caching-provider.js +82 -0
  323. package/build/module/providers/caching-gas-provider.d.ts +23 -0
  324. package/build/module/providers/caching-gas-provider.js +37 -0
  325. package/build/module/providers/caching-subgraph-provider.d.ts +33 -0
  326. package/build/module/providers/caching-subgraph-provider.js +182 -0
  327. package/build/module/providers/caching-token-list-provider.d.ts +52 -0
  328. package/build/module/providers/caching-token-list-provider.js +140 -0
  329. package/build/module/providers/caching-token-provider.d.ts +24 -0
  330. package/build/module/providers/caching-token-provider.js +227 -0
  331. package/build/module/providers/eip-1559-gas-price-provider.d.ts +31 -0
  332. package/build/module/providers/eip-1559-gas-price-provider.js +64 -0
  333. package/build/module/providers/eth-estimate-gas-provider.d.ts +21 -0
  334. package/build/module/providers/eth-estimate-gas-provider.js +99 -0
  335. package/build/module/providers/eth-gas-station-info-gas-price-provider.d.ts +19 -0
  336. package/build/module/providers/eth-gas-station-info-gas-price-provider.js +29 -0
  337. package/build/module/providers/fewV2/ring-caching-pool-provider.d.ts +33 -0
  338. package/build/module/providers/fewV2/ring-caching-pool-provider.js +85 -0
  339. package/build/module/providers/fewV2/ring-caching-subgraph-provider.d.ts +19 -0
  340. package/build/module/providers/fewV2/ring-caching-subgraph-provider.js +20 -0
  341. package/build/module/providers/fewV2/ring-pool-provider.d.ts +63 -0
  342. package/build/module/providers/fewV2/ring-pool-provider.js +141 -0
  343. package/build/module/providers/fewV2/ring-quote-provider.d.ts +34 -0
  344. package/build/module/providers/fewV2/ring-quote-provider.js +86 -0
  345. package/build/module/providers/fewV2/ring-static-subgraph-provider.d.ts +24 -0
  346. package/build/module/providers/fewV2/ring-static-subgraph-provider.js +319 -0
  347. package/build/module/providers/fewV2/ring-subgraph-provider-with-fallback.d.ts +16 -0
  348. package/build/module/providers/fewV2/ring-subgraph-provider-with-fallback.js +19 -0
  349. package/build/module/providers/fewV2/ring-subgraph-provider.d.ts +52 -0
  350. package/build/module/providers/fewV2/ring-subgraph-provider.js +176 -0
  351. package/build/module/providers/fewV2/ring-uri-subgraph-provider.d.ts +4 -0
  352. package/build/module/providers/fewV2/ring-uri-subgraph-provider.js +4 -0
  353. package/build/module/providers/gas-price-provider.d.ts +10 -0
  354. package/build/module/providers/gas-price-provider.js +6 -0
  355. package/build/module/providers/index.d.ts +56 -0
  356. package/build/module/providers/index.js +57 -0
  357. package/build/module/providers/legacy-gas-price-provider.d.ts +7 -0
  358. package/build/module/providers/legacy-gas-price-provider.js +14 -0
  359. package/build/module/providers/multicall-provider.d.ts +83 -0
  360. package/build/module/providers/multicall-provider.js +11 -0
  361. package/build/module/providers/multicall-ringswap-provider.d.ts +35 -0
  362. package/build/module/providers/multicall-ringswap-provider.js +157 -0
  363. package/build/module/providers/multicall-uniswap-provider.d.ts +37 -0
  364. package/build/module/providers/multicall-uniswap-provider.js +157 -0
  365. package/build/module/providers/on-chain-gas-price-provider.d.ts +19 -0
  366. package/build/module/providers/on-chain-gas-price-provider.js +33 -0
  367. package/build/module/providers/on-chain-quote-provider.d.ts +260 -0
  368. package/build/module/providers/on-chain-quote-provider.js +696 -0
  369. package/build/module/providers/pool-provider.d.ts +45 -0
  370. package/build/module/providers/pool-provider.js +66 -0
  371. package/build/module/providers/portion-provider.d.ts +86 -0
  372. package/build/module/providers/portion-provider.js +114 -0
  373. package/build/module/providers/provider.d.ts +38 -0
  374. package/build/module/providers/provider.js +2 -0
  375. package/build/module/providers/simulation-provider.d.ts +46 -0
  376. package/build/module/providers/simulation-provider.js +140 -0
  377. package/build/module/providers/static-gas-price-provider.d.ts +7 -0
  378. package/build/module/providers/static-gas-price-provider.js +9 -0
  379. package/build/module/providers/subgraph-provider-with-fallback.d.ts +11 -0
  380. package/build/module/providers/subgraph-provider-with-fallback.js +21 -0
  381. package/build/module/providers/subgraph-provider.d.ts +56 -0
  382. package/build/module/providers/subgraph-provider.js +284 -0
  383. package/build/module/providers/swap-router-provider.d.ts +30 -0
  384. package/build/module/providers/swap-router-provider.js +38 -0
  385. package/build/module/providers/tenderly-simulation-provider.d.ts +63 -0
  386. package/build/module/providers/tenderly-simulation-provider.js +444 -0
  387. package/build/module/providers/token-fee-fetcher.d.ts +31 -0
  388. package/build/module/providers/token-fee-fetcher.js +110 -0
  389. package/build/module/providers/token-properties-provider.d.ts +31 -0
  390. package/build/module/providers/token-properties-provider.js +114 -0
  391. package/build/module/providers/token-provider.d.ts +167 -0
  392. package/build/module/providers/token-provider.js +401 -0
  393. package/build/module/providers/token-validator-provider.d.ts +42 -0
  394. package/build/module/providers/token-validator-provider.js +92 -0
  395. package/build/module/providers/uri-subgraph-provider.d.ts +21 -0
  396. package/build/module/providers/uri-subgraph-provider.js +58 -0
  397. package/build/module/providers/v2/caching-pool-provider.d.ts +33 -0
  398. package/build/module/providers/v2/caching-pool-provider.js +85 -0
  399. package/build/module/providers/v2/caching-subgraph-provider.d.ts +19 -0
  400. package/build/module/providers/v2/caching-subgraph-provider.js +20 -0
  401. package/build/module/providers/v2/pool-provider.d.ts +63 -0
  402. package/build/module/providers/v2/pool-provider.js +141 -0
  403. package/build/module/providers/v2/quote-provider.d.ts +34 -0
  404. package/build/module/providers/v2/quote-provider.js +86 -0
  405. package/build/module/providers/v2/static-subgraph-provider.d.ts +19 -0
  406. package/build/module/providers/v2/static-subgraph-provider.js +178 -0
  407. package/build/module/providers/v2/subgraph-provider-with-fallback.d.ts +16 -0
  408. package/build/module/providers/v2/subgraph-provider-with-fallback.js +19 -0
  409. package/build/module/providers/v2/subgraph-provider.d.ts +52 -0
  410. package/build/module/providers/v2/subgraph-provider.js +331 -0
  411. package/build/module/providers/v2/uri-subgraph-provider.d.ts +4 -0
  412. package/build/module/providers/v2/uri-subgraph-provider.js +4 -0
  413. package/build/module/providers/v3/caching-pool-provider.d.ts +32 -0
  414. package/build/module/providers/v3/caching-pool-provider.js +77 -0
  415. package/build/module/providers/v3/caching-subgraph-provider.d.ts +19 -0
  416. package/build/module/providers/v3/caching-subgraph-provider.js +20 -0
  417. package/build/module/providers/v3/gas-data-provider.d.ts +39 -0
  418. package/build/module/providers/v3/gas-data-provider.js +22 -0
  419. package/build/module/providers/v3/pool-provider.d.ts +77 -0
  420. package/build/module/providers/v3/pool-provider.js +101 -0
  421. package/build/module/providers/v3/static-subgraph-provider.d.ts +21 -0
  422. package/build/module/providers/v3/static-subgraph-provider.js +224 -0
  423. package/build/module/providers/v3/subgraph-provider-with-fallback.d.ts +12 -0
  424. package/build/module/providers/v3/subgraph-provider-with-fallback.js +15 -0
  425. package/build/module/providers/v3/subgraph-provider.d.ts +45 -0
  426. package/build/module/providers/v3/subgraph-provider.js +42 -0
  427. package/build/module/providers/v3/uri-subgraph-provider.d.ts +4 -0
  428. package/build/module/providers/v3/uri-subgraph-provider.js +4 -0
  429. package/build/module/providers/v4/caching-pool-provider.d.ts +24 -0
  430. package/build/module/providers/v4/caching-pool-provider.js +74 -0
  431. package/build/module/providers/v4/caching-subgraph-provider.d.ts +19 -0
  432. package/build/module/providers/v4/caching-subgraph-provider.js +20 -0
  433. package/build/module/providers/v4/euler-swap-hooks-subgraph-provider.d.ts +25 -0
  434. package/build/module/providers/v4/euler-swap-hooks-subgraph-provider.js +153 -0
  435. package/build/module/providers/v4/pool-provider.d.ts +58 -0
  436. package/build/module/providers/v4/pool-provider.js +106 -0
  437. package/build/module/providers/v4/static-subgraph-provider.d.ts +15 -0
  438. package/build/module/providers/v4/static-subgraph-provider.js +71 -0
  439. package/build/module/providers/v4/subgraph-provider-with-fallback.d.ts +5 -0
  440. package/build/module/providers/v4/subgraph-provider-with-fallback.js +8 -0
  441. package/build/module/providers/v4/subgraph-provider.d.ts +63 -0
  442. package/build/module/providers/v4/subgraph-provider.js +59 -0
  443. package/build/module/providers/v4/uri-subgraph-provider.d.ts +4 -0
  444. package/build/module/providers/v4/uri-subgraph-provider.js +4 -0
  445. package/build/module/routers/alpha-router/alpha-router.d.ts +483 -0
  446. package/build/module/routers/alpha-router/alpha-router.js +2280 -0
  447. package/build/module/routers/alpha-router/config.d.ts +4 -0
  448. package/build/module/routers/alpha-router/config.js +125 -0
  449. package/build/module/routers/alpha-router/entities/index.d.ts +1 -0
  450. package/build/module/routers/alpha-router/entities/index.js +2 -0
  451. package/build/module/routers/alpha-router/entities/route-with-valid-quote.d.ts +329 -0
  452. package/build/module/routers/alpha-router/entities/route-with-valid-quote.js +306 -0
  453. package/build/module/routers/alpha-router/functions/best-swap-route.d.ts +25 -0
  454. package/build/module/routers/alpha-router/functions/best-swap-route.js +586 -0
  455. package/build/module/routers/alpha-router/functions/calculate-ratio-amount-in.d.ts +3 -0
  456. package/build/module/routers/alpha-router/functions/calculate-ratio-amount-in.js +14 -0
  457. package/build/module/routers/alpha-router/functions/compute-all-routes.d.ts +16 -0
  458. package/build/module/routers/alpha-router/functions/compute-all-routes.js +147 -0
  459. package/build/module/routers/alpha-router/functions/get-candidate-pools.d.ts +192 -0
  460. package/build/module/routers/alpha-router/functions/get-candidate-pools.js +3010 -0
  461. package/build/module/routers/alpha-router/gas-models/fewV2/v2-heuristic-gas-model.d.ts +31 -0
  462. package/build/module/routers/alpha-router/gas-models/fewV2/v2-heuristic-gas-model.js +162 -0
  463. package/build/module/routers/alpha-router/gas-models/gas-costs.d.ts +12 -0
  464. package/build/module/routers/alpha-router/gas-models/gas-costs.js +189 -0
  465. package/build/module/routers/alpha-router/gas-models/gas-model.d.ts +111 -0
  466. package/build/module/routers/alpha-router/gas-models/gas-model.js +114 -0
  467. package/build/module/routers/alpha-router/gas-models/index.d.ts +5 -0
  468. package/build/module/routers/alpha-router/gas-models/index.js +6 -0
  469. package/build/module/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.d.ts +24 -0
  470. package/build/module/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.js +154 -0
  471. package/build/module/routers/alpha-router/gas-models/ring-gas-model.d.ts +111 -0
  472. package/build/module/routers/alpha-router/gas-models/ring-gas-model.js +163 -0
  473. package/build/module/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.d.ts +21 -0
  474. package/build/module/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.js +362 -0
  475. package/build/module/routers/alpha-router/gas-models/uniswapFewV3/v3-heuristic-gas-model.d.ts +26 -0
  476. package/build/module/routers/alpha-router/gas-models/uniswapFewV3/v3-heuristic-gas-model.js +37 -0
  477. package/build/module/routers/alpha-router/gas-models/uniswapFewV4/v4-heuristic-gas-model.d.ts +15 -0
  478. package/build/module/routers/alpha-router/gas-models/uniswapFewV4/v4-heuristic-gas-model.js +36 -0
  479. package/build/module/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.d.ts +31 -0
  480. package/build/module/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.js +162 -0
  481. package/build/module/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.d.ts +26 -0
  482. package/build/module/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.js +37 -0
  483. package/build/module/routers/alpha-router/gas-models/v4/v4-heuristic-gas-model.d.ts +15 -0
  484. package/build/module/routers/alpha-router/gas-models/v4/v4-heuristic-gas-model.js +36 -0
  485. package/build/module/routers/alpha-router/index.d.ts +4 -0
  486. package/build/module/routers/alpha-router/index.js +5 -0
  487. package/build/module/routers/alpha-router/quoters/base-quoter.d.ts +78 -0
  488. package/build/module/routers/alpha-router/quoters/base-quoter.js +70 -0
  489. package/build/module/routers/alpha-router/quoters/few-v2-quoter.d.ts +24 -0
  490. package/build/module/routers/alpha-router/quoters/few-v2-quoter.js +138 -0
  491. package/build/module/routers/alpha-router/quoters/index.d.ts +5 -0
  492. package/build/module/routers/alpha-router/quoters/index.js +6 -0
  493. package/build/module/routers/alpha-router/quoters/mixed-quoter.d.ts +34 -0
  494. package/build/module/routers/alpha-router/quoters/mixed-quoter.js +149 -0
  495. package/build/module/routers/alpha-router/quoters/model/index.d.ts +1 -0
  496. package/build/module/routers/alpha-router/quoters/model/index.js +2 -0
  497. package/build/module/routers/alpha-router/quoters/model/results/get-quotes-result.d.ts +6 -0
  498. package/build/module/routers/alpha-router/quoters/model/results/get-quotes-result.js +2 -0
  499. package/build/module/routers/alpha-router/quoters/model/results/get-routes-result.d.ts +6 -0
  500. package/build/module/routers/alpha-router/quoters/model/results/get-routes-result.js +2 -0
  501. package/build/module/routers/alpha-router/quoters/model/results/index.d.ts +2 -0
  502. package/build/module/routers/alpha-router/quoters/model/results/index.js +3 -0
  503. package/build/module/routers/alpha-router/quoters/uniswap-few-v3-quoter.d.ts +19 -0
  504. package/build/module/routers/alpha-router/quoters/uniswap-few-v3-quoter.js +111 -0
  505. package/build/module/routers/alpha-router/quoters/uniswap-few-v4-quoter.d.ts +18 -0
  506. package/build/module/routers/alpha-router/quoters/uniswap-few-v4-quoter.js +114 -0
  507. package/build/module/routers/alpha-router/quoters/v2-quoter.d.ts +24 -0
  508. package/build/module/routers/alpha-router/quoters/v2-quoter.js +138 -0
  509. package/build/module/routers/alpha-router/quoters/v3-quoter.d.ts +19 -0
  510. package/build/module/routers/alpha-router/quoters/v3-quoter.js +118 -0
  511. package/build/module/routers/alpha-router/quoters/v4-quoter.d.ts +18 -0
  512. package/build/module/routers/alpha-router/quoters/v4-quoter.js +114 -0
  513. package/build/module/routers/index.d.ts +4 -0
  514. package/build/module/routers/index.js +5 -0
  515. package/build/module/routers/legacy-router/bases.d.ts +225 -0
  516. package/build/module/routers/legacy-router/bases.js +138 -0
  517. package/build/module/routers/legacy-router/index.d.ts +1 -0
  518. package/build/module/routers/legacy-router/index.js +2 -0
  519. package/build/module/routers/legacy-router/legacy-router.d.ts +41 -0
  520. package/build/module/routers/legacy-router/legacy-router.js +292 -0
  521. package/build/module/routers/router.d.ts +195 -0
  522. package/build/module/routers/router.js +58 -0
  523. package/build/module/tsconfig.module.tsbuildinfo +1 -0
  524. package/build/module/types/other/commons.d.ts +16 -0
  525. package/build/module/types/other/commons.js +5 -0
  526. package/build/module/types/other/factories/Erc20__factory.d.ts +45 -0
  527. package/build/module/types/other/factories/Erc20__factory.js +236 -0
  528. package/build/module/types/other/factories/GasDataArbitrum__factory.d.ts +18 -0
  529. package/build/module/types/other/factories/GasDataArbitrum__factory.js +54 -0
  530. package/build/module/types/other/factories/IMixedRouteQuoterV1__factory.d.ts +41 -0
  531. package/build/module/types/other/factories/IMixedRouteQuoterV1__factory.js +152 -0
  532. package/build/module/types/other/factories/ITokenValidator__factory.d.ts +22 -0
  533. package/build/module/types/other/factories/ITokenValidator__factory.js +74 -0
  534. package/build/module/types/other/factories/MixedRouteQuoterV2__factory.d.ts +86 -0
  535. package/build/module/types/other/factories/MixedRouteQuoterV2__factory.js +473 -0
  536. package/build/module/types/other/factories/Permit2__factory.d.ts +87 -0
  537. package/build/module/types/other/factories/Permit2__factory.js +932 -0
  538. package/build/module/types/other/factories/StateView__factory.d.ts +32 -0
  539. package/build/module/types/other/factories/StateView__factory.js +379 -0
  540. package/build/module/types/other/factories/SwapRouter02__factory.d.ts +67 -0
  541. package/build/module/types/other/factories/SwapRouter02__factory.js +1094 -0
  542. package/build/module/types/other/factories/TokenFeeDetector__factory.d.ts +47 -0
  543. package/build/module/types/other/factories/TokenFeeDetector__factory.js +239 -0
  544. package/build/module/types/other/factories/V4Quoter__factory.d.ts +37 -0
  545. package/build/module/types/other/factories/V4Quoter__factory.js +308 -0
  546. package/build/module/types/v2/commons.d.ts +16 -0
  547. package/build/module/types/v2/commons.js +5 -0
  548. package/build/module/types/v2/factories/IUniswapV2Pair__factory.d.ts +35 -0
  549. package/build/module/types/v2/factories/IUniswapV2Pair__factory.js +667 -0
  550. package/build/module/types/v3/commons.d.ts +16 -0
  551. package/build/module/types/v3/commons.js +5 -0
  552. package/build/module/types/v3/factories/IERC20Metadata__factory.d.ts +35 -0
  553. package/build/module/types/v3/factories/IERC20Metadata__factory.js +238 -0
  554. package/build/module/types/v3/factories/IQuoterV2__factory.d.ts +41 -0
  555. package/build/module/types/v3/factories/IQuoterV2__factory.js +216 -0
  556. package/build/module/types/v3/factories/IUniswapV3PoolState__factory.d.ts +22 -0
  557. package/build/module/types/v3/factories/IUniswapV3PoolState__factory.js +262 -0
  558. package/build/module/types/v3/factories/UniswapInterfaceMulticall__factory.d.ts +61 -0
  559. package/build/module/types/v3/factories/UniswapInterfaceMulticall__factory.js +123 -0
  560. package/build/module/util/addresses.d.ts +34 -0
  561. package/build/module/util/addresses.js +280 -0
  562. package/build/module/util/amounts.d.ts +10 -0
  563. package/build/module/util/amounts.js +82 -0
  564. package/build/module/util/callData.d.ts +1 -0
  565. package/build/module/util/callData.js +3 -0
  566. package/build/module/util/chains.d.ts +75 -0
  567. package/build/module/util/chains.js +772 -0
  568. package/build/module/util/defaultBlocksToLive.d.ts +4 -0
  569. package/build/module/util/defaultBlocksToLive.js +54 -0
  570. package/build/module/util/fewAddress.d.ts +48 -0
  571. package/build/module/util/fewAddress.js +627 -0
  572. package/build/module/util/gas-factory-helpers.d.ts +38 -0
  573. package/build/module/util/gas-factory-helpers.js +575 -0
  574. package/build/module/util/hooksOptions.d.ts +5 -0
  575. package/build/module/util/hooksOptions.js +7 -0
  576. package/build/module/util/index.d.ts +10 -0
  577. package/build/module/util/index.js +11 -0
  578. package/build/module/util/intent.d.ts +6 -0
  579. package/build/module/util/intent.js +10 -0
  580. package/build/module/util/l2FeeChains.d.ts +2 -0
  581. package/build/module/util/l2FeeChains.js +15 -0
  582. package/build/module/util/log.d.ts +3 -0
  583. package/build/module/util/log.js +93 -0
  584. package/build/module/util/methodParameters.d.ts +5 -0
  585. package/build/module/util/methodParameters.js +176 -0
  586. package/build/module/util/metric.d.ts +48 -0
  587. package/build/module/util/metric.js +53 -0
  588. package/build/module/util/mixedRouteFilterOutV4Pools.d.ts +3 -0
  589. package/build/module/util/mixedRouteFilterOutV4Pools.js +12 -0
  590. package/build/module/util/onchainQuoteProviderConfigs.d.ts +42 -0
  591. package/build/module/util/onchainQuoteProviderConfigs.js +74 -0
  592. package/build/module/util/pool.d.ts +5 -0
  593. package/build/module/util/pool.js +43 -0
  594. package/build/module/util/protocols.d.ts +2 -0
  595. package/build/module/util/protocols.js +18 -0
  596. package/build/module/util/routes.d.ts +11 -0
  597. package/build/module/util/routes.js +147 -0
  598. package/build/module/util/serializeRouteIds.d.ts +2 -0
  599. package/build/module/util/serializeRouteIds.js +7 -0
  600. package/build/module/util/simple-perf-tracker.d.ts +27 -0
  601. package/build/module/util/simple-perf-tracker.js +161 -0
  602. package/build/module/util/tenderlySimulationErrorBreakDown.d.ts +3 -0
  603. package/build/module/util/tenderlySimulationErrorBreakDown.js +29 -0
  604. package/build/module/util/unsupported-tokens.d.ts +37 -0
  605. package/build/module/util/unsupported-tokens.js +1116 -0
  606. package/package.json +127 -0
@@ -0,0 +1,3010 @@
1
+ import { ADDRESS_ZERO, Protocol } from '@ring-protocol/router-sdk';
2
+ import { ChainId, TradeType } from '@ring-protocol/sdk-core';
3
+ import _ from 'lodash';
4
+ import { isNativeCurrency } from '@ring-protocol/universal-router-sdk';
5
+ import { DAI_OPTIMISM_SEPOLIA, isPoolFeeDynamic, USDC_ARBITRUM_SEPOLIA, USDC_OPTIMISM_SEPOLIA, USDT_OPTIMISM_SEPOLIA, WBTC_OPTIMISM_SEPOLIA, } from '../../../providers';
6
+ import { CELO, CELO_ALFAJORES, CEUR_CELO, CEUR_CELO_ALFAJORES, CUSD_CELO, CUSD_CELO_ALFAJORES, DAI_ARBITRUM, DAI_AVAX, DAI_BNB, DAI_MAINNET, DAI_MOONBEAM, DAI_OPTIMISM, DAI_OPTIMISM_GOERLI, DAI_POLYGON_MUMBAI, DAI_SEPOLIA, DAI_UNICHAIN, FEI_MAINNET, FEW_DAI_ARB_SEPOLIA, FEW_DAI_MAINNET, FEW_DAI_SEPOLIA, FEW_RNG_MAINNET, FEW_USDB_BLAST, FEW_USDC_MAINNET, FEW_USDC_SEPOLIA, FEW_USDC_STORY_MAINNET, FEW_USDT_MAINNET, FEW_WBTC_MAINNET, USDB_BLAST, USDC_ARBITRUM, USDC_ARBITRUM_GOERLI, USDC_AVAX, USDC_BASE, USDC_BASE_SEPOLIA, USDC_BNB, USDC_ETHEREUM_GNOSIS, USDC_MAINNET, USDC_MOONBEAM, USDC_OPTIMISM, USDC_OPTIMISM_GOERLI, USDC_POLYGON, USDC_SEPOLIA, USDC_SONEIUM, USDC_UNICHAIN, USDT_ARBITRUM, USDT_BNB, USDT_MAINNET, USDT_MONAD_TESTNET, USDT_OPTIMISM, USDT_OPTIMISM_GOERLI, WBTC_ARBITRUM, WBTC_GNOSIS, WBTC_MAINNET, WBTC_MOONBEAM, WBTC_OPTIMISM, WBTC_OPTIMISM_GOERLI, WGLMR_MOONBEAM, WMATIC_POLYGON, WMATIC_POLYGON_MUMBAI, WSTETH_MAINNET, WXDAI_GNOSIS, } from '../../../providers/token-provider';
7
+ import { FEW_WRAPPED_NATIVE_CURRENCY, getAddress, getAddressLowerCase, getApplicableV3FeeAmounts, getApplicableV4FeesTickspacingsHooks, HooksOptions, nativeOnChain, unparseFeeAmount, WRAPPED_NATIVE_CURRENCY, } from '../../../util';
8
+ import { parseFeeAmount } from '../../../util/amounts';
9
+ import { log } from '../../../util/log';
10
+ import { metric, MetricLoggerUnit } from '../../../util/metric';
11
+ import { isFewToken } from '../../../util/fewAddress';
12
+ import { DYNAMIC_FEE_FLAG } from '@ring-protocol/v4-sdk';
13
+ const baseTokensByChain = {
14
+ [ChainId.MAINNET]: [
15
+ USDC_MAINNET,
16
+ USDT_MAINNET,
17
+ WBTC_MAINNET,
18
+ DAI_MAINNET,
19
+ WRAPPED_NATIVE_CURRENCY[1],
20
+ FEI_MAINNET,
21
+ WSTETH_MAINNET,
22
+ ],
23
+ [ChainId.OPTIMISM]: [
24
+ DAI_OPTIMISM,
25
+ USDC_OPTIMISM,
26
+ USDT_OPTIMISM,
27
+ WBTC_OPTIMISM,
28
+ ],
29
+ [ChainId.SEPOLIA]: [DAI_SEPOLIA, USDC_SEPOLIA],
30
+ [ChainId.OPTIMISM_GOERLI]: [
31
+ DAI_OPTIMISM_GOERLI,
32
+ USDC_OPTIMISM_GOERLI,
33
+ USDT_OPTIMISM_GOERLI,
34
+ WBTC_OPTIMISM_GOERLI,
35
+ ],
36
+ [ChainId.OPTIMISM_SEPOLIA]: [
37
+ DAI_OPTIMISM_SEPOLIA,
38
+ USDC_OPTIMISM_SEPOLIA,
39
+ USDT_OPTIMISM_SEPOLIA,
40
+ WBTC_OPTIMISM_SEPOLIA,
41
+ ],
42
+ [ChainId.ARBITRUM_ONE]: [
43
+ DAI_ARBITRUM,
44
+ USDC_ARBITRUM,
45
+ WBTC_ARBITRUM,
46
+ USDT_ARBITRUM,
47
+ ],
48
+ [ChainId.ARBITRUM_GOERLI]: [USDC_ARBITRUM_GOERLI],
49
+ [ChainId.ARBITRUM_SEPOLIA]: [USDC_ARBITRUM_SEPOLIA],
50
+ [ChainId.POLYGON]: [USDC_POLYGON, WMATIC_POLYGON],
51
+ [ChainId.POLYGON_MUMBAI]: [DAI_POLYGON_MUMBAI, WMATIC_POLYGON_MUMBAI],
52
+ [ChainId.CELO]: [CUSD_CELO, CEUR_CELO, CELO],
53
+ [ChainId.CELO_ALFAJORES]: [
54
+ CUSD_CELO_ALFAJORES,
55
+ CEUR_CELO_ALFAJORES,
56
+ CELO_ALFAJORES,
57
+ ],
58
+ [ChainId.GNOSIS]: [WBTC_GNOSIS, WXDAI_GNOSIS, USDC_ETHEREUM_GNOSIS],
59
+ [ChainId.MOONBEAM]: [
60
+ DAI_MOONBEAM,
61
+ USDC_MOONBEAM,
62
+ WBTC_MOONBEAM,
63
+ WGLMR_MOONBEAM,
64
+ ],
65
+ [ChainId.BNB]: [DAI_BNB, USDC_BNB, USDT_BNB],
66
+ [ChainId.AVALANCHE]: [DAI_AVAX, USDC_AVAX],
67
+ [ChainId.BASE]: [USDC_BASE],
68
+ [ChainId.BLAST]: [WRAPPED_NATIVE_CURRENCY[ChainId.BLAST], USDB_BLAST],
69
+ [ChainId.ZORA]: [WRAPPED_NATIVE_CURRENCY[ChainId.ZORA]],
70
+ [ChainId.ZKSYNC]: [WRAPPED_NATIVE_CURRENCY[ChainId.ZKSYNC]],
71
+ [ChainId.WORLDCHAIN]: [WRAPPED_NATIVE_CURRENCY[ChainId.WORLDCHAIN]],
72
+ [ChainId.UNICHAIN_SEPOLIA]: [
73
+ WRAPPED_NATIVE_CURRENCY[ChainId.UNICHAIN_SEPOLIA],
74
+ ],
75
+ [ChainId.MONAD_TESTNET]: [
76
+ WRAPPED_NATIVE_CURRENCY[ChainId.MONAD_TESTNET],
77
+ USDT_MONAD_TESTNET,
78
+ ],
79
+ [ChainId.BASE_SEPOLIA]: [
80
+ WRAPPED_NATIVE_CURRENCY[ChainId.BASE_SEPOLIA],
81
+ USDC_BASE_SEPOLIA,
82
+ ],
83
+ [ChainId.UNICHAIN]: [
84
+ WRAPPED_NATIVE_CURRENCY[ChainId.UNICHAIN],
85
+ DAI_UNICHAIN,
86
+ USDC_UNICHAIN,
87
+ ],
88
+ [ChainId.SONEIUM]: [USDC_SONEIUM, WRAPPED_NATIVE_CURRENCY[ChainId.SONEIUM]],
89
+ };
90
+ const fewBaseTokensByChain = {
91
+ [ChainId.MAINNET]: [
92
+ FEW_USDC_MAINNET,
93
+ FEW_USDT_MAINNET,
94
+ FEW_WBTC_MAINNET,
95
+ FEW_DAI_MAINNET,
96
+ FEW_RNG_MAINNET,
97
+ FEW_WRAPPED_NATIVE_CURRENCY[1],
98
+ ],
99
+ [ChainId.OPTIMISM]: [
100
+ DAI_OPTIMISM,
101
+ USDC_OPTIMISM,
102
+ USDT_OPTIMISM,
103
+ WBTC_OPTIMISM,
104
+ ],
105
+ [ChainId.GOERLI]: [
106
+ FEW_WRAPPED_NATIVE_CURRENCY[ChainId.GOERLI],
107
+ ],
108
+ [ChainId.BLAST]: [
109
+ FEW_WRAPPED_NATIVE_CURRENCY[ChainId.BLAST],
110
+ FEW_USDB_BLAST,
111
+ ],
112
+ [ChainId.SEPOLIA]: [FEW_WRAPPED_NATIVE_CURRENCY[ChainId.SEPOLIA], FEW_DAI_SEPOLIA, FEW_USDC_SEPOLIA],
113
+ [ChainId.UNICHAIN]: [FEW_WRAPPED_NATIVE_CURRENCY[ChainId.UNICHAIN]],
114
+ [ChainId.UNICHAIN_SEPOLIA]: [FEW_WRAPPED_NATIVE_CURRENCY[ChainId.UNICHAIN_SEPOLIA]],
115
+ [ChainId.ARBITRUM_SEPOLIA]: [FEW_WRAPPED_NATIVE_CURRENCY[ChainId.ARBITRUM_SEPOLIA], FEW_DAI_ARB_SEPOLIA],
116
+ [ChainId.OPTIMISM_GOERLI]: [
117
+ DAI_OPTIMISM_GOERLI,
118
+ USDC_OPTIMISM_GOERLI,
119
+ USDT_OPTIMISM_GOERLI,
120
+ WBTC_OPTIMISM_GOERLI,
121
+ ],
122
+ [ChainId.ARBITRUM_ONE]: [
123
+ DAI_ARBITRUM,
124
+ USDC_ARBITRUM,
125
+ WBTC_ARBITRUM,
126
+ USDT_ARBITRUM,
127
+ ],
128
+ [ChainId.ARBITRUM_GOERLI]: [USDC_ARBITRUM_GOERLI],
129
+ [ChainId.POLYGON]: [USDC_POLYGON, WMATIC_POLYGON],
130
+ [ChainId.POLYGON_MUMBAI]: [DAI_POLYGON_MUMBAI, WMATIC_POLYGON_MUMBAI],
131
+ [ChainId.CELO]: [CUSD_CELO, CEUR_CELO, CELO],
132
+ [ChainId.CELO_ALFAJORES]: [
133
+ CUSD_CELO_ALFAJORES,
134
+ CEUR_CELO_ALFAJORES,
135
+ CELO_ALFAJORES,
136
+ ],
137
+ [ChainId.GNOSIS]: [WBTC_GNOSIS, WXDAI_GNOSIS, USDC_ETHEREUM_GNOSIS],
138
+ [ChainId.MOONBEAM]: [
139
+ DAI_MOONBEAM,
140
+ USDC_MOONBEAM,
141
+ WBTC_MOONBEAM,
142
+ WGLMR_MOONBEAM,
143
+ ],
144
+ [ChainId.BNB]: [DAI_BNB, USDC_BNB, USDT_BNB],
145
+ [ChainId.AVALANCHE]: [DAI_AVAX, USDC_AVAX],
146
+ [ChainId.BASE]: [USDC_BASE],
147
+ [ChainId.STORY_MAINNET]: [FEW_USDC_STORY_MAINNET],
148
+ };
149
+ class SubcategorySelectionPools {
150
+ constructor(pools, poolsNeeded) {
151
+ this.pools = pools;
152
+ this.poolsNeeded = poolsNeeded;
153
+ }
154
+ hasEnoughPools() {
155
+ return this.pools.length >= this.poolsNeeded;
156
+ }
157
+ }
158
+ /**
159
+ * Function that finds any missing pools that were not selected by the heuristic but that would
160
+ * create a route with the topPool by TVL with either tokenIn or tokenOut across protocols.
161
+ *
162
+ * e.g. In V2CandidatePools we found that wstETH/DOG is the most liquid pool,
163
+ * then in V3CandidatePools ETH/wstETH is *not* the most liquid pool, so it is not selected
164
+ * This process will look for that pool in order to complete the route.
165
+ *
166
+ */
167
+ export async function getMixedCrossLiquidityCandidatePools({ tokenIn, tokenOut, blockNumber, v2SubgraphProvider, v3SubgraphProvider, v2Candidates, v3Candidates, }) {
168
+ const v2Pools = (await v2SubgraphProvider.getPools(tokenIn, tokenOut, {
169
+ blockNumber,
170
+ })).sort((a, b) => b.reserve - a.reserve);
171
+ const v3Pools = (await v3SubgraphProvider.getPools(tokenIn, tokenOut, {
172
+ blockNumber,
173
+ })).sort((a, b) => b.tvlUSD - a.tvlUSD);
174
+ const tokenInAddress = tokenIn.address.toLowerCase();
175
+ const tokenOutAddress = tokenOut.address.toLowerCase();
176
+ const v2SelectedPools = findCrossProtocolMissingPools(tokenInAddress, tokenOutAddress, v2Pools, v2Candidates, v3Candidates);
177
+ const v3SelectedPools = findCrossProtocolMissingPools(tokenInAddress, tokenOutAddress, v3Pools, v3Candidates, v2Candidates);
178
+ const selectedV2Pools = [
179
+ v2SelectedPools.forTokenIn,
180
+ v2SelectedPools.forTokenOut,
181
+ ].filter((pool) => pool !== undefined);
182
+ const selectedV3Pools = [
183
+ v3SelectedPools.forTokenIn,
184
+ v3SelectedPools.forTokenOut,
185
+ ].filter((pool) => pool !== undefined);
186
+ return {
187
+ v2Pools: selectedV2Pools,
188
+ v3Pools: selectedV3Pools,
189
+ };
190
+ }
191
+ function findCrossProtocolMissingPools(tokenInAddress, tokenOutAddress, pools, candidatesInProtocolToSearch, candidatesInContextProtocol) {
192
+ var _a;
193
+ const selectedPools = {};
194
+ const previouslySelectedPools = new Set((_a = candidatesInProtocolToSearch === null || candidatesInProtocolToSearch === void 0 ? void 0 : candidatesInProtocolToSearch.subgraphPools.map((pool) => pool.id)) !== null && _a !== void 0 ? _a : []);
195
+ const topPoolByTvlWithTokenOut = candidatesInContextProtocol === null || candidatesInContextProtocol === void 0 ? void 0 : candidatesInContextProtocol.candidatePools.selections.topByTVLUsingTokenOut[0];
196
+ const crossTokenAgainstTokenOut = (topPoolByTvlWithTokenOut === null || topPoolByTvlWithTokenOut === void 0 ? void 0 : topPoolByTvlWithTokenOut.token0.id.toLowerCase()) === tokenOutAddress
197
+ ? topPoolByTvlWithTokenOut === null || topPoolByTvlWithTokenOut === void 0 ? void 0 : topPoolByTvlWithTokenOut.token1.id.toLowerCase()
198
+ : topPoolByTvlWithTokenOut === null || topPoolByTvlWithTokenOut === void 0 ? void 0 : topPoolByTvlWithTokenOut.token0.id.toLowerCase();
199
+ const topPoolByTvlWithTokenIn = candidatesInContextProtocol === null || candidatesInContextProtocol === void 0 ? void 0 : candidatesInContextProtocol.candidatePools.selections.topByTVLUsingTokenIn[0];
200
+ const crossTokenAgainstTokenIn = (topPoolByTvlWithTokenIn === null || topPoolByTvlWithTokenIn === void 0 ? void 0 : topPoolByTvlWithTokenIn.token0.id.toLowerCase()) === tokenInAddress
201
+ ? topPoolByTvlWithTokenIn === null || topPoolByTvlWithTokenIn === void 0 ? void 0 : topPoolByTvlWithTokenIn.token1.id.toLowerCase()
202
+ : topPoolByTvlWithTokenIn === null || topPoolByTvlWithTokenIn === void 0 ? void 0 : topPoolByTvlWithTokenIn.token0.id.toLowerCase();
203
+ for (const pool of pools) {
204
+ // If we already found both pools for tokenIn and tokenOut. break out of this for loop.
205
+ if (selectedPools.forTokenIn !== undefined &&
206
+ selectedPools.forTokenOut !== undefined) {
207
+ break;
208
+ }
209
+ // If the pool has already been selected. continue to the next pool.
210
+ if (previouslySelectedPools.has(pool.id.toLowerCase())) {
211
+ continue;
212
+ }
213
+ const poolToken0Address = pool.token0.id.toLowerCase();
214
+ const poolToken1Address = pool.token1.id.toLowerCase();
215
+ // If we haven't selected the pool for tokenIn, and we found a pool matching the tokenOut, and the intermediateToken, select this pool
216
+ if (selectedPools.forTokenIn === undefined &&
217
+ ((poolToken0Address === tokenOutAddress &&
218
+ poolToken1Address === crossTokenAgainstTokenIn) ||
219
+ (poolToken1Address === tokenOutAddress &&
220
+ poolToken0Address === crossTokenAgainstTokenIn))) {
221
+ selectedPools.forTokenIn = pool;
222
+ }
223
+ // If we haven't selected the pool for tokenOut, and we found a pool matching the tokenIn, and the intermediateToken, select this pool
224
+ if (selectedPools.forTokenOut === undefined &&
225
+ ((poolToken0Address === tokenInAddress &&
226
+ poolToken1Address === crossTokenAgainstTokenOut) ||
227
+ (poolToken1Address === tokenInAddress &&
228
+ poolToken0Address === crossTokenAgainstTokenOut))) {
229
+ selectedPools.forTokenOut = pool;
230
+ }
231
+ }
232
+ return selectedPools;
233
+ }
234
+ // TODO: ROUTE-241 - refactor getV3CandidatePools against getV4CandidatePools
235
+ export async function getV4CandidatePools({ currencyIn, currencyOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, v4PoolParams = getApplicableV4FeesTickspacingsHooks(chainId), }) {
236
+ var _a, _b, _c, _d, _e;
237
+ const { blockNumber, v4PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, topNSecondHopForTokenAddress, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
238
+ const tokenInAddress = getAddressLowerCase(currencyIn);
239
+ const tokenOutAddress = getAddressLowerCase(currencyOut);
240
+ const beforeSubgraphPools = Date.now();
241
+ const allPools = await subgraphProvider.getPools(currencyIn, currencyOut, {
242
+ blockNumber,
243
+ });
244
+ log.info({ samplePools: allPools.slice(0, 3) }, 'Got all pools from V4 subgraph provider');
245
+ // Although this is less of an optimization than the V2 equivalent,
246
+ // save some time copying objects by mutating the underlying pool directly.
247
+ for (const pool of allPools) {
248
+ pool.token0.id = pool.token0.id.toLowerCase();
249
+ pool.token1.id = pool.token1.id.toLowerCase();
250
+ }
251
+ metric.putMetric('V4SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
252
+ const beforePoolsFiltered = Date.now();
253
+ // Only consider pools where neither tokens are in the blocked token list.
254
+ let filteredPools = allPools;
255
+ if (blockedTokenListProvider) {
256
+ filteredPools = [];
257
+ for (const pool of allPools) {
258
+ const token0InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token0.id);
259
+ const token1InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token1.id);
260
+ if (token0InBlocklist || token1InBlocklist) {
261
+ continue;
262
+ }
263
+ filteredPools.push(pool);
264
+ }
265
+ }
266
+ // Sort by tvlUSD in descending order
267
+ const subgraphPoolsSorted = filteredPools.sort((a, b) => b.tvlUSD - a.tvlUSD);
268
+ log.info(`V4 After filtering blocked tokens went from ${allPools.length} to ${subgraphPoolsSorted.length}.`);
269
+ const poolAddressesSoFar = new Set();
270
+ const addToAddressSet = (pools) => {
271
+ _(pools)
272
+ .map((pool) => pool.id)
273
+ .forEach((poolAddress) => poolAddressesSoFar.add(poolAddress));
274
+ };
275
+ const baseTokens = (_a = baseTokensByChain[chainId]) !== null && _a !== void 0 ? _a : [];
276
+ const topByBaseWithTokenIn = _(baseTokens)
277
+ .flatMap((token) => {
278
+ return _(subgraphPoolsSorted)
279
+ .filter((subgraphPool) => {
280
+ const tokenAddress = token.address.toLowerCase();
281
+ return ((subgraphPool.token0.id == tokenAddress &&
282
+ subgraphPool.token1.id == tokenInAddress) ||
283
+ (subgraphPool.token1.id == tokenAddress &&
284
+ subgraphPool.token0.id == tokenInAddress));
285
+ })
286
+ .filter((subgraphPool) => {
287
+ // in case of hooks only, it means we want to filter out hookless pools
288
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
289
+ return subgraphPool.hooks !== ADDRESS_ZERO;
290
+ }
291
+ // in case of no hooks, it means we want to filter out hook pools
292
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
293
+ return subgraphPool.hooks === ADDRESS_ZERO;
294
+ }
295
+ // otherwise it's the default case, so we just return true
296
+ return true;
297
+ })
298
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
299
+ .slice(0, topNWithEachBaseToken)
300
+ .value();
301
+ })
302
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
303
+ .slice(0, topNWithBaseToken)
304
+ .value();
305
+ const topByBaseWithTokenOut = _(baseTokens)
306
+ .flatMap((token) => {
307
+ return _(subgraphPoolsSorted)
308
+ .filter((subgraphPool) => {
309
+ const tokenAddress = token.address.toLowerCase();
310
+ return ((subgraphPool.token0.id == tokenAddress &&
311
+ subgraphPool.token1.id == tokenOutAddress) ||
312
+ (subgraphPool.token1.id == tokenAddress &&
313
+ subgraphPool.token0.id == tokenOutAddress));
314
+ })
315
+ .filter((subgraphPool) => {
316
+ // in case of hooks only, it means we want to filter out hookless pools
317
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
318
+ return subgraphPool.hooks !== ADDRESS_ZERO;
319
+ }
320
+ // in case of no hooks, it means we want to filter out hook pools
321
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
322
+ return subgraphPool.hooks === ADDRESS_ZERO;
323
+ }
324
+ // otherwise it's the default case, so we just return true
325
+ return true;
326
+ })
327
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
328
+ .slice(0, topNWithEachBaseToken)
329
+ .value();
330
+ })
331
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
332
+ .slice(0, topNWithBaseToken)
333
+ .value();
334
+ let top2DirectSwapPool = _(subgraphPoolsSorted)
335
+ .filter((subgraphPool) => {
336
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
337
+ ((subgraphPool.token0.id == tokenInAddress &&
338
+ subgraphPool.token1.id == tokenOutAddress) ||
339
+ (subgraphPool.token1.id == tokenInAddress &&
340
+ subgraphPool.token0.id == tokenOutAddress)));
341
+ })
342
+ .filter((subgraphPool) => {
343
+ // in case of hooks only, it means we want to filter out hookless pools
344
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
345
+ return subgraphPool.hooks !== ADDRESS_ZERO;
346
+ }
347
+ // in case of no hooks, it means we want to filter out hook pools
348
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
349
+ return subgraphPool.hooks === ADDRESS_ZERO;
350
+ }
351
+ // otherwise it's the default case, so we just return true
352
+ return true;
353
+ })
354
+ .slice(0, topNDirectSwaps)
355
+ .value();
356
+ if (top2DirectSwapPool.length == 0 &&
357
+ topNDirectSwaps > 0 &&
358
+ routingConfig.hooksOptions !== HooksOptions.HOOKS_ONLY) {
359
+ // If we requested direct swap pools but did not find any in the subgraph query.
360
+ // Optimistically add them into the query regardless. Invalid pools ones will be dropped anyway
361
+ // when we query the pool on-chain. Ensures that new pools for new pairs can be swapped on immediately.
362
+ // Also we need to avoid adding hookless pools into the query, when upstream requested hooksOnly
363
+ top2DirectSwapPool = _.map(v4PoolParams, (poolParams) => {
364
+ const [fee, tickSpacing, hooks] = poolParams;
365
+ const { currency0, currency1, poolId } = poolProvider.getPoolId(currencyIn, currencyOut, fee, tickSpacing, hooks);
366
+ return {
367
+ id: poolId,
368
+ feeTier: fee.toString(),
369
+ tickSpacing: tickSpacing.toString(),
370
+ hooks: hooks,
371
+ liquidity: '10000',
372
+ token0: {
373
+ symbol: currency0.symbol,
374
+ id: getAddress(currency0),
375
+ name: currency0.name,
376
+ decimals: currency0.decimals.toString(),
377
+ },
378
+ token1: {
379
+ symbol: currency1.symbol,
380
+ id: getAddress(currency1),
381
+ name: currency1.name,
382
+ decimals: currency1.decimals.toString(),
383
+ },
384
+ tvlETH: 10000,
385
+ tvlUSD: 10000,
386
+ };
387
+ });
388
+ }
389
+ addToAddressSet(top2DirectSwapPool);
390
+ const wrappedNativeAddress = (_b = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _b === void 0 ? void 0 : _b.address.toLowerCase();
391
+ // Main reason we need this is for gas estimates, only needed if token out is not native.
392
+ // We don't check the seen address set because if we've already added pools for getting native quotes
393
+ // theres no need to add more.
394
+ let top2EthQuoteTokenPool = [];
395
+ if ((((_c = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _c === void 0 ? void 0 : _c.symbol) ==
396
+ ((_d = WRAPPED_NATIVE_CURRENCY[ChainId.MAINNET]) === null || _d === void 0 ? void 0 : _d.symbol) &&
397
+ currencyOut.symbol != 'WETH' &&
398
+ currencyOut.symbol != 'WETH9' &&
399
+ currencyOut.symbol != 'ETH') ||
400
+ (((_e = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _e === void 0 ? void 0 : _e.symbol) == WMATIC_POLYGON.symbol &&
401
+ currencyOut.symbol != 'MATIC' &&
402
+ currencyOut.symbol != 'WMATIC')) {
403
+ top2EthQuoteTokenPool = _(subgraphPoolsSorted)
404
+ .filter((subgraphPool) => {
405
+ if (routeType == TradeType.EXACT_INPUT) {
406
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
407
+ subgraphPool.token1.id == tokenOutAddress) ||
408
+ (subgraphPool.token1.id == wrappedNativeAddress &&
409
+ subgraphPool.token0.id == tokenOutAddress));
410
+ }
411
+ else {
412
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
413
+ subgraphPool.token1.id == tokenInAddress) ||
414
+ (subgraphPool.token1.id == wrappedNativeAddress &&
415
+ subgraphPool.token0.id == tokenInAddress));
416
+ }
417
+ })
418
+ .slice(0, 1)
419
+ .value();
420
+ }
421
+ addToAddressSet(top2EthQuoteTokenPool);
422
+ const topByTVL = _(subgraphPoolsSorted)
423
+ .filter((subgraphPool) => {
424
+ return !poolAddressesSoFar.has(subgraphPool.id);
425
+ })
426
+ .slice(0, topN)
427
+ .value();
428
+ addToAddressSet(topByTVL);
429
+ const topByTVLUsingTokenIn = _(subgraphPoolsSorted)
430
+ .filter((subgraphPool) => {
431
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
432
+ (subgraphPool.token0.id == tokenInAddress ||
433
+ subgraphPool.token1.id == tokenInAddress));
434
+ })
435
+ .filter((subgraphPool) => {
436
+ // in case of hooks only, it means we want to filter out hookless pools
437
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
438
+ return subgraphPool.hooks !== ADDRESS_ZERO;
439
+ }
440
+ // in case of no hooks, it means we want to filter out hook pools
441
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
442
+ return subgraphPool.hooks === ADDRESS_ZERO;
443
+ }
444
+ // otherwise it's the default case, so we just return true
445
+ return true;
446
+ })
447
+ .slice(0, topNTokenInOut)
448
+ .value();
449
+ addToAddressSet(topByTVLUsingTokenIn);
450
+ const topByTVLUsingTokenOut = _(subgraphPoolsSorted)
451
+ .filter((subgraphPool) => {
452
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
453
+ (subgraphPool.token0.id == tokenOutAddress ||
454
+ subgraphPool.token1.id == tokenOutAddress));
455
+ })
456
+ .filter((subgraphPool) => {
457
+ // in case of hooks only, it means we want to filter out hookless pools
458
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
459
+ return subgraphPool.hooks !== ADDRESS_ZERO;
460
+ }
461
+ // in case of no hooks, it means we want to filter out hook pools
462
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
463
+ return subgraphPool.hooks === ADDRESS_ZERO;
464
+ }
465
+ // otherwise it's the default case, so we just return true
466
+ return true;
467
+ })
468
+ .slice(0, topNTokenInOut)
469
+ .value();
470
+ addToAddressSet(topByTVLUsingTokenOut);
471
+ const topByTVLUsingTokenInSecondHops = _(topByTVLUsingTokenIn)
472
+ .map((subgraphPool) => {
473
+ return tokenInAddress == subgraphPool.token0.id
474
+ ? subgraphPool.token1.id
475
+ : subgraphPool.token0.id;
476
+ })
477
+ .flatMap((secondHopId) => {
478
+ var _a;
479
+ return _(subgraphPoolsSorted)
480
+ .filter((subgraphPool) => {
481
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
482
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
483
+ (subgraphPool.token0.id == secondHopId ||
484
+ subgraphPool.token1.id == secondHopId));
485
+ })
486
+ .filter((subgraphPool) => {
487
+ // in case of hooks only, it means we want to filter out hookless pools
488
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
489
+ return subgraphPool.hooks !== ADDRESS_ZERO;
490
+ }
491
+ // in case of no hooks, it means we want to filter out hook pools
492
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
493
+ return subgraphPool.hooks === ADDRESS_ZERO;
494
+ }
495
+ // otherwise it's the default case, so we just return true
496
+ return true;
497
+ })
498
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
499
+ .value();
500
+ })
501
+ .uniqBy((pool) => pool.id)
502
+ .value();
503
+ addToAddressSet(topByTVLUsingTokenInSecondHops);
504
+ const topByTVLUsingTokenOutSecondHops = _(topByTVLUsingTokenOut)
505
+ .map((subgraphPool) => {
506
+ return tokenOutAddress == subgraphPool.token0.id
507
+ ? subgraphPool.token1.id
508
+ : subgraphPool.token0.id;
509
+ })
510
+ .flatMap((secondHopId) => {
511
+ var _a;
512
+ return _(subgraphPoolsSorted)
513
+ .filter((subgraphPool) => {
514
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
515
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
516
+ (subgraphPool.token0.id == secondHopId ||
517
+ subgraphPool.token1.id == secondHopId));
518
+ })
519
+ .filter((subgraphPool) => {
520
+ // in case of hooks only, it means we want to filter out hookless pools
521
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
522
+ return subgraphPool.hooks !== ADDRESS_ZERO;
523
+ }
524
+ // in case of no hooks, it means we want to filter out hook pools
525
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
526
+ return subgraphPool.hooks === ADDRESS_ZERO;
527
+ }
528
+ // otherwise it's the default case, so we just return true
529
+ return true;
530
+ })
531
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
532
+ .value();
533
+ })
534
+ .uniqBy((pool) => pool.id)
535
+ .value();
536
+ addToAddressSet(topByTVLUsingTokenOutSecondHops);
537
+ const subgraphPools = _([
538
+ ...topByBaseWithTokenIn,
539
+ ...topByBaseWithTokenOut,
540
+ ...top2DirectSwapPool,
541
+ ...top2EthQuoteTokenPool,
542
+ ...topByTVL,
543
+ ...topByTVLUsingTokenIn,
544
+ ...topByTVLUsingTokenOut,
545
+ ...topByTVLUsingTokenInSecondHops,
546
+ ...topByTVLUsingTokenOutSecondHops,
547
+ ])
548
+ .compact()
549
+ .uniqBy((pool) => pool.id)
550
+ .value();
551
+ const tokenAddresses = _(subgraphPools)
552
+ .flatMap((subgraphPool) => [subgraphPool.token0.id, subgraphPool.token1.id])
553
+ .compact()
554
+ .uniq()
555
+ .value();
556
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V4 pools we are considering`);
557
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
558
+ blockNumber,
559
+ });
560
+ const printV4SubgraphPool = (s) => {
561
+ var _a, _b, _c, _d;
562
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}/${s.feeTier}/${s.tickSpacing}/${s.hooks}`;
563
+ };
564
+ log.info({
565
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV4SubgraphPool),
566
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV4SubgraphPool),
567
+ topByTVL: topByTVL.map(printV4SubgraphPool),
568
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV4SubgraphPool),
569
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV4SubgraphPool),
570
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV4SubgraphPool),
571
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV4SubgraphPool),
572
+ top2DirectSwap: top2DirectSwapPool.map(printV4SubgraphPool),
573
+ top2EthQuotePool: top2EthQuoteTokenPool.map(printV4SubgraphPool),
574
+ }, `V4 Candidate Pools`);
575
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
576
+ // native currency is not erc20 token, therefore there's no way to retrieve native currency metadata as the erc20 token.
577
+ const tokenA = isNativeCurrency(subgraphPool.token0.id)
578
+ ? nativeOnChain(chainId)
579
+ : tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
580
+ const tokenB = isNativeCurrency(subgraphPool.token1.id)
581
+ ? nativeOnChain(chainId)
582
+ : tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
583
+ let fee;
584
+ try {
585
+ fee = Number(subgraphPool.feeTier);
586
+ fee = isPoolFeeDynamic(tokenA, tokenB, Number(subgraphPool.tickSpacing), subgraphPool.hooks, subgraphPool.id)
587
+ ? DYNAMIC_FEE_FLAG
588
+ : fee;
589
+ }
590
+ catch (err) {
591
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier} because fee tier not supported`);
592
+ return undefined;
593
+ }
594
+ if (!tokenA || !tokenB) {
595
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
596
+ return undefined;
597
+ }
598
+ return [
599
+ tokenA,
600
+ tokenB,
601
+ fee,
602
+ Number(subgraphPool.tickSpacing),
603
+ subgraphPool.hooks,
604
+ ];
605
+ });
606
+ const tokenPairs = _.compact(tokenPairsRaw);
607
+ metric.putMetric('V4PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
608
+ const beforePoolsLoad = Date.now();
609
+ const poolAccessor = await poolProvider.getPools(tokenPairs, {
610
+ blockNumber,
611
+ });
612
+ metric.putMetric('V4PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
613
+ const poolsBySelection = {
614
+ protocol: Protocol.V4,
615
+ selections: {
616
+ topByBaseWithTokenIn,
617
+ topByBaseWithTokenOut,
618
+ topByDirectSwapPool: top2DirectSwapPool,
619
+ topByEthQuoteTokenPool: top2EthQuoteTokenPool,
620
+ topByTVL,
621
+ topByTVLUsingTokenIn,
622
+ topByTVLUsingTokenOut,
623
+ topByTVLUsingTokenInSecondHops,
624
+ topByTVLUsingTokenOutSecondHops,
625
+ },
626
+ };
627
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
628
+ }
629
+ export async function getUniswapV4FewTokenCandidatePools({ currencyIn, currencyOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, v4PoolParams = getApplicableV4FeesTickspacingsHooks(chainId), }) {
630
+ var _a, _b, _c, _d, _e;
631
+ const { blockNumber, v4PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, topNSecondHopForTokenAddress, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
632
+ const tokenInAddress = getAddressLowerCase(currencyIn);
633
+ const tokenOutAddress = getAddressLowerCase(currencyOut);
634
+ const beforeSubgraphPools = Date.now();
635
+ const allPools = await subgraphProvider.getPools(currencyIn, currencyOut, {
636
+ blockNumber,
637
+ });
638
+ log.info({ samplePools: allPools.slice(0, 3) }, 'Got all pools from V4 subgraph provider');
639
+ // Although this is less of an optimization than the V2 equivalent,
640
+ // save some time copying objects by mutating the underlying pool directly.
641
+ for (const pool of allPools) {
642
+ pool.token0.id = pool.token0.id.toLowerCase();
643
+ pool.token1.id = pool.token1.id.toLowerCase();
644
+ }
645
+ metric.putMetric('V4SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
646
+ const beforePoolsFiltered = Date.now();
647
+ // Only consider pools where neither tokens are in the blocked token list.
648
+ let filteredPools = allPools;
649
+ if (blockedTokenListProvider) {
650
+ filteredPools = [];
651
+ for (const pool of allPools) {
652
+ const token0InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token0.id);
653
+ const token1InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token1.id);
654
+ if (token0InBlocklist || token1InBlocklist) {
655
+ continue;
656
+ }
657
+ filteredPools.push(pool);
658
+ }
659
+ }
660
+ // Sort by tvlUSD in descending order
661
+ const subgraphPoolsSorted = filteredPools.sort((a, b) => b.tvlUSD - a.tvlUSD);
662
+ log.info(`Uniswap Few V4 after filtering blocked tokens went from ${allPools.length} to ${subgraphPoolsSorted.length}.`);
663
+ const poolAddressesSoFar = new Set();
664
+ const addToAddressSet = (pools) => {
665
+ _(pools)
666
+ .map((pool) => pool.id)
667
+ .forEach((poolAddress) => poolAddressesSoFar.add(poolAddress));
668
+ };
669
+ const baseTokens = (_a = fewBaseTokensByChain[chainId]) !== null && _a !== void 0 ? _a : [];
670
+ const topByBaseWithTokenIn = _(baseTokens)
671
+ .flatMap((token) => {
672
+ return _(subgraphPoolsSorted)
673
+ .filter((subgraphPool) => {
674
+ const tokenAddress = token.address.toLowerCase();
675
+ return ((subgraphPool.token0.id == tokenAddress &&
676
+ subgraphPool.token1.id == tokenInAddress) ||
677
+ (subgraphPool.token1.id == tokenAddress &&
678
+ subgraphPool.token0.id == tokenInAddress));
679
+ })
680
+ .filter((subgraphPool) => {
681
+ // in case of hooks only, it means we want to filter out hookless pools
682
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
683
+ return subgraphPool.hooks !== ADDRESS_ZERO;
684
+ }
685
+ // in case of no hooks, it means we want to filter out hook pools
686
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
687
+ return subgraphPool.hooks === ADDRESS_ZERO;
688
+ }
689
+ // otherwise it's the default case, so we just return true
690
+ return true;
691
+ })
692
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
693
+ .slice(0, topNWithEachBaseToken)
694
+ .value();
695
+ })
696
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
697
+ .slice(0, topNWithBaseToken)
698
+ .value();
699
+ const topByBaseWithTokenOut = _(baseTokens)
700
+ .flatMap((token) => {
701
+ return _(subgraphPoolsSorted)
702
+ .filter((subgraphPool) => {
703
+ const tokenAddress = token.address.toLowerCase();
704
+ return ((subgraphPool.token0.id == tokenAddress &&
705
+ subgraphPool.token1.id == tokenOutAddress) ||
706
+ (subgraphPool.token1.id == tokenAddress &&
707
+ subgraphPool.token0.id == tokenOutAddress));
708
+ })
709
+ .filter((subgraphPool) => {
710
+ // in case of hooks only, it means we want to filter out hookless pools
711
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
712
+ return subgraphPool.hooks !== ADDRESS_ZERO;
713
+ }
714
+ // in case of no hooks, it means we want to filter out hook pools
715
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
716
+ return subgraphPool.hooks === ADDRESS_ZERO;
717
+ }
718
+ // otherwise it's the default case, so we just return true
719
+ return true;
720
+ })
721
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
722
+ .slice(0, topNWithEachBaseToken)
723
+ .value();
724
+ })
725
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
726
+ .slice(0, topNWithBaseToken)
727
+ .value();
728
+ let top2DirectSwapPool = _(subgraphPoolsSorted)
729
+ .filter((subgraphPool) => {
730
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
731
+ ((subgraphPool.token0.id == tokenInAddress &&
732
+ subgraphPool.token1.id == tokenOutAddress) ||
733
+ (subgraphPool.token1.id == tokenInAddress &&
734
+ subgraphPool.token0.id == tokenOutAddress)));
735
+ })
736
+ .filter((subgraphPool) => {
737
+ // in case of hooks only, it means we want to filter out hookless pools
738
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
739
+ return subgraphPool.hooks !== ADDRESS_ZERO;
740
+ }
741
+ // in case of no hooks, it means we want to filter out hook pools
742
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
743
+ return subgraphPool.hooks === ADDRESS_ZERO;
744
+ }
745
+ // otherwise it's the default case, so we just return true
746
+ return true;
747
+ })
748
+ .slice(0, topNDirectSwaps)
749
+ .value();
750
+ if (top2DirectSwapPool.length == 0 &&
751
+ topNDirectSwaps > 0 &&
752
+ routingConfig.hooksOptions !== HooksOptions.HOOKS_ONLY) {
753
+ // If we requested direct swap pools but did not find any in the subgraph query.
754
+ // Optimistically add them into the query regardless. Invalid pools ones will be dropped anyway
755
+ // when we query the pool on-chain. Ensures that new pools for new pairs can be swapped on immediately.
756
+ // Also we need to avoid adding hookless pools into the query, when upstream requested hooksOnly
757
+ top2DirectSwapPool = _.map(v4PoolParams, (poolParams) => {
758
+ const [fee, tickSpacing, hooks] = poolParams;
759
+ const { currency0, currency1, poolId } = poolProvider.getPoolId(currencyIn, currencyOut, fee, tickSpacing, hooks);
760
+ return {
761
+ id: poolId,
762
+ feeTier: fee.toString(),
763
+ tickSpacing: tickSpacing.toString(),
764
+ hooks: hooks,
765
+ liquidity: '10000',
766
+ token0: {
767
+ symbol: currency0.symbol,
768
+ id: getAddress(currency0),
769
+ name: currency0.name,
770
+ decimals: currency0.decimals.toString(),
771
+ },
772
+ token1: {
773
+ symbol: currency1.symbol,
774
+ id: getAddress(currency1),
775
+ name: currency1.name,
776
+ decimals: currency1.decimals.toString(),
777
+ },
778
+ tvlETH: 10000,
779
+ tvlUSD: 10000,
780
+ };
781
+ });
782
+ }
783
+ addToAddressSet(top2DirectSwapPool);
784
+ const wrappedNativeAddress = (_b = FEW_WRAPPED_NATIVE_CURRENCY[chainId]) === null || _b === void 0 ? void 0 : _b.address.toLowerCase();
785
+ // Main reason we need this is for gas estimates, only needed if token out is not native.
786
+ // We don't check the seen address set because if we've already added pools for getting native quotes
787
+ // theres no need to add more.
788
+ let top2EthQuoteTokenPool = [];
789
+ if ((((_c = FEW_WRAPPED_NATIVE_CURRENCY[chainId]) === null || _c === void 0 ? void 0 : _c.symbol) ==
790
+ ((_d = FEW_WRAPPED_NATIVE_CURRENCY[ChainId.MAINNET]) === null || _d === void 0 ? void 0 : _d.symbol) &&
791
+ currencyOut.symbol != 'WETH' &&
792
+ currencyOut.symbol != 'WETH9' &&
793
+ currencyOut.symbol != 'ETH') ||
794
+ (((_e = FEW_WRAPPED_NATIVE_CURRENCY[chainId]) === null || _e === void 0 ? void 0 : _e.symbol) == WMATIC_POLYGON.symbol &&
795
+ currencyOut.symbol != 'MATIC' &&
796
+ currencyOut.symbol != 'WMATIC')) {
797
+ top2EthQuoteTokenPool = _(subgraphPoolsSorted)
798
+ .filter((subgraphPool) => {
799
+ if (routeType == TradeType.EXACT_INPUT) {
800
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
801
+ subgraphPool.token1.id == tokenOutAddress) ||
802
+ (subgraphPool.token1.id == wrappedNativeAddress &&
803
+ subgraphPool.token0.id == tokenOutAddress));
804
+ }
805
+ else {
806
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
807
+ subgraphPool.token1.id == tokenInAddress) ||
808
+ (subgraphPool.token1.id == wrappedNativeAddress &&
809
+ subgraphPool.token0.id == tokenInAddress));
810
+ }
811
+ })
812
+ .slice(0, 1)
813
+ .value();
814
+ }
815
+ addToAddressSet(top2EthQuoteTokenPool);
816
+ const topByTVL = _(subgraphPoolsSorted)
817
+ .filter((subgraphPool) => {
818
+ return !poolAddressesSoFar.has(subgraphPool.id);
819
+ })
820
+ .slice(0, topN)
821
+ .value();
822
+ addToAddressSet(topByTVL);
823
+ const topByTVLUsingTokenIn = _(subgraphPoolsSorted)
824
+ .filter((subgraphPool) => {
825
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
826
+ (subgraphPool.token0.id == tokenInAddress ||
827
+ subgraphPool.token1.id == tokenInAddress));
828
+ })
829
+ .filter((subgraphPool) => {
830
+ // in case of hooks only, it means we want to filter out hookless pools
831
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
832
+ return subgraphPool.hooks !== ADDRESS_ZERO;
833
+ }
834
+ // in case of no hooks, it means we want to filter out hook pools
835
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
836
+ return subgraphPool.hooks === ADDRESS_ZERO;
837
+ }
838
+ // otherwise it's the default case, so we just return true
839
+ return true;
840
+ })
841
+ .slice(0, topNTokenInOut)
842
+ .value();
843
+ addToAddressSet(topByTVLUsingTokenIn);
844
+ const topByTVLUsingTokenOut = _(subgraphPoolsSorted)
845
+ .filter((subgraphPool) => {
846
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
847
+ (subgraphPool.token0.id == tokenOutAddress ||
848
+ subgraphPool.token1.id == tokenOutAddress));
849
+ })
850
+ .filter((subgraphPool) => {
851
+ // in case of hooks only, it means we want to filter out hookless pools
852
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
853
+ return subgraphPool.hooks !== ADDRESS_ZERO;
854
+ }
855
+ // in case of no hooks, it means we want to filter out hook pools
856
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
857
+ return subgraphPool.hooks === ADDRESS_ZERO;
858
+ }
859
+ // otherwise it's the default case, so we just return true
860
+ return true;
861
+ })
862
+ .slice(0, topNTokenInOut)
863
+ .value();
864
+ addToAddressSet(topByTVLUsingTokenOut);
865
+ const topByTVLUsingTokenInSecondHops = _(topByTVLUsingTokenIn)
866
+ .map((subgraphPool) => {
867
+ return tokenInAddress == subgraphPool.token0.id
868
+ ? subgraphPool.token1.id
869
+ : subgraphPool.token0.id;
870
+ })
871
+ .flatMap((secondHopId) => {
872
+ var _a;
873
+ return _(subgraphPoolsSorted)
874
+ .filter((subgraphPool) => {
875
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
876
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
877
+ (subgraphPool.token0.id == secondHopId ||
878
+ subgraphPool.token1.id == secondHopId));
879
+ })
880
+ .filter((subgraphPool) => {
881
+ // in case of hooks only, it means we want to filter out hookless pools
882
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
883
+ return subgraphPool.hooks !== ADDRESS_ZERO;
884
+ }
885
+ // in case of no hooks, it means we want to filter out hook pools
886
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
887
+ return subgraphPool.hooks === ADDRESS_ZERO;
888
+ }
889
+ // otherwise it's the default case, so we just return true
890
+ return true;
891
+ })
892
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
893
+ .value();
894
+ })
895
+ .uniqBy((pool) => pool.id)
896
+ .value();
897
+ addToAddressSet(topByTVLUsingTokenInSecondHops);
898
+ const topByTVLUsingTokenOutSecondHops = _(topByTVLUsingTokenOut)
899
+ .map((subgraphPool) => {
900
+ return tokenOutAddress == subgraphPool.token0.id
901
+ ? subgraphPool.token1.id
902
+ : subgraphPool.token0.id;
903
+ })
904
+ .flatMap((secondHopId) => {
905
+ var _a;
906
+ return _(subgraphPoolsSorted)
907
+ .filter((subgraphPool) => {
908
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
909
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
910
+ (subgraphPool.token0.id == secondHopId ||
911
+ subgraphPool.token1.id == secondHopId));
912
+ })
913
+ .filter((subgraphPool) => {
914
+ // in case of hooks only, it means we want to filter out hookless pools
915
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
916
+ return subgraphPool.hooks !== ADDRESS_ZERO;
917
+ }
918
+ // in case of no hooks, it means we want to filter out hook pools
919
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
920
+ return subgraphPool.hooks === ADDRESS_ZERO;
921
+ }
922
+ // otherwise it's the default case, so we just return true
923
+ return true;
924
+ })
925
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
926
+ .value();
927
+ })
928
+ .uniqBy((pool) => pool.id)
929
+ .value();
930
+ addToAddressSet(topByTVLUsingTokenOutSecondHops);
931
+ const subgraphPools = _([
932
+ ...topByBaseWithTokenIn,
933
+ ...topByBaseWithTokenOut,
934
+ ...top2DirectSwapPool,
935
+ ...top2EthQuoteTokenPool,
936
+ ...topByTVL,
937
+ ...topByTVLUsingTokenIn,
938
+ ...topByTVLUsingTokenOut,
939
+ ...topByTVLUsingTokenInSecondHops,
940
+ ...topByTVLUsingTokenOutSecondHops,
941
+ ])
942
+ .compact()
943
+ .uniqBy((pool) => pool.id)
944
+ .value();
945
+ const tokenAddresses = _(subgraphPools)
946
+ .flatMap((subgraphPool) => [subgraphPool.token0.id, subgraphPool.token1.id])
947
+ .compact()
948
+ .uniq()
949
+ .value();
950
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V4 pools we are considering`);
951
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
952
+ blockNumber,
953
+ });
954
+ const printV4SubgraphPool = (s) => {
955
+ var _a, _b, _c, _d;
956
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}/${s.feeTier}/${s.tickSpacing}/${s.hooks}`;
957
+ };
958
+ log.info({
959
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV4SubgraphPool),
960
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV4SubgraphPool),
961
+ topByTVL: topByTVL.map(printV4SubgraphPool),
962
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV4SubgraphPool),
963
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV4SubgraphPool),
964
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV4SubgraphPool),
965
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV4SubgraphPool),
966
+ top2DirectSwap: top2DirectSwapPool.map(printV4SubgraphPool),
967
+ top2EthQuotePool: top2EthQuoteTokenPool.map(printV4SubgraphPool),
968
+ }, `V4 Candidate Pools`);
969
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
970
+ // native currency is not erc20 token, therefore there's no way to retrieve native currency metadata as the erc20 token.
971
+ const tokenA = isNativeCurrency(subgraphPool.token0.id)
972
+ ? nativeOnChain(chainId)
973
+ : tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
974
+ const tokenB = isNativeCurrency(subgraphPool.token1.id)
975
+ ? nativeOnChain(chainId)
976
+ : tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
977
+ let fee;
978
+ try {
979
+ fee = Number(subgraphPool.feeTier);
980
+ fee = isPoolFeeDynamic(tokenA, tokenB, Number(subgraphPool.tickSpacing), subgraphPool.hooks, subgraphPool.id)
981
+ ? DYNAMIC_FEE_FLAG
982
+ : fee;
983
+ }
984
+ catch (err) {
985
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier} because fee tier not supported`);
986
+ return undefined;
987
+ }
988
+ if (!tokenA || !tokenB) {
989
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
990
+ return undefined;
991
+ }
992
+ return [
993
+ tokenA,
994
+ tokenB,
995
+ fee,
996
+ Number(subgraphPool.tickSpacing),
997
+ subgraphPool.hooks,
998
+ ];
999
+ });
1000
+ const tokenPairs = _.compact(tokenPairsRaw);
1001
+ metric.putMetric('V4PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
1002
+ const beforePoolsLoad = Date.now();
1003
+ const poolAccessor = await poolProvider.getPools(tokenPairs, {
1004
+ blockNumber,
1005
+ });
1006
+ metric.putMetric('V4PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
1007
+ const poolsBySelection = {
1008
+ protocol: Protocol.V4,
1009
+ selections: {
1010
+ topByBaseWithTokenIn,
1011
+ topByBaseWithTokenOut,
1012
+ topByDirectSwapPool: top2DirectSwapPool,
1013
+ topByEthQuoteTokenPool: top2EthQuoteTokenPool,
1014
+ topByTVL,
1015
+ topByTVLUsingTokenIn,
1016
+ topByTVLUsingTokenOut,
1017
+ topByTVLUsingTokenInSecondHops,
1018
+ topByTVLUsingTokenOutSecondHops,
1019
+ },
1020
+ };
1021
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
1022
+ }
1023
+ export async function getV3CandidatePools({ tokenIn, tokenOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, }) {
1024
+ var _a, _b, _c, _d, _e;
1025
+ const { blockNumber, v3PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, topNSecondHopForTokenAddress, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
1026
+ const tokenInAddress = tokenIn.address.toLowerCase();
1027
+ const tokenOutAddress = tokenOut.address.toLowerCase();
1028
+ const beforeSubgraphPools = Date.now();
1029
+ const allPools = await subgraphProvider.getPools(tokenIn, tokenOut, {
1030
+ blockNumber,
1031
+ });
1032
+ log.info({ samplePools: allPools.slice(0, 3) }, 'Got all pools from V3 subgraph provider');
1033
+ // Although this is less of an optimization than the V2 equivalent,
1034
+ // save some time copying objects by mutating the underlying pool directly.
1035
+ for (const pool of allPools) {
1036
+ pool.token0.id = pool.token0.id.toLowerCase();
1037
+ pool.token1.id = pool.token1.id.toLowerCase();
1038
+ }
1039
+ metric.putMetric('V3SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
1040
+ const beforePoolsFiltered = Date.now();
1041
+ // Only consider pools where neither tokens are in the blocked token list.
1042
+ let filteredPools = allPools;
1043
+ if (blockedTokenListProvider) {
1044
+ filteredPools = [];
1045
+ for (const pool of allPools) {
1046
+ const token0InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token0.id);
1047
+ const token1InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token1.id);
1048
+ if (token0InBlocklist || token1InBlocklist) {
1049
+ continue;
1050
+ }
1051
+ filteredPools.push(pool);
1052
+ }
1053
+ }
1054
+ // Sort by tvlUSD in descending order
1055
+ const subgraphPoolsSorted = filteredPools.sort((a, b) => b.tvlUSD - a.tvlUSD);
1056
+ log.info(`V3 After filtering blocked tokens went from ${allPools.length} to ${subgraphPoolsSorted.length}.`);
1057
+ const poolAddressesSoFar = new Set();
1058
+ const addToAddressSet = (pools) => {
1059
+ _(pools)
1060
+ .map((pool) => pool.id)
1061
+ .forEach((poolAddress) => poolAddressesSoFar.add(poolAddress));
1062
+ };
1063
+ const baseTokens = (_a = baseTokensByChain[chainId]) !== null && _a !== void 0 ? _a : [];
1064
+ const topByBaseWithTokenIn = _(baseTokens)
1065
+ .flatMap((token) => {
1066
+ return _(subgraphPoolsSorted)
1067
+ .filter((subgraphPool) => {
1068
+ const tokenAddress = token.address.toLowerCase();
1069
+ return ((subgraphPool.token0.id == tokenAddress &&
1070
+ subgraphPool.token1.id == tokenInAddress) ||
1071
+ (subgraphPool.token1.id == tokenAddress &&
1072
+ subgraphPool.token0.id == tokenInAddress));
1073
+ })
1074
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
1075
+ .slice(0, topNWithEachBaseToken)
1076
+ .value();
1077
+ })
1078
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
1079
+ .slice(0, topNWithBaseToken)
1080
+ .value();
1081
+ const topByBaseWithTokenOut = _(baseTokens)
1082
+ .flatMap((token) => {
1083
+ return _(subgraphPoolsSorted)
1084
+ .filter((subgraphPool) => {
1085
+ const tokenAddress = token.address.toLowerCase();
1086
+ return ((subgraphPool.token0.id == tokenAddress &&
1087
+ subgraphPool.token1.id == tokenOutAddress) ||
1088
+ (subgraphPool.token1.id == tokenAddress &&
1089
+ subgraphPool.token0.id == tokenOutAddress));
1090
+ })
1091
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
1092
+ .slice(0, topNWithEachBaseToken)
1093
+ .value();
1094
+ })
1095
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
1096
+ .slice(0, topNWithBaseToken)
1097
+ .value();
1098
+ let top2DirectSwapPool = _(subgraphPoolsSorted)
1099
+ .filter((subgraphPool) => {
1100
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1101
+ ((subgraphPool.token0.id == tokenInAddress &&
1102
+ subgraphPool.token1.id == tokenOutAddress) ||
1103
+ (subgraphPool.token1.id == tokenInAddress &&
1104
+ subgraphPool.token0.id == tokenOutAddress)));
1105
+ })
1106
+ .slice(0, topNDirectSwaps)
1107
+ .value();
1108
+ if (top2DirectSwapPool.length == 0 && topNDirectSwaps > 0) {
1109
+ // We don't want to re-add AMPL token pools for V3 in Mainnet.
1110
+ // TODO: ROUTE-347, Remove this check once we have a better way to sync filters from subgraph cronjob <> routing path.
1111
+ if (!(chainId == ChainId.MAINNET &&
1112
+ (tokenIn.address.toLowerCase() ===
1113
+ '0xd46ba6d942050d489dbd938a2c909a5d5039a161' ||
1114
+ tokenOut.address.toLowerCase() ===
1115
+ '0xd46ba6d942050d489dbd938a2c909a5d5039a161'))) {
1116
+ // If we requested direct swap pools but did not find any in the subgraph query.
1117
+ // Optimistically add them into the query regardless. Invalid pools ones will be dropped anyway
1118
+ // when we query the pool on-chain. Ensures that new pools for new pairs can be swapped on immediately.
1119
+ top2DirectSwapPool = _.map(getApplicableV3FeeAmounts(chainId), (feeAmount) => {
1120
+ const { token0, token1, poolAddress } = poolProvider.getPoolAddress(tokenIn, tokenOut, feeAmount);
1121
+ return {
1122
+ id: poolAddress,
1123
+ feeTier: unparseFeeAmount(feeAmount),
1124
+ liquidity: '10000',
1125
+ token0: {
1126
+ id: token0.address,
1127
+ },
1128
+ token1: {
1129
+ id: token1.address,
1130
+ },
1131
+ tvlETH: 10000,
1132
+ tvlUSD: 10000,
1133
+ };
1134
+ });
1135
+ }
1136
+ }
1137
+ addToAddressSet(top2DirectSwapPool);
1138
+ const wrappedNativeAddress = (_b = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _b === void 0 ? void 0 : _b.address.toLowerCase();
1139
+ // Main reason we need this is for gas estimates, only needed if token out is not native.
1140
+ // We don't check the seen address set because if we've already added pools for getting native quotes
1141
+ // theres no need to add more.
1142
+ let top2EthQuoteTokenPool = [];
1143
+ if ((((_c = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _c === void 0 ? void 0 : _c.symbol) ==
1144
+ ((_d = WRAPPED_NATIVE_CURRENCY[ChainId.MAINNET]) === null || _d === void 0 ? void 0 : _d.symbol) &&
1145
+ tokenOut.symbol != 'WETH' &&
1146
+ tokenOut.symbol != 'WETH9' &&
1147
+ tokenOut.symbol != 'ETH') ||
1148
+ (((_e = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _e === void 0 ? void 0 : _e.symbol) == WMATIC_POLYGON.symbol &&
1149
+ tokenOut.symbol != 'MATIC' &&
1150
+ tokenOut.symbol != 'WMATIC')) {
1151
+ top2EthQuoteTokenPool = _(subgraphPoolsSorted)
1152
+ .filter((subgraphPool) => {
1153
+ if (routeType == TradeType.EXACT_INPUT) {
1154
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
1155
+ subgraphPool.token1.id == tokenOutAddress) ||
1156
+ (subgraphPool.token1.id == wrappedNativeAddress &&
1157
+ subgraphPool.token0.id == tokenOutAddress));
1158
+ }
1159
+ else {
1160
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
1161
+ subgraphPool.token1.id == tokenInAddress) ||
1162
+ (subgraphPool.token1.id == wrappedNativeAddress &&
1163
+ subgraphPool.token0.id == tokenInAddress));
1164
+ }
1165
+ })
1166
+ .slice(0, 1)
1167
+ .value();
1168
+ }
1169
+ addToAddressSet(top2EthQuoteTokenPool);
1170
+ const topByTVL = _(subgraphPoolsSorted)
1171
+ .filter((subgraphPool) => {
1172
+ return !poolAddressesSoFar.has(subgraphPool.id);
1173
+ })
1174
+ .slice(0, topN)
1175
+ .value();
1176
+ addToAddressSet(topByTVL);
1177
+ const topByTVLUsingTokenIn = _(subgraphPoolsSorted)
1178
+ .filter((subgraphPool) => {
1179
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1180
+ (subgraphPool.token0.id == tokenInAddress ||
1181
+ subgraphPool.token1.id == tokenInAddress));
1182
+ })
1183
+ .slice(0, topNTokenInOut)
1184
+ .value();
1185
+ addToAddressSet(topByTVLUsingTokenIn);
1186
+ const topByTVLUsingTokenOut = _(subgraphPoolsSorted)
1187
+ .filter((subgraphPool) => {
1188
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1189
+ (subgraphPool.token0.id == tokenOutAddress ||
1190
+ subgraphPool.token1.id == tokenOutAddress));
1191
+ })
1192
+ .slice(0, topNTokenInOut)
1193
+ .value();
1194
+ addToAddressSet(topByTVLUsingTokenOut);
1195
+ const topByTVLUsingTokenInSecondHops = _(topByTVLUsingTokenIn)
1196
+ .map((subgraphPool) => {
1197
+ return tokenInAddress == subgraphPool.token0.id
1198
+ ? subgraphPool.token1.id
1199
+ : subgraphPool.token0.id;
1200
+ })
1201
+ .flatMap((secondHopId) => {
1202
+ var _a;
1203
+ return _(subgraphPoolsSorted)
1204
+ .filter((subgraphPool) => {
1205
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1206
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
1207
+ (subgraphPool.token0.id == secondHopId ||
1208
+ subgraphPool.token1.id == secondHopId));
1209
+ })
1210
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
1211
+ .value();
1212
+ })
1213
+ .uniqBy((pool) => pool.id)
1214
+ .value();
1215
+ addToAddressSet(topByTVLUsingTokenInSecondHops);
1216
+ const topByTVLUsingTokenOutSecondHops = _(topByTVLUsingTokenOut)
1217
+ .map((subgraphPool) => {
1218
+ return tokenOutAddress == subgraphPool.token0.id
1219
+ ? subgraphPool.token1.id
1220
+ : subgraphPool.token0.id;
1221
+ })
1222
+ .flatMap((secondHopId) => {
1223
+ var _a;
1224
+ return _(subgraphPoolsSorted)
1225
+ .filter((subgraphPool) => {
1226
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1227
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
1228
+ (subgraphPool.token0.id == secondHopId ||
1229
+ subgraphPool.token1.id == secondHopId));
1230
+ })
1231
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
1232
+ .value();
1233
+ })
1234
+ .uniqBy((pool) => pool.id)
1235
+ .value();
1236
+ addToAddressSet(topByTVLUsingTokenOutSecondHops);
1237
+ const subgraphPools = _([
1238
+ ...topByBaseWithTokenIn,
1239
+ ...topByBaseWithTokenOut,
1240
+ ...top2DirectSwapPool,
1241
+ ...top2EthQuoteTokenPool,
1242
+ ...topByTVL,
1243
+ ...topByTVLUsingTokenIn,
1244
+ ...topByTVLUsingTokenOut,
1245
+ ...topByTVLUsingTokenInSecondHops,
1246
+ ...topByTVLUsingTokenOutSecondHops,
1247
+ ])
1248
+ .compact()
1249
+ .uniqBy((pool) => pool.id)
1250
+ .value();
1251
+ const tokenAddresses = _(subgraphPools)
1252
+ .flatMap((subgraphPool) => [subgraphPool.token0.id, subgraphPool.token1.id])
1253
+ .compact()
1254
+ .uniq()
1255
+ .value();
1256
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V3 pools we are considering`);
1257
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
1258
+ blockNumber,
1259
+ });
1260
+ const printV3SubgraphPool = (s) => {
1261
+ var _a, _b, _c, _d;
1262
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}/${s.feeTier}`;
1263
+ };
1264
+ log.info({
1265
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV3SubgraphPool),
1266
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV3SubgraphPool),
1267
+ topByTVL: topByTVL.map(printV3SubgraphPool),
1268
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV3SubgraphPool),
1269
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV3SubgraphPool),
1270
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV3SubgraphPool),
1271
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV3SubgraphPool),
1272
+ top2DirectSwap: top2DirectSwapPool.map(printV3SubgraphPool),
1273
+ top2EthQuotePool: top2EthQuoteTokenPool.map(printV3SubgraphPool),
1274
+ }, `V3 Candidate Pools`);
1275
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
1276
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
1277
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
1278
+ let fee;
1279
+ try {
1280
+ fee = parseFeeAmount(subgraphPool.feeTier);
1281
+ }
1282
+ catch (err) {
1283
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier} because fee tier not supported`);
1284
+ return undefined;
1285
+ }
1286
+ if (!tokenA || !tokenB) {
1287
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
1288
+ return undefined;
1289
+ }
1290
+ return [tokenA, tokenB, fee];
1291
+ });
1292
+ const tokenPairs = _.compact(tokenPairsRaw);
1293
+ metric.putMetric('V3PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
1294
+ const beforePoolsLoad = Date.now();
1295
+ const poolAccessor = await poolProvider.getPools(tokenPairs, {
1296
+ blockNumber,
1297
+ });
1298
+ metric.putMetric('V3PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
1299
+ const poolsBySelection = {
1300
+ protocol: Protocol.V3,
1301
+ selections: {
1302
+ topByBaseWithTokenIn,
1303
+ topByBaseWithTokenOut,
1304
+ topByDirectSwapPool: top2DirectSwapPool,
1305
+ topByEthQuoteTokenPool: top2EthQuoteTokenPool,
1306
+ topByTVL,
1307
+ topByTVLUsingTokenIn,
1308
+ topByTVLUsingTokenOut,
1309
+ topByTVLUsingTokenInSecondHops,
1310
+ topByTVLUsingTokenOutSecondHops,
1311
+ },
1312
+ };
1313
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
1314
+ }
1315
+ export async function getUniswapFewTokenV3CandidatePools({ tokenIn, tokenOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, }) {
1316
+ var _a, _b, _c, _d, _e;
1317
+ const { blockNumber, v3PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, topNSecondHopForTokenAddress, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
1318
+ const tokenInAddress = tokenIn.address.toLowerCase();
1319
+ const tokenOutAddress = tokenOut.address.toLowerCase();
1320
+ const beforeSubgraphPools = Date.now();
1321
+ const allPools = await subgraphProvider.getPools(tokenIn, tokenOut, {
1322
+ blockNumber,
1323
+ });
1324
+ log.info({ samplePools: allPools.slice(0, 3) }, 'Got all pools from V3 subgraph provider');
1325
+ // Although this is less of an optimization than the V2 equivalent,
1326
+ // save some time copying objects by mutating the underlying pool directly.
1327
+ for (const pool of allPools) {
1328
+ pool.token0.id = pool.token0.id.toLowerCase();
1329
+ pool.token1.id = pool.token1.id.toLowerCase();
1330
+ }
1331
+ metric.putMetric('V3SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
1332
+ const beforePoolsFiltered = Date.now();
1333
+ // Only consider pools where neither tokens are in the blocked token list.
1334
+ let filteredPools = allPools;
1335
+ if (blockedTokenListProvider) {
1336
+ filteredPools = [];
1337
+ for (const pool of allPools) {
1338
+ const token0InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token0.id);
1339
+ const token1InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token1.id);
1340
+ if (token0InBlocklist || token1InBlocklist) {
1341
+ continue;
1342
+ }
1343
+ filteredPools.push(pool);
1344
+ }
1345
+ }
1346
+ // Sort by tvlUSD in descending order
1347
+ const subgraphPoolsSorted = filteredPools.sort((a, b) => b.tvlUSD - a.tvlUSD);
1348
+ log.info(`Uniswap v3 few after filtering blocked tokens went from ${allPools.length} to ${subgraphPoolsSorted.length}.`);
1349
+ const poolAddressesSoFar = new Set();
1350
+ const addToAddressSet = (pools) => {
1351
+ _(pools)
1352
+ .map((pool) => pool.id)
1353
+ .forEach((poolAddress) => poolAddressesSoFar.add(poolAddress));
1354
+ };
1355
+ const baseTokens = (_a = fewBaseTokensByChain[chainId]) !== null && _a !== void 0 ? _a : [];
1356
+ const topByBaseWithTokenIn = _(baseTokens)
1357
+ .flatMap((token) => {
1358
+ return _(subgraphPoolsSorted)
1359
+ .filter((subgraphPool) => {
1360
+ const tokenAddress = token.address.toLowerCase();
1361
+ return ((subgraphPool.token0.id == tokenAddress &&
1362
+ subgraphPool.token1.id == tokenInAddress) ||
1363
+ (subgraphPool.token1.id == tokenAddress &&
1364
+ subgraphPool.token0.id == tokenInAddress));
1365
+ })
1366
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
1367
+ .slice(0, topNWithEachBaseToken)
1368
+ .value();
1369
+ })
1370
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
1371
+ .slice(0, topNWithBaseToken)
1372
+ .value();
1373
+ const topByBaseWithTokenOut = _(baseTokens)
1374
+ .flatMap((token) => {
1375
+ return _(subgraphPoolsSorted)
1376
+ .filter((subgraphPool) => {
1377
+ const tokenAddress = token.address.toLowerCase();
1378
+ return ((subgraphPool.token0.id == tokenAddress &&
1379
+ subgraphPool.token1.id == tokenOutAddress) ||
1380
+ (subgraphPool.token1.id == tokenAddress &&
1381
+ subgraphPool.token0.id == tokenOutAddress));
1382
+ })
1383
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
1384
+ .slice(0, topNWithEachBaseToken)
1385
+ .value();
1386
+ })
1387
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
1388
+ .slice(0, topNWithBaseToken)
1389
+ .value();
1390
+ let top2DirectSwapPool = _(subgraphPoolsSorted)
1391
+ .filter((subgraphPool) => {
1392
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1393
+ ((subgraphPool.token0.id == tokenInAddress &&
1394
+ subgraphPool.token1.id == tokenOutAddress) ||
1395
+ (subgraphPool.token1.id == tokenInAddress &&
1396
+ subgraphPool.token0.id == tokenOutAddress)));
1397
+ })
1398
+ .slice(0, topNDirectSwaps)
1399
+ .value();
1400
+ if (top2DirectSwapPool.length == 0 && topNDirectSwaps > 0) {
1401
+ // We don't want to re-add AMPL token pools for V3 in Mainnet.
1402
+ // TODO: ROUTE-347, Remove this check once we have a better way to sync filters from subgraph cronjob <> routing path.
1403
+ if (!(chainId == ChainId.MAINNET &&
1404
+ (tokenIn.address.toLowerCase() ===
1405
+ '0xd46ba6d942050d489dbd938a2c909a5d5039a161' ||
1406
+ tokenOut.address.toLowerCase() ===
1407
+ '0xd46ba6d942050d489dbd938a2c909a5d5039a161'))) {
1408
+ // If we requested direct swap pools but did not find any in the subgraph query.
1409
+ // Optimistically add them into the query regardless. Invalid pools ones will be dropped anyway
1410
+ // when we query the pool on-chain. Ensures that new pools for new pairs can be swapped on immediately.
1411
+ top2DirectSwapPool = _.map(getApplicableV3FeeAmounts(chainId), (feeAmount) => {
1412
+ const { token0, token1, poolAddress } = poolProvider.getPoolAddress(tokenIn, tokenOut, feeAmount);
1413
+ return {
1414
+ id: poolAddress,
1415
+ feeTier: unparseFeeAmount(feeAmount),
1416
+ liquidity: '10000',
1417
+ token0: {
1418
+ id: token0.address,
1419
+ },
1420
+ token1: {
1421
+ id: token1.address,
1422
+ },
1423
+ tvlETH: 10000,
1424
+ tvlUSD: 10000,
1425
+ };
1426
+ });
1427
+ }
1428
+ }
1429
+ addToAddressSet(top2DirectSwapPool);
1430
+ const wrappedNativeAddress = (_b = FEW_WRAPPED_NATIVE_CURRENCY[chainId]) === null || _b === void 0 ? void 0 : _b.address.toLowerCase();
1431
+ // Main reason we need this is for gas estimates, only needed if token out is not native.
1432
+ // We don't check the seen address set because if we've already added pools for getting native quotes
1433
+ // theres no need to add more.
1434
+ let top2EthQuoteTokenPool = [];
1435
+ if ((((_c = FEW_WRAPPED_NATIVE_CURRENCY[chainId]) === null || _c === void 0 ? void 0 : _c.symbol) ==
1436
+ ((_d = FEW_WRAPPED_NATIVE_CURRENCY[ChainId.MAINNET]) === null || _d === void 0 ? void 0 : _d.symbol) &&
1437
+ tokenOut.symbol != 'WETH' &&
1438
+ tokenOut.symbol != 'WETH9' &&
1439
+ tokenOut.symbol != 'ETH') ||
1440
+ (((_e = FEW_WRAPPED_NATIVE_CURRENCY[chainId]) === null || _e === void 0 ? void 0 : _e.symbol) == WMATIC_POLYGON.symbol &&
1441
+ tokenOut.symbol != 'MATIC' &&
1442
+ tokenOut.symbol != 'WMATIC')) {
1443
+ top2EthQuoteTokenPool = _(subgraphPoolsSorted)
1444
+ .filter((subgraphPool) => {
1445
+ if (routeType == TradeType.EXACT_INPUT) {
1446
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
1447
+ subgraphPool.token1.id == tokenOutAddress) ||
1448
+ (subgraphPool.token1.id == wrappedNativeAddress &&
1449
+ subgraphPool.token0.id == tokenOutAddress));
1450
+ }
1451
+ else {
1452
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
1453
+ subgraphPool.token1.id == tokenInAddress) ||
1454
+ (subgraphPool.token1.id == wrappedNativeAddress &&
1455
+ subgraphPool.token0.id == tokenInAddress));
1456
+ }
1457
+ })
1458
+ .slice(0, 1)
1459
+ .value();
1460
+ }
1461
+ addToAddressSet(top2EthQuoteTokenPool);
1462
+ const topByTVL = _(subgraphPoolsSorted)
1463
+ .filter((subgraphPool) => {
1464
+ return !poolAddressesSoFar.has(subgraphPool.id);
1465
+ })
1466
+ .slice(0, topN)
1467
+ .value();
1468
+ addToAddressSet(topByTVL);
1469
+ const topByTVLUsingTokenIn = _(subgraphPoolsSorted)
1470
+ .filter((subgraphPool) => {
1471
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1472
+ (subgraphPool.token0.id == tokenInAddress ||
1473
+ subgraphPool.token1.id == tokenInAddress));
1474
+ })
1475
+ .slice(0, topNTokenInOut)
1476
+ .value();
1477
+ addToAddressSet(topByTVLUsingTokenIn);
1478
+ const topByTVLUsingTokenOut = _(subgraphPoolsSorted)
1479
+ .filter((subgraphPool) => {
1480
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1481
+ (subgraphPool.token0.id == tokenOutAddress ||
1482
+ subgraphPool.token1.id == tokenOutAddress));
1483
+ })
1484
+ .slice(0, topNTokenInOut)
1485
+ .value();
1486
+ addToAddressSet(topByTVLUsingTokenOut);
1487
+ const topByTVLUsingTokenInSecondHops = _(topByTVLUsingTokenIn)
1488
+ .map((subgraphPool) => {
1489
+ return tokenInAddress == subgraphPool.token0.id
1490
+ ? subgraphPool.token1.id
1491
+ : subgraphPool.token0.id;
1492
+ })
1493
+ .flatMap((secondHopId) => {
1494
+ var _a;
1495
+ return _(subgraphPoolsSorted)
1496
+ .filter((subgraphPool) => {
1497
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1498
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
1499
+ (subgraphPool.token0.id == secondHopId ||
1500
+ subgraphPool.token1.id == secondHopId));
1501
+ })
1502
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
1503
+ .value();
1504
+ })
1505
+ .uniqBy((pool) => pool.id)
1506
+ .value();
1507
+ addToAddressSet(topByTVLUsingTokenInSecondHops);
1508
+ const topByTVLUsingTokenOutSecondHops = _(topByTVLUsingTokenOut)
1509
+ .map((subgraphPool) => {
1510
+ return tokenOutAddress == subgraphPool.token0.id
1511
+ ? subgraphPool.token1.id
1512
+ : subgraphPool.token0.id;
1513
+ })
1514
+ .flatMap((secondHopId) => {
1515
+ var _a;
1516
+ return _(subgraphPoolsSorted)
1517
+ .filter((subgraphPool) => {
1518
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
1519
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
1520
+ (subgraphPool.token0.id == secondHopId ||
1521
+ subgraphPool.token1.id == secondHopId));
1522
+ })
1523
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
1524
+ .value();
1525
+ })
1526
+ .uniqBy((pool) => pool.id)
1527
+ .value();
1528
+ addToAddressSet(topByTVLUsingTokenOutSecondHops);
1529
+ const subgraphPools = _([
1530
+ ...topByBaseWithTokenIn,
1531
+ ...topByBaseWithTokenOut,
1532
+ ...top2DirectSwapPool,
1533
+ ...top2EthQuoteTokenPool,
1534
+ ...topByTVL,
1535
+ ...topByTVLUsingTokenIn,
1536
+ ...topByTVLUsingTokenOut,
1537
+ ...topByTVLUsingTokenInSecondHops,
1538
+ ...topByTVLUsingTokenOutSecondHops,
1539
+ ])
1540
+ .compact()
1541
+ .uniqBy((pool) => pool.id)
1542
+ .value();
1543
+ const tokenAddresses = _(subgraphPools)
1544
+ .flatMap((subgraphPool) => [subgraphPool.token0.id, subgraphPool.token1.id])
1545
+ .compact()
1546
+ .uniq()
1547
+ .value();
1548
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V3 pools we are considering`);
1549
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
1550
+ blockNumber,
1551
+ });
1552
+ const printV3SubgraphPool = (s) => {
1553
+ var _a, _b, _c, _d;
1554
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}/${s.feeTier}`;
1555
+ };
1556
+ log.info({
1557
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV3SubgraphPool),
1558
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV3SubgraphPool),
1559
+ topByTVL: topByTVL.map(printV3SubgraphPool),
1560
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV3SubgraphPool),
1561
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV3SubgraphPool),
1562
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV3SubgraphPool),
1563
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV3SubgraphPool),
1564
+ top2DirectSwap: top2DirectSwapPool.map(printV3SubgraphPool),
1565
+ top2EthQuotePool: top2EthQuoteTokenPool.map(printV3SubgraphPool),
1566
+ }, `V3 Candidate Pools`);
1567
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
1568
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
1569
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
1570
+ let fee;
1571
+ try {
1572
+ fee = parseFeeAmount(subgraphPool.feeTier);
1573
+ }
1574
+ catch (err) {
1575
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier} because fee tier not supported`);
1576
+ return undefined;
1577
+ }
1578
+ if (!tokenA || !tokenB) {
1579
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
1580
+ return undefined;
1581
+ }
1582
+ return [tokenA, tokenB, fee];
1583
+ });
1584
+ const tokenPairs = _.compact(tokenPairsRaw);
1585
+ metric.putMetric('V3PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
1586
+ const beforePoolsLoad = Date.now();
1587
+ const poolAccessor = await poolProvider.getPools(tokenPairs, {
1588
+ blockNumber,
1589
+ });
1590
+ metric.putMetric('V3PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
1591
+ const poolsBySelection = {
1592
+ protocol: Protocol.V3,
1593
+ selections: {
1594
+ topByBaseWithTokenIn,
1595
+ topByBaseWithTokenOut,
1596
+ topByDirectSwapPool: top2DirectSwapPool,
1597
+ topByEthQuoteTokenPool: top2EthQuoteTokenPool,
1598
+ topByTVL,
1599
+ topByTVLUsingTokenIn,
1600
+ topByTVLUsingTokenOut,
1601
+ topByTVLUsingTokenInSecondHops,
1602
+ topByTVLUsingTokenOutSecondHops,
1603
+ },
1604
+ };
1605
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
1606
+ }
1607
+ export async function getV2CandidatePools({ tokenIn, tokenOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, }) {
1608
+ var _a;
1609
+ const { blockNumber, v2PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
1610
+ const tokenInAddress = tokenIn.address.toLowerCase();
1611
+ const tokenOutAddress = tokenOut.address.toLowerCase();
1612
+ const beforeSubgraphPools = Date.now();
1613
+ const allPoolsRaw = await subgraphProvider.getPools(tokenIn, tokenOut, {
1614
+ blockNumber,
1615
+ });
1616
+ // With tens of thousands of V2 pools, operations that copy pools become costly.
1617
+ // Mutate the pool directly rather than creating a new pool / token to optimmize for speed.
1618
+ for (const pool of allPoolsRaw) {
1619
+ pool.token0.id = pool.token0.id.toLowerCase();
1620
+ pool.token1.id = pool.token1.id.toLowerCase();
1621
+ }
1622
+ metric.putMetric('V2SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
1623
+ const beforePoolsFiltered = Date.now();
1624
+ // Sort by pool reserve in descending order.
1625
+ const subgraphPoolsSorted = allPoolsRaw.sort((a, b) => b.reserve - a.reserve);
1626
+ const poolAddressesSoFar = new Set();
1627
+ // Always add the direct swap pool into the mix regardless of if it exists in the subgraph pool list.
1628
+ // Ensures that new pools can be swapped on immediately, and that if a pool was filtered out of the
1629
+ // subgraph query for some reason (e.g. trackedReserveETH was 0), then we still consider it.
1630
+ let topByDirectSwapPool = [];
1631
+ if (topNDirectSwaps > 0) {
1632
+ const { token0, token1, poolAddress } = poolProvider.getPoolAddress(tokenIn, tokenOut);
1633
+ poolAddressesSoFar.add(poolAddress.toLowerCase());
1634
+ topByDirectSwapPool = [
1635
+ {
1636
+ id: poolAddress,
1637
+ token0: {
1638
+ id: token0.address,
1639
+ },
1640
+ token1: {
1641
+ id: token1.address,
1642
+ },
1643
+ supply: 10000,
1644
+ reserve: 10000,
1645
+ reserveUSD: 10000, // Not used. Set to arbitrary number.
1646
+ },
1647
+ ];
1648
+ }
1649
+ const wethAddress = WRAPPED_NATIVE_CURRENCY[chainId].address.toLowerCase();
1650
+ const topByBaseWithTokenInMap = new Map();
1651
+ const topByBaseWithTokenOutMap = new Map();
1652
+ const baseTokens = (_a = baseTokensByChain[chainId]) !== null && _a !== void 0 ? _a : [];
1653
+ const baseTokensAddresses = new Set();
1654
+ baseTokens.forEach((token) => {
1655
+ const baseTokenAddr = token.address.toLowerCase();
1656
+ baseTokensAddresses.add(baseTokenAddr);
1657
+ topByBaseWithTokenInMap.set(baseTokenAddr, new SubcategorySelectionPools([], topNWithEachBaseToken));
1658
+ topByBaseWithTokenOutMap.set(baseTokenAddr, new SubcategorySelectionPools([], topNWithEachBaseToken));
1659
+ });
1660
+ let topByBaseWithTokenInPoolsFound = 0;
1661
+ let topByBaseWithTokenOutPoolsFound = 0;
1662
+ // Main reason we need this is for gas estimates
1663
+ // There can ever only be 1 Token/ETH pool, so we will only look for 1
1664
+ let topNEthQuoteToken = 1;
1665
+ // but, we only need it if token out is not ETH.
1666
+ if (tokenOut.symbol == 'WETH' ||
1667
+ tokenOut.symbol == 'WETH9' ||
1668
+ tokenOut.symbol == 'ETH') {
1669
+ // if it's eth we change the topN to 0, so we can break early from the loop.
1670
+ topNEthQuoteToken = 0;
1671
+ }
1672
+ const topByEthQuoteTokenPool = [];
1673
+ const topByTVLUsingTokenIn = [];
1674
+ const topByTVLUsingTokenOut = [];
1675
+ const topByTVL = [];
1676
+ // Used to track how many iterations we do in the first loop
1677
+ let loopsInFirstIteration = 0;
1678
+ // Filtering step for up to first hop
1679
+ // The pools are pre-sorted, so we can just iterate through them and fill our heuristics.
1680
+ for (const subgraphPool of subgraphPoolsSorted) {
1681
+ loopsInFirstIteration += 1;
1682
+ // Check if we have satisfied all the heuristics, if so, we can stop.
1683
+ if (topByBaseWithTokenInPoolsFound >= topNWithBaseToken &&
1684
+ topByBaseWithTokenOutPoolsFound >= topNWithBaseToken &&
1685
+ topByEthQuoteTokenPool.length >= topNEthQuoteToken &&
1686
+ topByTVL.length >= topN &&
1687
+ topByTVLUsingTokenIn.length >= topNTokenInOut &&
1688
+ topByTVLUsingTokenOut.length >= topNTokenInOut) {
1689
+ // We have satisfied all the heuristics, so we can stop.
1690
+ break;
1691
+ }
1692
+ if (poolAddressesSoFar.has(subgraphPool.id)) {
1693
+ // We've already added this pool, so skip it.
1694
+ continue;
1695
+ }
1696
+ // Only consider pools where neither tokens are in the blocked token list.
1697
+ if (blockedTokenListProvider) {
1698
+ const [token0InBlocklist, token1InBlocklist] = await Promise.all([
1699
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token0.id),
1700
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token1.id),
1701
+ ]);
1702
+ if (token0InBlocklist || token1InBlocklist) {
1703
+ continue;
1704
+ }
1705
+ }
1706
+ const tokenInToken0TopByBase = topByBaseWithTokenInMap.get(subgraphPool.token0.id);
1707
+ if (topByBaseWithTokenInPoolsFound < topNWithBaseToken &&
1708
+ tokenInToken0TopByBase &&
1709
+ subgraphPool.token0.id != tokenOutAddress &&
1710
+ subgraphPool.token1.id == tokenInAddress) {
1711
+ topByBaseWithTokenInPoolsFound += 1;
1712
+ poolAddressesSoFar.add(subgraphPool.id);
1713
+ if (topByTVLUsingTokenIn.length < topNTokenInOut) {
1714
+ topByTVLUsingTokenIn.push(subgraphPool);
1715
+ }
1716
+ if (routeType === TradeType.EXACT_OUTPUT &&
1717
+ subgraphPool.token0.id == wethAddress) {
1718
+ topByEthQuoteTokenPool.push(subgraphPool);
1719
+ }
1720
+ tokenInToken0TopByBase.pools.push(subgraphPool);
1721
+ continue;
1722
+ }
1723
+ const tokenInToken1TopByBase = topByBaseWithTokenInMap.get(subgraphPool.token1.id);
1724
+ if (topByBaseWithTokenInPoolsFound < topNWithBaseToken &&
1725
+ tokenInToken1TopByBase &&
1726
+ subgraphPool.token0.id == tokenInAddress &&
1727
+ subgraphPool.token1.id != tokenOutAddress) {
1728
+ topByBaseWithTokenInPoolsFound += 1;
1729
+ poolAddressesSoFar.add(subgraphPool.id);
1730
+ if (topByTVLUsingTokenIn.length < topNTokenInOut) {
1731
+ topByTVLUsingTokenIn.push(subgraphPool);
1732
+ }
1733
+ if (routeType === TradeType.EXACT_OUTPUT &&
1734
+ subgraphPool.token1.id == wethAddress) {
1735
+ topByEthQuoteTokenPool.push(subgraphPool);
1736
+ }
1737
+ tokenInToken1TopByBase.pools.push(subgraphPool);
1738
+ continue;
1739
+ }
1740
+ const tokenOutToken0TopByBase = topByBaseWithTokenOutMap.get(subgraphPool.token0.id);
1741
+ if (topByBaseWithTokenOutPoolsFound < topNWithBaseToken &&
1742
+ tokenOutToken0TopByBase &&
1743
+ subgraphPool.token0.id != tokenInAddress &&
1744
+ subgraphPool.token1.id == tokenOutAddress) {
1745
+ topByBaseWithTokenOutPoolsFound += 1;
1746
+ poolAddressesSoFar.add(subgraphPool.id);
1747
+ if (topByTVLUsingTokenOut.length < topNTokenInOut) {
1748
+ topByTVLUsingTokenOut.push(subgraphPool);
1749
+ }
1750
+ if (routeType === TradeType.EXACT_INPUT &&
1751
+ subgraphPool.token0.id == wethAddress) {
1752
+ topByEthQuoteTokenPool.push(subgraphPool);
1753
+ }
1754
+ tokenOutToken0TopByBase.pools.push(subgraphPool);
1755
+ continue;
1756
+ }
1757
+ const tokenOutToken1TopByBase = topByBaseWithTokenOutMap.get(subgraphPool.token1.id);
1758
+ if (topByBaseWithTokenOutPoolsFound < topNWithBaseToken &&
1759
+ tokenOutToken1TopByBase &&
1760
+ subgraphPool.token0.id == tokenOutAddress &&
1761
+ subgraphPool.token1.id != tokenInAddress) {
1762
+ topByBaseWithTokenOutPoolsFound += 1;
1763
+ poolAddressesSoFar.add(subgraphPool.id);
1764
+ if (topByTVLUsingTokenOut.length < topNTokenInOut) {
1765
+ topByTVLUsingTokenOut.push(subgraphPool);
1766
+ }
1767
+ if (routeType === TradeType.EXACT_INPUT &&
1768
+ subgraphPool.token1.id == wethAddress) {
1769
+ topByEthQuoteTokenPool.push(subgraphPool);
1770
+ }
1771
+ tokenOutToken1TopByBase.pools.push(subgraphPool);
1772
+ continue;
1773
+ }
1774
+ // Note: we do not need to check other native currencies for the V2 Protocol
1775
+ if (topByEthQuoteTokenPool.length < topNEthQuoteToken &&
1776
+ ((routeType === TradeType.EXACT_INPUT &&
1777
+ ((subgraphPool.token0.id == wethAddress &&
1778
+ subgraphPool.token1.id == tokenOutAddress) ||
1779
+ (subgraphPool.token1.id == wethAddress &&
1780
+ subgraphPool.token0.id == tokenOutAddress))) ||
1781
+ (routeType === TradeType.EXACT_OUTPUT &&
1782
+ ((subgraphPool.token0.id == wethAddress &&
1783
+ subgraphPool.token1.id == tokenInAddress) ||
1784
+ (subgraphPool.token1.id == wethAddress &&
1785
+ subgraphPool.token0.id == tokenInAddress))))) {
1786
+ poolAddressesSoFar.add(subgraphPool.id);
1787
+ topByEthQuoteTokenPool.push(subgraphPool);
1788
+ continue;
1789
+ }
1790
+ if (topByTVL.length < topN) {
1791
+ poolAddressesSoFar.add(subgraphPool.id);
1792
+ topByTVL.push(subgraphPool);
1793
+ continue;
1794
+ }
1795
+ if (topByTVLUsingTokenIn.length < topNTokenInOut &&
1796
+ (subgraphPool.token0.id == tokenInAddress ||
1797
+ subgraphPool.token1.id == tokenInAddress)) {
1798
+ poolAddressesSoFar.add(subgraphPool.id);
1799
+ topByTVLUsingTokenIn.push(subgraphPool);
1800
+ continue;
1801
+ }
1802
+ if (topByTVLUsingTokenOut.length < topNTokenInOut &&
1803
+ (subgraphPool.token0.id == tokenOutAddress ||
1804
+ subgraphPool.token1.id == tokenOutAddress)) {
1805
+ poolAddressesSoFar.add(subgraphPool.id);
1806
+ topByTVLUsingTokenOut.push(subgraphPool);
1807
+ continue;
1808
+ }
1809
+ }
1810
+ metric.putMetric('V2SubgraphLoopsInFirstIteration', loopsInFirstIteration, MetricLoggerUnit.Count);
1811
+ const topByBaseWithTokenIn = [];
1812
+ for (const topByBaseWithTokenInSelection of topByBaseWithTokenInMap.values()) {
1813
+ topByBaseWithTokenIn.push(...topByBaseWithTokenInSelection.pools);
1814
+ }
1815
+ const topByBaseWithTokenOut = [];
1816
+ for (const topByBaseWithTokenOutSelection of topByBaseWithTokenOutMap.values()) {
1817
+ topByBaseWithTokenOut.push(...topByBaseWithTokenOutSelection.pools);
1818
+ }
1819
+ // Filtering step for second hops
1820
+ const topByTVLUsingTokenInSecondHopsMap = new Map();
1821
+ const topByTVLUsingTokenOutSecondHopsMap = new Map();
1822
+ const tokenInSecondHopAddresses = topByTVLUsingTokenIn
1823
+ .filter((pool) => {
1824
+ // filtering second hops
1825
+ if (tokenInAddress === pool.token0.id) {
1826
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token1.id.toLowerCase()));
1827
+ }
1828
+ else {
1829
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token0.id.toLowerCase()));
1830
+ }
1831
+ })
1832
+ .map((pool) => tokenInAddress === pool.token0.id ? pool.token1.id : pool.token0.id);
1833
+ const tokenOutSecondHopAddresses = topByTVLUsingTokenOut
1834
+ .filter((pool) => {
1835
+ // filtering second hops
1836
+ if (tokenOutAddress === pool.token0.id) {
1837
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token1.id.toLowerCase()));
1838
+ }
1839
+ else {
1840
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token0.id.toLowerCase()));
1841
+ }
1842
+ })
1843
+ .map((pool) => tokenOutAddress === pool.token0.id ? pool.token1.id : pool.token0.id);
1844
+ for (const secondHopId of tokenInSecondHopAddresses) {
1845
+ topByTVLUsingTokenInSecondHopsMap.set(secondHopId, new SubcategorySelectionPools([], topNSecondHop));
1846
+ }
1847
+ for (const secondHopId of tokenOutSecondHopAddresses) {
1848
+ topByTVLUsingTokenOutSecondHopsMap.set(secondHopId, new SubcategorySelectionPools([], topNSecondHop));
1849
+ }
1850
+ // Used to track how many iterations we do in the second loop
1851
+ let loopsInSecondIteration = 0;
1852
+ if (tokenInSecondHopAddresses.length > 0 ||
1853
+ tokenOutSecondHopAddresses.length > 0) {
1854
+ for (const subgraphPool of subgraphPoolsSorted) {
1855
+ loopsInSecondIteration += 1;
1856
+ let allTokenInSecondHopsHaveTheirTopN = true;
1857
+ for (const secondHopPools of topByTVLUsingTokenInSecondHopsMap.values()) {
1858
+ if (!secondHopPools.hasEnoughPools()) {
1859
+ allTokenInSecondHopsHaveTheirTopN = false;
1860
+ break;
1861
+ }
1862
+ }
1863
+ let allTokenOutSecondHopsHaveTheirTopN = true;
1864
+ for (const secondHopPools of topByTVLUsingTokenOutSecondHopsMap.values()) {
1865
+ if (!secondHopPools.hasEnoughPools()) {
1866
+ allTokenOutSecondHopsHaveTheirTopN = false;
1867
+ break;
1868
+ }
1869
+ }
1870
+ if (allTokenInSecondHopsHaveTheirTopN &&
1871
+ allTokenOutSecondHopsHaveTheirTopN) {
1872
+ // We have satisfied all the heuristics, so we can stop.
1873
+ break;
1874
+ }
1875
+ if (poolAddressesSoFar.has(subgraphPool.id)) {
1876
+ continue;
1877
+ }
1878
+ // Only consider pools where neither tokens are in the blocked token list.
1879
+ if (blockedTokenListProvider) {
1880
+ const [token0InBlocklist, token1InBlocklist] = await Promise.all([
1881
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token0.id),
1882
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token1.id),
1883
+ ]);
1884
+ if (token0InBlocklist || token1InBlocklist) {
1885
+ continue;
1886
+ }
1887
+ }
1888
+ const tokenInToken0SecondHop = topByTVLUsingTokenInSecondHopsMap.get(subgraphPool.token0.id);
1889
+ if (tokenInToken0SecondHop && !tokenInToken0SecondHop.hasEnoughPools()) {
1890
+ poolAddressesSoFar.add(subgraphPool.id);
1891
+ tokenInToken0SecondHop.pools.push(subgraphPool);
1892
+ continue;
1893
+ }
1894
+ const tokenInToken1SecondHop = topByTVLUsingTokenInSecondHopsMap.get(subgraphPool.token1.id);
1895
+ if (tokenInToken1SecondHop && !tokenInToken1SecondHop.hasEnoughPools()) {
1896
+ poolAddressesSoFar.add(subgraphPool.id);
1897
+ tokenInToken1SecondHop.pools.push(subgraphPool);
1898
+ continue;
1899
+ }
1900
+ const tokenOutToken0SecondHop = topByTVLUsingTokenOutSecondHopsMap.get(subgraphPool.token0.id);
1901
+ if (tokenOutToken0SecondHop &&
1902
+ !tokenOutToken0SecondHop.hasEnoughPools()) {
1903
+ poolAddressesSoFar.add(subgraphPool.id);
1904
+ tokenOutToken0SecondHop.pools.push(subgraphPool);
1905
+ continue;
1906
+ }
1907
+ const tokenOutToken1SecondHop = topByTVLUsingTokenOutSecondHopsMap.get(subgraphPool.token1.id);
1908
+ if (tokenOutToken1SecondHop &&
1909
+ !tokenOutToken1SecondHop.hasEnoughPools()) {
1910
+ poolAddressesSoFar.add(subgraphPool.id);
1911
+ tokenOutToken1SecondHop.pools.push(subgraphPool);
1912
+ continue;
1913
+ }
1914
+ }
1915
+ }
1916
+ metric.putMetric('V2SubgraphLoopsInSecondIteration', loopsInSecondIteration, MetricLoggerUnit.Count);
1917
+ const topByTVLUsingTokenInSecondHops = [];
1918
+ for (const secondHopPools of topByTVLUsingTokenInSecondHopsMap.values()) {
1919
+ topByTVLUsingTokenInSecondHops.push(...secondHopPools.pools);
1920
+ }
1921
+ const topByTVLUsingTokenOutSecondHops = [];
1922
+ for (const secondHopPools of topByTVLUsingTokenOutSecondHopsMap.values()) {
1923
+ topByTVLUsingTokenOutSecondHops.push(...secondHopPools.pools);
1924
+ }
1925
+ const subgraphPools = _([
1926
+ ...topByBaseWithTokenIn,
1927
+ ...topByBaseWithTokenOut,
1928
+ ...topByDirectSwapPool,
1929
+ ...topByEthQuoteTokenPool,
1930
+ ...topByTVL,
1931
+ ...topByTVLUsingTokenIn,
1932
+ ...topByTVLUsingTokenOut,
1933
+ ...topByTVLUsingTokenInSecondHops,
1934
+ ...topByTVLUsingTokenOutSecondHops,
1935
+ ])
1936
+ .uniqBy((pool) => pool.id)
1937
+ .value();
1938
+ const tokenAddressesSet = new Set();
1939
+ for (const pool of subgraphPools) {
1940
+ tokenAddressesSet.add(pool.token0.id);
1941
+ tokenAddressesSet.add(pool.token1.id);
1942
+ }
1943
+ const tokenAddresses = Array.from(tokenAddressesSet);
1944
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V2 pools we are considering`);
1945
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
1946
+ blockNumber,
1947
+ });
1948
+ const printV2SubgraphPool = (s) => {
1949
+ var _a, _b, _c, _d;
1950
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}`;
1951
+ };
1952
+ log.info({
1953
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV2SubgraphPool),
1954
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV2SubgraphPool),
1955
+ topByTVL: topByTVL.map(printV2SubgraphPool),
1956
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV2SubgraphPool),
1957
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV2SubgraphPool),
1958
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV2SubgraphPool),
1959
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV2SubgraphPool),
1960
+ top2DirectSwap: topByDirectSwapPool.map(printV2SubgraphPool),
1961
+ top2EthQuotePool: topByEthQuoteTokenPool.map(printV2SubgraphPool),
1962
+ }, `V2 Candidate pools`);
1963
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
1964
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
1965
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
1966
+ if (!tokenA || !tokenB) {
1967
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}`);
1968
+ return undefined;
1969
+ }
1970
+ return [tokenA, tokenB];
1971
+ });
1972
+ const tokenPairs = _.compact(tokenPairsRaw);
1973
+ metric.putMetric('V2PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
1974
+ const beforePoolsLoad = Date.now();
1975
+ // this should be the only place to enable fee-on-transfer fee fetching,
1976
+ // because this places loads pools (pairs of tokens with fot taxes) from the subgraph
1977
+ const poolAccessor = await poolProvider.getPools(tokenPairs, routingConfig);
1978
+ metric.putMetric('V2PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
1979
+ const poolsBySelection = {
1980
+ protocol: Protocol.V2,
1981
+ selections: {
1982
+ topByBaseWithTokenIn,
1983
+ topByBaseWithTokenOut,
1984
+ topByDirectSwapPool,
1985
+ topByEthQuoteTokenPool,
1986
+ topByTVL,
1987
+ topByTVLUsingTokenIn,
1988
+ topByTVLUsingTokenOut,
1989
+ topByTVLUsingTokenInSecondHops,
1990
+ topByTVLUsingTokenOutSecondHops,
1991
+ },
1992
+ };
1993
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
1994
+ }
1995
+ export async function getUniswapFewTokenV2CandidatePools({ tokenIn, tokenOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, }) {
1996
+ const { blockNumber, v2PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
1997
+ const tokenInAddress = tokenIn.address.toLowerCase();
1998
+ const tokenOutAddress = tokenOut.address.toLowerCase();
1999
+ const beforeSubgraphPools = Date.now();
2000
+ const allPoolsRaw = await subgraphProvider.getPools(tokenIn, tokenOut, {
2001
+ blockNumber,
2002
+ });
2003
+ // With tens of thousands of V2 pools, operations that copy pools become costly.
2004
+ // Mutate the pool directly rather than creating a new pool / token to optimmize for speed.
2005
+ for (const pool of allPoolsRaw) {
2006
+ pool.token0.id = pool.token0.id.toLowerCase();
2007
+ pool.token1.id = pool.token1.id.toLowerCase();
2008
+ }
2009
+ metric.putMetric('Uniswap FewTokenV2SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
2010
+ const beforePoolsFiltered = Date.now();
2011
+ // Sort by pool reserve in descending order.
2012
+ const subgraphPoolsSorted = allPoolsRaw.sort((a, b) => b.reserve - a.reserve);
2013
+ const poolAddressesSoFar = new Set();
2014
+ // Always add the direct swap pool into the mix regardless of if it exists in the subgraph pool list.
2015
+ // Ensures that new pools can be swapped on immediately, and that if a pool was filtered out of the
2016
+ // subgraph query for some reason (e.g. trackedReserveETH was 0), then we still consider it.
2017
+ let topByDirectSwapPool = [];
2018
+ if (topNDirectSwaps > 0) {
2019
+ const { token0, token1, poolAddress } = poolProvider.getPoolAddress(tokenIn, tokenOut);
2020
+ poolAddressesSoFar.add(poolAddress.toLowerCase());
2021
+ topByDirectSwapPool = [
2022
+ {
2023
+ id: poolAddress,
2024
+ token0: {
2025
+ id: token0.address,
2026
+ },
2027
+ token1: {
2028
+ id: token1.address,
2029
+ },
2030
+ supply: 10000,
2031
+ reserve: 10000,
2032
+ reserveUSD: 10000, // Not used. Set to arbitrary number.
2033
+ },
2034
+ ];
2035
+ }
2036
+ const wethAddress = FEW_WRAPPED_NATIVE_CURRENCY[chainId].address.toLowerCase();
2037
+ const topByBaseWithTokenInMap = new Map();
2038
+ const topByBaseWithTokenOutMap = new Map();
2039
+ const baseTokens = isFewToken(tokenIn) ? fewBaseTokensByChain[chainId] : baseTokensByChain[chainId];
2040
+ const baseTokensAddresses = new Set();
2041
+ baseTokens.forEach((token) => {
2042
+ const baseTokenAddr = token.address.toLowerCase();
2043
+ baseTokensAddresses.add(baseTokenAddr);
2044
+ topByBaseWithTokenInMap.set(baseTokenAddr, new SubcategorySelectionPools([], topNWithEachBaseToken));
2045
+ topByBaseWithTokenOutMap.set(baseTokenAddr, new SubcategorySelectionPools([], topNWithEachBaseToken));
2046
+ });
2047
+ let topByBaseWithTokenInPoolsFound = 0;
2048
+ let topByBaseWithTokenOutPoolsFound = 0;
2049
+ // Main reason we need this is for gas estimates
2050
+ // There can ever only be 1 Token/ETH pool, so we will only look for 1
2051
+ let topNEthQuoteToken = 1;
2052
+ // but, we only need it if token out is not ETH.
2053
+ if (tokenOut.symbol == 'WETH' ||
2054
+ tokenOut.symbol == 'WETH9' ||
2055
+ tokenOut.symbol == 'ETH') {
2056
+ // if it's eth we change the topN to 0, so we can break early from the loop.
2057
+ topNEthQuoteToken = 0;
2058
+ }
2059
+ const topByEthQuoteTokenPool = [];
2060
+ const topByTVLUsingTokenIn = [];
2061
+ const topByTVLUsingTokenOut = [];
2062
+ const topByTVL = [];
2063
+ // Used to track how many iterations we do in the first loop
2064
+ let loopsInFirstIteration = 0;
2065
+ // Filtering step for up to first hop
2066
+ // The pools are pre-sorted, so we can just iterate through them and fill our heuristics.
2067
+ for (const subgraphPool of subgraphPoolsSorted) {
2068
+ loopsInFirstIteration += 1;
2069
+ // Check if we have satisfied all the heuristics, if so, we can stop.
2070
+ if (topByBaseWithTokenInPoolsFound >= topNWithBaseToken &&
2071
+ topByBaseWithTokenOutPoolsFound >= topNWithBaseToken &&
2072
+ topByEthQuoteTokenPool.length >= topNEthQuoteToken &&
2073
+ topByTVL.length >= topN &&
2074
+ topByTVLUsingTokenIn.length >= topNTokenInOut &&
2075
+ topByTVLUsingTokenOut.length >= topNTokenInOut) {
2076
+ // We have satisfied all the heuristics, so we can stop.
2077
+ break;
2078
+ }
2079
+ if (poolAddressesSoFar.has(subgraphPool.id)) {
2080
+ // We've already added this pool, so skip it.
2081
+ continue;
2082
+ }
2083
+ // Only consider pools where neither tokens are in the blocked token list.
2084
+ if (blockedTokenListProvider) {
2085
+ const [token0InBlocklist, token1InBlocklist] = await Promise.all([
2086
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token0.id),
2087
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token1.id),
2088
+ ]);
2089
+ if (token0InBlocklist || token1InBlocklist) {
2090
+ continue;
2091
+ }
2092
+ }
2093
+ const tokenInToken0TopByBase = topByBaseWithTokenInMap.get(subgraphPool.token0.id);
2094
+ if (topByBaseWithTokenInPoolsFound < topNWithBaseToken &&
2095
+ tokenInToken0TopByBase &&
2096
+ subgraphPool.token0.id != tokenOutAddress &&
2097
+ subgraphPool.token1.id == tokenInAddress) {
2098
+ topByBaseWithTokenInPoolsFound += 1;
2099
+ poolAddressesSoFar.add(subgraphPool.id);
2100
+ if (topByTVLUsingTokenIn.length < topNTokenInOut) {
2101
+ topByTVLUsingTokenIn.push(subgraphPool);
2102
+ }
2103
+ if (routeType === TradeType.EXACT_OUTPUT &&
2104
+ subgraphPool.token0.id == wethAddress) {
2105
+ topByEthQuoteTokenPool.push(subgraphPool);
2106
+ }
2107
+ tokenInToken0TopByBase.pools.push(subgraphPool);
2108
+ continue;
2109
+ }
2110
+ const tokenInToken1TopByBase = topByBaseWithTokenInMap.get(subgraphPool.token1.id);
2111
+ if (topByBaseWithTokenInPoolsFound < topNWithBaseToken &&
2112
+ tokenInToken1TopByBase &&
2113
+ subgraphPool.token0.id == tokenInAddress &&
2114
+ subgraphPool.token1.id != tokenOutAddress) {
2115
+ topByBaseWithTokenInPoolsFound += 1;
2116
+ poolAddressesSoFar.add(subgraphPool.id);
2117
+ if (topByTVLUsingTokenIn.length < topNTokenInOut) {
2118
+ topByTVLUsingTokenIn.push(subgraphPool);
2119
+ }
2120
+ if (routeType === TradeType.EXACT_OUTPUT &&
2121
+ subgraphPool.token1.id == wethAddress) {
2122
+ topByEthQuoteTokenPool.push(subgraphPool);
2123
+ }
2124
+ tokenInToken1TopByBase.pools.push(subgraphPool);
2125
+ continue;
2126
+ }
2127
+ const tokenOutToken0TopByBase = topByBaseWithTokenOutMap.get(subgraphPool.token0.id);
2128
+ if (topByBaseWithTokenOutPoolsFound < topNWithBaseToken &&
2129
+ tokenOutToken0TopByBase &&
2130
+ subgraphPool.token0.id != tokenInAddress &&
2131
+ subgraphPool.token1.id == tokenOutAddress) {
2132
+ topByBaseWithTokenOutPoolsFound += 1;
2133
+ poolAddressesSoFar.add(subgraphPool.id);
2134
+ if (topByTVLUsingTokenOut.length < topNTokenInOut) {
2135
+ topByTVLUsingTokenOut.push(subgraphPool);
2136
+ }
2137
+ if (routeType === TradeType.EXACT_INPUT &&
2138
+ subgraphPool.token0.id == wethAddress) {
2139
+ topByEthQuoteTokenPool.push(subgraphPool);
2140
+ }
2141
+ tokenOutToken0TopByBase.pools.push(subgraphPool);
2142
+ continue;
2143
+ }
2144
+ const tokenOutToken1TopByBase = topByBaseWithTokenOutMap.get(subgraphPool.token1.id);
2145
+ if (topByBaseWithTokenOutPoolsFound < topNWithBaseToken &&
2146
+ tokenOutToken1TopByBase &&
2147
+ subgraphPool.token0.id == tokenOutAddress &&
2148
+ subgraphPool.token1.id != tokenInAddress) {
2149
+ topByBaseWithTokenOutPoolsFound += 1;
2150
+ poolAddressesSoFar.add(subgraphPool.id);
2151
+ if (topByTVLUsingTokenOut.length < topNTokenInOut) {
2152
+ topByTVLUsingTokenOut.push(subgraphPool);
2153
+ }
2154
+ if (routeType === TradeType.EXACT_INPUT &&
2155
+ subgraphPool.token1.id == wethAddress) {
2156
+ topByEthQuoteTokenPool.push(subgraphPool);
2157
+ }
2158
+ tokenOutToken1TopByBase.pools.push(subgraphPool);
2159
+ continue;
2160
+ }
2161
+ // Note: we do not need to check other native currencies for the V2 Protocol
2162
+ if (topByEthQuoteTokenPool.length < topNEthQuoteToken &&
2163
+ ((routeType === TradeType.EXACT_INPUT &&
2164
+ ((subgraphPool.token0.id == wethAddress &&
2165
+ subgraphPool.token1.id == tokenOutAddress) ||
2166
+ (subgraphPool.token1.id == wethAddress &&
2167
+ subgraphPool.token0.id == tokenOutAddress))) ||
2168
+ (routeType === TradeType.EXACT_OUTPUT &&
2169
+ ((subgraphPool.token0.id == wethAddress &&
2170
+ subgraphPool.token1.id == tokenInAddress) ||
2171
+ (subgraphPool.token1.id == wethAddress &&
2172
+ subgraphPool.token0.id == tokenInAddress))))) {
2173
+ poolAddressesSoFar.add(subgraphPool.id);
2174
+ topByEthQuoteTokenPool.push(subgraphPool);
2175
+ continue;
2176
+ }
2177
+ if (topByTVL.length < topN) {
2178
+ poolAddressesSoFar.add(subgraphPool.id);
2179
+ topByTVL.push(subgraphPool);
2180
+ continue;
2181
+ }
2182
+ if (topByTVLUsingTokenIn.length < topNTokenInOut &&
2183
+ (subgraphPool.token0.id == tokenInAddress ||
2184
+ subgraphPool.token1.id == tokenInAddress)) {
2185
+ poolAddressesSoFar.add(subgraphPool.id);
2186
+ topByTVLUsingTokenIn.push(subgraphPool);
2187
+ continue;
2188
+ }
2189
+ if (topByTVLUsingTokenOut.length < topNTokenInOut &&
2190
+ (subgraphPool.token0.id == tokenOutAddress ||
2191
+ subgraphPool.token1.id == tokenOutAddress)) {
2192
+ poolAddressesSoFar.add(subgraphPool.id);
2193
+ topByTVLUsingTokenOut.push(subgraphPool);
2194
+ continue;
2195
+ }
2196
+ }
2197
+ metric.putMetric('V2SubgraphLoopsInFirstIteration', loopsInFirstIteration, MetricLoggerUnit.Count);
2198
+ const topByBaseWithTokenIn = [];
2199
+ for (const topByBaseWithTokenInSelection of topByBaseWithTokenInMap.values()) {
2200
+ topByBaseWithTokenIn.push(...topByBaseWithTokenInSelection.pools);
2201
+ }
2202
+ const topByBaseWithTokenOut = [];
2203
+ for (const topByBaseWithTokenOutSelection of topByBaseWithTokenOutMap.values()) {
2204
+ topByBaseWithTokenOut.push(...topByBaseWithTokenOutSelection.pools);
2205
+ }
2206
+ // Filtering step for second hops
2207
+ const topByTVLUsingTokenInSecondHopsMap = new Map();
2208
+ const topByTVLUsingTokenOutSecondHopsMap = new Map();
2209
+ const tokenInSecondHopAddresses = topByTVLUsingTokenIn
2210
+ .filter((pool) => {
2211
+ // filtering second hops
2212
+ if (tokenInAddress === pool.token0.id) {
2213
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token1.id.toLowerCase()));
2214
+ }
2215
+ else {
2216
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token0.id.toLowerCase()));
2217
+ }
2218
+ })
2219
+ .map((pool) => tokenInAddress === pool.token0.id ? pool.token1.id : pool.token0.id);
2220
+ const tokenOutSecondHopAddresses = topByTVLUsingTokenOut
2221
+ .filter((pool) => {
2222
+ // filtering second hops
2223
+ if (tokenOutAddress === pool.token0.id) {
2224
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token1.id.toLowerCase()));
2225
+ }
2226
+ else {
2227
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token0.id.toLowerCase()));
2228
+ }
2229
+ })
2230
+ .map((pool) => tokenOutAddress === pool.token0.id ? pool.token1.id : pool.token0.id);
2231
+ for (const secondHopId of tokenInSecondHopAddresses) {
2232
+ topByTVLUsingTokenInSecondHopsMap.set(secondHopId, new SubcategorySelectionPools([], topNSecondHop));
2233
+ }
2234
+ for (const secondHopId of tokenOutSecondHopAddresses) {
2235
+ topByTVLUsingTokenOutSecondHopsMap.set(secondHopId, new SubcategorySelectionPools([], topNSecondHop));
2236
+ }
2237
+ // Used to track how many iterations we do in the second loop
2238
+ let loopsInSecondIteration = 0;
2239
+ if (tokenInSecondHopAddresses.length > 0 ||
2240
+ tokenOutSecondHopAddresses.length > 0) {
2241
+ for (const subgraphPool of subgraphPoolsSorted) {
2242
+ loopsInSecondIteration += 1;
2243
+ let allTokenInSecondHopsHaveTheirTopN = true;
2244
+ for (const secondHopPools of topByTVLUsingTokenInSecondHopsMap.values()) {
2245
+ if (!secondHopPools.hasEnoughPools()) {
2246
+ allTokenInSecondHopsHaveTheirTopN = false;
2247
+ break;
2248
+ }
2249
+ }
2250
+ let allTokenOutSecondHopsHaveTheirTopN = true;
2251
+ for (const secondHopPools of topByTVLUsingTokenOutSecondHopsMap.values()) {
2252
+ if (!secondHopPools.hasEnoughPools()) {
2253
+ allTokenOutSecondHopsHaveTheirTopN = false;
2254
+ break;
2255
+ }
2256
+ }
2257
+ if (allTokenInSecondHopsHaveTheirTopN &&
2258
+ allTokenOutSecondHopsHaveTheirTopN) {
2259
+ // We have satisfied all the heuristics, so we can stop.
2260
+ break;
2261
+ }
2262
+ if (poolAddressesSoFar.has(subgraphPool.id)) {
2263
+ continue;
2264
+ }
2265
+ // Only consider pools where neither tokens are in the blocked token list.
2266
+ if (blockedTokenListProvider) {
2267
+ const [token0InBlocklist, token1InBlocklist] = await Promise.all([
2268
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token0.id),
2269
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token1.id),
2270
+ ]);
2271
+ if (token0InBlocklist || token1InBlocklist) {
2272
+ continue;
2273
+ }
2274
+ }
2275
+ const tokenInToken0SecondHop = topByTVLUsingTokenInSecondHopsMap.get(subgraphPool.token0.id);
2276
+ if (tokenInToken0SecondHop && !tokenInToken0SecondHop.hasEnoughPools()) {
2277
+ poolAddressesSoFar.add(subgraphPool.id);
2278
+ tokenInToken0SecondHop.pools.push(subgraphPool);
2279
+ continue;
2280
+ }
2281
+ const tokenInToken1SecondHop = topByTVLUsingTokenInSecondHopsMap.get(subgraphPool.token1.id);
2282
+ if (tokenInToken1SecondHop && !tokenInToken1SecondHop.hasEnoughPools()) {
2283
+ poolAddressesSoFar.add(subgraphPool.id);
2284
+ tokenInToken1SecondHop.pools.push(subgraphPool);
2285
+ continue;
2286
+ }
2287
+ const tokenOutToken0SecondHop = topByTVLUsingTokenOutSecondHopsMap.get(subgraphPool.token0.id);
2288
+ if (tokenOutToken0SecondHop &&
2289
+ !tokenOutToken0SecondHop.hasEnoughPools()) {
2290
+ poolAddressesSoFar.add(subgraphPool.id);
2291
+ tokenOutToken0SecondHop.pools.push(subgraphPool);
2292
+ continue;
2293
+ }
2294
+ const tokenOutToken1SecondHop = topByTVLUsingTokenOutSecondHopsMap.get(subgraphPool.token1.id);
2295
+ if (tokenOutToken1SecondHop &&
2296
+ !tokenOutToken1SecondHop.hasEnoughPools()) {
2297
+ poolAddressesSoFar.add(subgraphPool.id);
2298
+ tokenOutToken1SecondHop.pools.push(subgraphPool);
2299
+ continue;
2300
+ }
2301
+ }
2302
+ }
2303
+ metric.putMetric('V2SubgraphLoopsInSecondIteration', loopsInSecondIteration, MetricLoggerUnit.Count);
2304
+ const topByTVLUsingTokenInSecondHops = [];
2305
+ for (const secondHopPools of topByTVLUsingTokenInSecondHopsMap.values()) {
2306
+ topByTVLUsingTokenInSecondHops.push(...secondHopPools.pools);
2307
+ }
2308
+ const topByTVLUsingTokenOutSecondHops = [];
2309
+ for (const secondHopPools of topByTVLUsingTokenOutSecondHopsMap.values()) {
2310
+ topByTVLUsingTokenOutSecondHops.push(...secondHopPools.pools);
2311
+ }
2312
+ const subgraphPools = _([
2313
+ ...topByBaseWithTokenIn,
2314
+ ...topByBaseWithTokenOut,
2315
+ ...topByDirectSwapPool,
2316
+ ...topByEthQuoteTokenPool,
2317
+ ...topByTVL,
2318
+ ...topByTVLUsingTokenIn,
2319
+ ...topByTVLUsingTokenOut,
2320
+ ...topByTVLUsingTokenInSecondHops,
2321
+ ...topByTVLUsingTokenOutSecondHops,
2322
+ ])
2323
+ .uniqBy((pool) => pool.id)
2324
+ .value();
2325
+ const tokenAddressesSet = new Set();
2326
+ for (const pool of subgraphPools) {
2327
+ tokenAddressesSet.add(pool.token0.id);
2328
+ tokenAddressesSet.add(pool.token1.id);
2329
+ }
2330
+ const tokenAddresses = Array.from(tokenAddressesSet);
2331
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V2 pools we are considering`);
2332
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
2333
+ blockNumber,
2334
+ });
2335
+ const printV2SubgraphPool = (s) => {
2336
+ var _a, _b, _c, _d;
2337
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}`;
2338
+ };
2339
+ log.info({
2340
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV2SubgraphPool),
2341
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV2SubgraphPool),
2342
+ topByTVL: topByTVL.map(printV2SubgraphPool),
2343
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV2SubgraphPool),
2344
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV2SubgraphPool),
2345
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV2SubgraphPool),
2346
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV2SubgraphPool),
2347
+ top2DirectSwap: topByDirectSwapPool.map(printV2SubgraphPool),
2348
+ top2EthQuotePool: topByEthQuoteTokenPool.map(printV2SubgraphPool),
2349
+ }, `V2 Candidate pools`);
2350
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
2351
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
2352
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
2353
+ if (!tokenA || !tokenB) {
2354
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}`);
2355
+ return undefined;
2356
+ }
2357
+ return [tokenA, tokenB];
2358
+ });
2359
+ const tokenPairs = _.compact(tokenPairsRaw);
2360
+ metric.putMetric('V2PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
2361
+ const beforePoolsLoad = Date.now();
2362
+ // this should be the only place to enable fee-on-transfer fee fetching,
2363
+ // because this places loads pools (pairs of tokens with fot taxes) from the subgraph
2364
+ const poolAccessor = await poolProvider.getPools(tokenPairs, routingConfig);
2365
+ metric.putMetric('V2PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
2366
+ const poolsBySelection = {
2367
+ protocol: Protocol.V2,
2368
+ selections: {
2369
+ topByBaseWithTokenIn,
2370
+ topByBaseWithTokenOut,
2371
+ topByDirectSwapPool,
2372
+ topByEthQuoteTokenPool,
2373
+ topByTVL,
2374
+ topByTVLUsingTokenIn,
2375
+ topByTVLUsingTokenOut,
2376
+ topByTVLUsingTokenInSecondHops,
2377
+ topByTVLUsingTokenOutSecondHops,
2378
+ },
2379
+ };
2380
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
2381
+ }
2382
+ export async function getRingFewV2CandidatePools({ tokenIn, tokenOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, }) {
2383
+ var _a;
2384
+ const { blockNumber, v2PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
2385
+ const tokenInAddress = tokenIn.address.toLowerCase();
2386
+ const tokenOutAddress = tokenOut.address.toLowerCase();
2387
+ const beforeSubgraphPools = Date.now();
2388
+ const allPoolsRaw = await subgraphProvider.getPools(tokenIn, tokenOut, {
2389
+ blockNumber,
2390
+ });
2391
+ // With tens of thousands of V2 pools, operations that copy pools become costly.
2392
+ // Mutate the pool directly rather than creating a new pool / token to optimmize for speed.
2393
+ for (const pool of allPoolsRaw) {
2394
+ pool.token0.id = pool.token0.id.toLowerCase();
2395
+ pool.token1.id = pool.token1.id.toLowerCase();
2396
+ }
2397
+ metric.putMetric('Ringswap FewTokenV2SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
2398
+ const beforePoolsFiltered = Date.now();
2399
+ // Sort by pool reserve in descending order.
2400
+ const subgraphPoolsSorted = allPoolsRaw.sort((a, b) => b.reserve - a.reserve);
2401
+ const poolAddressesSoFar = new Set();
2402
+ // Always add the direct swap pool into the mix regardless of if it exists in the subgraph pool list.
2403
+ // Ensures that new pools can be swapped on immediately, and that if a pool was filtered out of the
2404
+ // subgraph query for some reason (e.g. trackedReserveETH was 0), then we still consider it.
2405
+ let topByDirectSwapPool = [];
2406
+ if (topNDirectSwaps > 0) {
2407
+ const { token0, token1, poolAddress } = poolProvider.getPoolAddress(tokenIn, tokenOut);
2408
+ poolAddressesSoFar.add(poolAddress.toLowerCase());
2409
+ topByDirectSwapPool = [
2410
+ {
2411
+ id: poolAddress,
2412
+ token0: {
2413
+ id: token0.address,
2414
+ },
2415
+ token1: {
2416
+ id: token1.address,
2417
+ },
2418
+ supply: 10000,
2419
+ reserve: 10000,
2420
+ reserveUSD: 10000, // Not used. Set to arbitrary number.
2421
+ },
2422
+ ];
2423
+ }
2424
+ const wethAddress = FEW_WRAPPED_NATIVE_CURRENCY[chainId].address.toLowerCase();
2425
+ const topByBaseWithTokenInMap = new Map();
2426
+ const topByBaseWithTokenOutMap = new Map();
2427
+ const baseTokens = (_a = fewBaseTokensByChain[chainId]) !== null && _a !== void 0 ? _a : [];
2428
+ const baseTokensAddresses = new Set();
2429
+ baseTokens.forEach((token) => {
2430
+ const baseTokenAddr = token.address.toLowerCase();
2431
+ baseTokensAddresses.add(baseTokenAddr);
2432
+ topByBaseWithTokenInMap.set(baseTokenAddr, new SubcategorySelectionPools([], topNWithEachBaseToken));
2433
+ topByBaseWithTokenOutMap.set(baseTokenAddr, new SubcategorySelectionPools([], topNWithEachBaseToken));
2434
+ });
2435
+ let topByBaseWithTokenInPoolsFound = 0;
2436
+ let topByBaseWithTokenOutPoolsFound = 0;
2437
+ // Main reason we need this is for gas estimates
2438
+ // There can ever only be 1 Token/ETH pool, so we will only look for 1
2439
+ let topNEthQuoteToken = 1;
2440
+ // but, we only need it if token out is not ETH.
2441
+ if (tokenOut.symbol == 'WETH' ||
2442
+ tokenOut.symbol == 'WETH9' ||
2443
+ tokenOut.symbol == 'ETH') {
2444
+ // if it's eth we change the topN to 0, so we can break early from the loop.
2445
+ topNEthQuoteToken = 0;
2446
+ }
2447
+ const topByEthQuoteTokenPool = [];
2448
+ const topByTVLUsingTokenIn = [];
2449
+ const topByTVLUsingTokenOut = [];
2450
+ const topByTVL = [];
2451
+ // Used to track how many iterations we do in the first loop
2452
+ let loopsInFirstIteration = 0;
2453
+ // Filtering step for up to first hop
2454
+ // The pools are pre-sorted, so we can just iterate through them and fill our heuristics.
2455
+ for (const subgraphPool of subgraphPoolsSorted) {
2456
+ loopsInFirstIteration += 1;
2457
+ // Check if we have satisfied all the heuristics, if so, we can stop.
2458
+ if (topByBaseWithTokenInPoolsFound >= topNWithBaseToken &&
2459
+ topByBaseWithTokenOutPoolsFound >= topNWithBaseToken &&
2460
+ topByEthQuoteTokenPool.length >= topNEthQuoteToken &&
2461
+ topByTVL.length >= topN &&
2462
+ topByTVLUsingTokenIn.length >= topNTokenInOut &&
2463
+ topByTVLUsingTokenOut.length >= topNTokenInOut) {
2464
+ // We have satisfied all the heuristics, so we can stop.
2465
+ break;
2466
+ }
2467
+ if (poolAddressesSoFar.has(subgraphPool.id)) {
2468
+ // We've already added this pool, so skip it.
2469
+ continue;
2470
+ }
2471
+ // Only consider pools where neither tokens are in the blocked token list.
2472
+ if (blockedTokenListProvider) {
2473
+ const [token0InBlocklist, token1InBlocklist] = await Promise.all([
2474
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token0.id),
2475
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token1.id),
2476
+ ]);
2477
+ if (token0InBlocklist || token1InBlocklist) {
2478
+ continue;
2479
+ }
2480
+ }
2481
+ const tokenInToken0TopByBase = topByBaseWithTokenInMap.get(subgraphPool.token0.id);
2482
+ if (topByBaseWithTokenInPoolsFound < topNWithBaseToken &&
2483
+ tokenInToken0TopByBase &&
2484
+ subgraphPool.token0.id != tokenOutAddress &&
2485
+ subgraphPool.token1.id == tokenInAddress) {
2486
+ topByBaseWithTokenInPoolsFound += 1;
2487
+ poolAddressesSoFar.add(subgraphPool.id);
2488
+ if (topByTVLUsingTokenIn.length < topNTokenInOut) {
2489
+ topByTVLUsingTokenIn.push(subgraphPool);
2490
+ }
2491
+ if (routeType === TradeType.EXACT_OUTPUT &&
2492
+ subgraphPool.token0.id == wethAddress) {
2493
+ topByEthQuoteTokenPool.push(subgraphPool);
2494
+ }
2495
+ tokenInToken0TopByBase.pools.push(subgraphPool);
2496
+ continue;
2497
+ }
2498
+ const tokenInToken1TopByBase = topByBaseWithTokenInMap.get(subgraphPool.token1.id);
2499
+ if (topByBaseWithTokenInPoolsFound < topNWithBaseToken &&
2500
+ tokenInToken1TopByBase &&
2501
+ subgraphPool.token0.id == tokenInAddress &&
2502
+ subgraphPool.token1.id != tokenOutAddress) {
2503
+ topByBaseWithTokenInPoolsFound += 1;
2504
+ poolAddressesSoFar.add(subgraphPool.id);
2505
+ if (topByTVLUsingTokenIn.length < topNTokenInOut) {
2506
+ topByTVLUsingTokenIn.push(subgraphPool);
2507
+ }
2508
+ if (routeType === TradeType.EXACT_OUTPUT &&
2509
+ subgraphPool.token1.id == wethAddress) {
2510
+ topByEthQuoteTokenPool.push(subgraphPool);
2511
+ }
2512
+ tokenInToken1TopByBase.pools.push(subgraphPool);
2513
+ continue;
2514
+ }
2515
+ const tokenOutToken0TopByBase = topByBaseWithTokenOutMap.get(subgraphPool.token0.id);
2516
+ if (topByBaseWithTokenOutPoolsFound < topNWithBaseToken &&
2517
+ tokenOutToken0TopByBase &&
2518
+ subgraphPool.token0.id != tokenInAddress &&
2519
+ subgraphPool.token1.id == tokenOutAddress) {
2520
+ topByBaseWithTokenOutPoolsFound += 1;
2521
+ poolAddressesSoFar.add(subgraphPool.id);
2522
+ if (topByTVLUsingTokenOut.length < topNTokenInOut) {
2523
+ topByTVLUsingTokenOut.push(subgraphPool);
2524
+ }
2525
+ if (routeType === TradeType.EXACT_INPUT &&
2526
+ subgraphPool.token0.id == wethAddress) {
2527
+ topByEthQuoteTokenPool.push(subgraphPool);
2528
+ }
2529
+ tokenOutToken0TopByBase.pools.push(subgraphPool);
2530
+ continue;
2531
+ }
2532
+ const tokenOutToken1TopByBase = topByBaseWithTokenOutMap.get(subgraphPool.token1.id);
2533
+ if (topByBaseWithTokenOutPoolsFound < topNWithBaseToken &&
2534
+ tokenOutToken1TopByBase &&
2535
+ subgraphPool.token0.id == tokenOutAddress &&
2536
+ subgraphPool.token1.id != tokenInAddress) {
2537
+ topByBaseWithTokenOutPoolsFound += 1;
2538
+ poolAddressesSoFar.add(subgraphPool.id);
2539
+ if (topByTVLUsingTokenOut.length < topNTokenInOut) {
2540
+ topByTVLUsingTokenOut.push(subgraphPool);
2541
+ }
2542
+ if (routeType === TradeType.EXACT_INPUT &&
2543
+ subgraphPool.token1.id == wethAddress) {
2544
+ topByEthQuoteTokenPool.push(subgraphPool);
2545
+ }
2546
+ tokenOutToken1TopByBase.pools.push(subgraphPool);
2547
+ continue;
2548
+ }
2549
+ // Note: we do not need to check other native currencies for the V2 Protocol
2550
+ if (topByEthQuoteTokenPool.length < topNEthQuoteToken &&
2551
+ ((routeType === TradeType.EXACT_INPUT &&
2552
+ ((subgraphPool.token0.id == wethAddress &&
2553
+ subgraphPool.token1.id == tokenOutAddress) ||
2554
+ (subgraphPool.token1.id == wethAddress &&
2555
+ subgraphPool.token0.id == tokenOutAddress))) ||
2556
+ (routeType === TradeType.EXACT_OUTPUT &&
2557
+ ((subgraphPool.token0.id == wethAddress &&
2558
+ subgraphPool.token1.id == tokenInAddress) ||
2559
+ (subgraphPool.token1.id == wethAddress &&
2560
+ subgraphPool.token0.id == tokenInAddress))))) {
2561
+ poolAddressesSoFar.add(subgraphPool.id);
2562
+ topByEthQuoteTokenPool.push(subgraphPool);
2563
+ continue;
2564
+ }
2565
+ if (topByTVL.length < topN) {
2566
+ poolAddressesSoFar.add(subgraphPool.id);
2567
+ topByTVL.push(subgraphPool);
2568
+ continue;
2569
+ }
2570
+ if (topByTVLUsingTokenIn.length < topNTokenInOut &&
2571
+ (subgraphPool.token0.id == tokenInAddress ||
2572
+ subgraphPool.token1.id == tokenInAddress)) {
2573
+ poolAddressesSoFar.add(subgraphPool.id);
2574
+ topByTVLUsingTokenIn.push(subgraphPool);
2575
+ continue;
2576
+ }
2577
+ if (topByTVLUsingTokenOut.length < topNTokenInOut &&
2578
+ (subgraphPool.token0.id == tokenOutAddress ||
2579
+ subgraphPool.token1.id == tokenOutAddress)) {
2580
+ poolAddressesSoFar.add(subgraphPool.id);
2581
+ topByTVLUsingTokenOut.push(subgraphPool);
2582
+ continue;
2583
+ }
2584
+ }
2585
+ metric.putMetric('V2SubgraphLoopsInFirstIteration', loopsInFirstIteration, MetricLoggerUnit.Count);
2586
+ const topByBaseWithTokenIn = [];
2587
+ for (const topByBaseWithTokenInSelection of topByBaseWithTokenInMap.values()) {
2588
+ topByBaseWithTokenIn.push(...topByBaseWithTokenInSelection.pools);
2589
+ }
2590
+ const topByBaseWithTokenOut = [];
2591
+ for (const topByBaseWithTokenOutSelection of topByBaseWithTokenOutMap.values()) {
2592
+ topByBaseWithTokenOut.push(...topByBaseWithTokenOutSelection.pools);
2593
+ }
2594
+ // Filtering step for second hops
2595
+ const topByTVLUsingTokenInSecondHopsMap = new Map();
2596
+ const topByTVLUsingTokenOutSecondHopsMap = new Map();
2597
+ const tokenInSecondHopAddresses = topByTVLUsingTokenIn
2598
+ .filter((pool) => {
2599
+ // filtering second hops
2600
+ if (tokenInAddress === pool.token0.id) {
2601
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token1.id.toLowerCase()));
2602
+ }
2603
+ else {
2604
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token0.id.toLowerCase()));
2605
+ }
2606
+ })
2607
+ .map((pool) => tokenInAddress === pool.token0.id ? pool.token1.id : pool.token0.id);
2608
+ const tokenOutSecondHopAddresses = topByTVLUsingTokenOut
2609
+ .filter((pool) => {
2610
+ // filtering second hops
2611
+ if (tokenOutAddress === pool.token0.id) {
2612
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token1.id.toLowerCase()));
2613
+ }
2614
+ else {
2615
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token0.id.toLowerCase()));
2616
+ }
2617
+ })
2618
+ .map((pool) => tokenOutAddress === pool.token0.id ? pool.token1.id : pool.token0.id);
2619
+ for (const secondHopId of tokenInSecondHopAddresses) {
2620
+ topByTVLUsingTokenInSecondHopsMap.set(secondHopId, new SubcategorySelectionPools([], topNSecondHop));
2621
+ }
2622
+ for (const secondHopId of tokenOutSecondHopAddresses) {
2623
+ topByTVLUsingTokenOutSecondHopsMap.set(secondHopId, new SubcategorySelectionPools([], topNSecondHop));
2624
+ }
2625
+ // Used to track how many iterations we do in the second loop
2626
+ let loopsInSecondIteration = 0;
2627
+ if (tokenInSecondHopAddresses.length > 0 ||
2628
+ tokenOutSecondHopAddresses.length > 0) {
2629
+ for (const subgraphPool of subgraphPoolsSorted) {
2630
+ loopsInSecondIteration += 1;
2631
+ let allTokenInSecondHopsHaveTheirTopN = true;
2632
+ for (const secondHopPools of topByTVLUsingTokenInSecondHopsMap.values()) {
2633
+ if (!secondHopPools.hasEnoughPools()) {
2634
+ allTokenInSecondHopsHaveTheirTopN = false;
2635
+ break;
2636
+ }
2637
+ }
2638
+ let allTokenOutSecondHopsHaveTheirTopN = true;
2639
+ for (const secondHopPools of topByTVLUsingTokenOutSecondHopsMap.values()) {
2640
+ if (!secondHopPools.hasEnoughPools()) {
2641
+ allTokenOutSecondHopsHaveTheirTopN = false;
2642
+ break;
2643
+ }
2644
+ }
2645
+ if (allTokenInSecondHopsHaveTheirTopN &&
2646
+ allTokenOutSecondHopsHaveTheirTopN) {
2647
+ // We have satisfied all the heuristics, so we can stop.
2648
+ break;
2649
+ }
2650
+ if (poolAddressesSoFar.has(subgraphPool.id)) {
2651
+ continue;
2652
+ }
2653
+ // Only consider pools where neither tokens are in the blocked token list.
2654
+ if (blockedTokenListProvider) {
2655
+ const [token0InBlocklist, token1InBlocklist] = await Promise.all([
2656
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token0.id),
2657
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token1.id),
2658
+ ]);
2659
+ if (token0InBlocklist || token1InBlocklist) {
2660
+ continue;
2661
+ }
2662
+ }
2663
+ const tokenInToken0SecondHop = topByTVLUsingTokenInSecondHopsMap.get(subgraphPool.token0.id);
2664
+ if (tokenInToken0SecondHop && !tokenInToken0SecondHop.hasEnoughPools()) {
2665
+ poolAddressesSoFar.add(subgraphPool.id);
2666
+ tokenInToken0SecondHop.pools.push(subgraphPool);
2667
+ continue;
2668
+ }
2669
+ const tokenInToken1SecondHop = topByTVLUsingTokenInSecondHopsMap.get(subgraphPool.token1.id);
2670
+ if (tokenInToken1SecondHop && !tokenInToken1SecondHop.hasEnoughPools()) {
2671
+ poolAddressesSoFar.add(subgraphPool.id);
2672
+ tokenInToken1SecondHop.pools.push(subgraphPool);
2673
+ continue;
2674
+ }
2675
+ const tokenOutToken0SecondHop = topByTVLUsingTokenOutSecondHopsMap.get(subgraphPool.token0.id);
2676
+ if (tokenOutToken0SecondHop &&
2677
+ !tokenOutToken0SecondHop.hasEnoughPools()) {
2678
+ poolAddressesSoFar.add(subgraphPool.id);
2679
+ tokenOutToken0SecondHop.pools.push(subgraphPool);
2680
+ continue;
2681
+ }
2682
+ const tokenOutToken1SecondHop = topByTVLUsingTokenOutSecondHopsMap.get(subgraphPool.token1.id);
2683
+ if (tokenOutToken1SecondHop &&
2684
+ !tokenOutToken1SecondHop.hasEnoughPools()) {
2685
+ poolAddressesSoFar.add(subgraphPool.id);
2686
+ tokenOutToken1SecondHop.pools.push(subgraphPool);
2687
+ continue;
2688
+ }
2689
+ }
2690
+ }
2691
+ metric.putMetric('V2SubgraphLoopsInSecondIteration', loopsInSecondIteration, MetricLoggerUnit.Count);
2692
+ const topByTVLUsingTokenInSecondHops = [];
2693
+ for (const secondHopPools of topByTVLUsingTokenInSecondHopsMap.values()) {
2694
+ topByTVLUsingTokenInSecondHops.push(...secondHopPools.pools);
2695
+ }
2696
+ const topByTVLUsingTokenOutSecondHops = [];
2697
+ for (const secondHopPools of topByTVLUsingTokenOutSecondHopsMap.values()) {
2698
+ topByTVLUsingTokenOutSecondHops.push(...secondHopPools.pools);
2699
+ }
2700
+ const subgraphPools = _([
2701
+ ...topByBaseWithTokenIn,
2702
+ ...topByBaseWithTokenOut,
2703
+ ...topByDirectSwapPool,
2704
+ ...topByEthQuoteTokenPool,
2705
+ ...topByTVL,
2706
+ ...topByTVLUsingTokenIn,
2707
+ ...topByTVLUsingTokenOut,
2708
+ ...topByTVLUsingTokenInSecondHops,
2709
+ ...topByTVLUsingTokenOutSecondHops,
2710
+ ])
2711
+ .uniqBy((pool) => pool.id)
2712
+ .value();
2713
+ const tokenAddressesSet = new Set();
2714
+ for (const pool of subgraphPools) {
2715
+ tokenAddressesSet.add(pool.token0.id);
2716
+ tokenAddressesSet.add(pool.token1.id);
2717
+ }
2718
+ const tokenAddresses = Array.from(tokenAddressesSet);
2719
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V2 pools we are considering`);
2720
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
2721
+ blockNumber,
2722
+ });
2723
+ const printV2SubgraphPool = (s) => {
2724
+ var _a, _b, _c, _d;
2725
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}`;
2726
+ };
2727
+ log.info({
2728
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV2SubgraphPool),
2729
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV2SubgraphPool),
2730
+ topByTVL: topByTVL.map(printV2SubgraphPool),
2731
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV2SubgraphPool),
2732
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV2SubgraphPool),
2733
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV2SubgraphPool),
2734
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV2SubgraphPool),
2735
+ top2DirectSwap: topByDirectSwapPool.map(printV2SubgraphPool),
2736
+ top2EthQuotePool: topByEthQuoteTokenPool.map(printV2SubgraphPool),
2737
+ }, `V2 Candidate pools`);
2738
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
2739
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
2740
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
2741
+ if (!tokenA || !tokenB) {
2742
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}`);
2743
+ return undefined;
2744
+ }
2745
+ return [tokenA, tokenB];
2746
+ });
2747
+ const tokenPairs = _.compact(tokenPairsRaw);
2748
+ metric.putMetric('V2PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
2749
+ const beforePoolsLoad = Date.now();
2750
+ // this should be the only place to enable fee-on-transfer fee fetching,
2751
+ // because this places loads pools (pairs of tokens with fot taxes) from the subgraph
2752
+ const poolAccessor = await poolProvider.getPools(tokenPairs, routingConfig);
2753
+ metric.putMetric('V2PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
2754
+ const poolsBySelection = {
2755
+ protocol: Protocol.V2,
2756
+ selections: {
2757
+ topByBaseWithTokenIn,
2758
+ topByBaseWithTokenOut,
2759
+ topByDirectSwapPool,
2760
+ topByEthQuoteTokenPool,
2761
+ topByTVL,
2762
+ topByTVLUsingTokenIn,
2763
+ topByTVLUsingTokenOut,
2764
+ topByTVLUsingTokenInSecondHops,
2765
+ topByTVLUsingTokenOutSecondHops,
2766
+ },
2767
+ };
2768
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
2769
+ }
2770
+ export async function getMixedRouteCandidatePools({ v4CandidatePools, v3CandidatePools, v2CandidatePools, crossLiquidityPools, routingConfig, tokenProvider, v4PoolProvider, v3poolProvider, v2poolProvider, chainId, }) {
2771
+ const beforeSubgraphPools = Date.now();
2772
+ const [v4Results, v3Results, v2Results] = [
2773
+ v4CandidatePools,
2774
+ v3CandidatePools,
2775
+ v2CandidatePools,
2776
+ ];
2777
+ // Create empty defaults for undefined results
2778
+ const { subgraphPools: V4subgraphPools = [], candidatePools: V4candidatePools = {
2779
+ protocol: Protocol.V4,
2780
+ selections: {
2781
+ topByBaseWithTokenIn: [],
2782
+ topByBaseWithTokenOut: [],
2783
+ topByDirectSwapPool: [],
2784
+ topByEthQuoteTokenPool: [],
2785
+ topByTVL: [],
2786
+ topByTVLUsingTokenIn: [],
2787
+ topByTVLUsingTokenOut: [],
2788
+ topByTVLUsingTokenInSecondHops: [],
2789
+ topByTVLUsingTokenOutSecondHops: [],
2790
+ },
2791
+ }, } = v4Results || {};
2792
+ const { subgraphPools: V3subgraphPools = [], candidatePools: V3candidatePools = {
2793
+ protocol: Protocol.V3,
2794
+ selections: {
2795
+ topByBaseWithTokenIn: [],
2796
+ topByBaseWithTokenOut: [],
2797
+ topByDirectSwapPool: [],
2798
+ topByEthQuoteTokenPool: [],
2799
+ topByTVL: [],
2800
+ topByTVLUsingTokenIn: [],
2801
+ topByTVLUsingTokenOut: [],
2802
+ topByTVLUsingTokenInSecondHops: [],
2803
+ topByTVLUsingTokenOutSecondHops: [],
2804
+ },
2805
+ }, } = v3Results || {};
2806
+ const { subgraphPools: V2subgraphPools = [], candidatePools: V2candidatePools = {
2807
+ protocol: Protocol.V2,
2808
+ selections: {
2809
+ topByBaseWithTokenIn: [],
2810
+ topByBaseWithTokenOut: [],
2811
+ topByDirectSwapPool: [],
2812
+ topByEthQuoteTokenPool: [],
2813
+ topByTVL: [],
2814
+ topByTVLUsingTokenIn: [],
2815
+ topByTVLUsingTokenOut: [],
2816
+ topByTVLUsingTokenInSecondHops: [],
2817
+ topByTVLUsingTokenOutSecondHops: [],
2818
+ },
2819
+ }, } = v2Results || {};
2820
+ // Injects the liquidity pools found by the getMixedCrossLiquidityCandidatePools function
2821
+ V2subgraphPools.push(...crossLiquidityPools.v2Pools);
2822
+ V3subgraphPools.push(...crossLiquidityPools.v3Pools);
2823
+ metric.putMetric('MixedSubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
2824
+ const beforePoolsFiltered = Date.now();
2825
+ /**
2826
+ * Main heuristic for pruning mixedRoutes:
2827
+ * - we pick V2 pools with higher liq than respective V3 pools, or if the v3 pool doesn't exist
2828
+ *
2829
+ * This way we can reduce calls to our provider since it's possible to generate a lot of mixed routes
2830
+ */
2831
+ /// We only really care about pools involving the tokenIn or tokenOut explictly,
2832
+ /// since there's no way a long tail token in V2 would be routed through as an intermediary
2833
+ const V2topByTVLPoolIds = new Set([
2834
+ ...V2candidatePools.selections.topByTVLUsingTokenIn,
2835
+ ...V2candidatePools.selections.topByBaseWithTokenIn,
2836
+ /// tokenOut:
2837
+ ...V2candidatePools.selections.topByTVLUsingTokenOut,
2838
+ ...V2candidatePools.selections.topByBaseWithTokenOut,
2839
+ /// Direct swap:
2840
+ ...V2candidatePools.selections.topByDirectSwapPool,
2841
+ // Cross Liquidity (has to be added to be considered):
2842
+ ...crossLiquidityPools.v2Pools,
2843
+ ].map((poolId) => poolId.id));
2844
+ const V2topByTVLSortedPools = _(V2subgraphPools)
2845
+ .filter((pool) => V2topByTVLPoolIds.has(pool.id))
2846
+ .sortBy((pool) => -pool.reserveUSD)
2847
+ .value();
2848
+ /// we consider all returned V3 pools for this heuristic to "fill in the gaps"
2849
+ const V3sortedPools = _(V3subgraphPools)
2850
+ .sortBy((pool) => -pool.tvlUSD)
2851
+ .value();
2852
+ const V4sortedPools = _(V4subgraphPools)
2853
+ .sortBy((pool) => -pool.tvlUSD)
2854
+ .value();
2855
+ /// Finding pools with greater reserveUSD on v2 than tvlUSD on v3, or if there is no v3 liquidity
2856
+ const buildV2Pools = [];
2857
+ V2topByTVLSortedPools.forEach((V2subgraphPool) => {
2858
+ const V3subgraphPool = V3sortedPools.find((pool) => (pool.token0.id == V2subgraphPool.token0.id &&
2859
+ pool.token1.id == V2subgraphPool.token1.id) ||
2860
+ (pool.token0.id == V2subgraphPool.token1.id &&
2861
+ pool.token1.id == V2subgraphPool.token0.id));
2862
+ if (V3subgraphPool) {
2863
+ if (V2subgraphPool.reserveUSD > V3subgraphPool.tvlUSD) {
2864
+ log.info({
2865
+ token0: V2subgraphPool.token0.id,
2866
+ token1: V2subgraphPool.token1.id,
2867
+ v2reserveUSD: V2subgraphPool.reserveUSD,
2868
+ v3tvlUSD: V3subgraphPool.tvlUSD,
2869
+ }, `MixedRoute heuristic, found a V2 pool with higher liquidity than its V3 counterpart`);
2870
+ buildV2Pools.push(V2subgraphPool);
2871
+ }
2872
+ }
2873
+ else {
2874
+ log.info({
2875
+ token0: V2subgraphPool.token0.id,
2876
+ token1: V2subgraphPool.token1.id,
2877
+ v2reserveUSD: V2subgraphPool.reserveUSD,
2878
+ }, `MixedRoute heuristic, found a V2 pool with no V3 counterpart`);
2879
+ buildV2Pools.push(V2subgraphPool);
2880
+ }
2881
+ const V4subgraphPool = V4sortedPools.find((pool) => (pool.token0.id == V2subgraphPool.token0.id &&
2882
+ pool.token1.id == V2subgraphPool.token1.id) ||
2883
+ (pool.token0.id == V2subgraphPool.token1.id &&
2884
+ pool.token1.id == V2subgraphPool.token0.id));
2885
+ if (V4subgraphPool) {
2886
+ if (V2subgraphPool.reserveUSD > V4subgraphPool.tvlUSD) {
2887
+ log.info({
2888
+ token0: V2subgraphPool.token0.id,
2889
+ token1: V2subgraphPool.token1.id,
2890
+ v2reserveUSD: V2subgraphPool.reserveUSD,
2891
+ v4tvlUSD: V4subgraphPool.tvlUSD,
2892
+ }, `MixedRoute heuristic, found a V2 pool with higher liquidity than its V4 counterpart`);
2893
+ buildV2Pools.push(V2subgraphPool);
2894
+ }
2895
+ }
2896
+ else {
2897
+ log.info({
2898
+ token0: V2subgraphPool.token0.id,
2899
+ token1: V2subgraphPool.token1.id,
2900
+ v2reserveUSD: V2subgraphPool.reserveUSD,
2901
+ }, `MixedRoute heuristic, found a V2 pool with no V3 counterpart`);
2902
+ buildV2Pools.push(V2subgraphPool);
2903
+ }
2904
+ });
2905
+ log.info(buildV2Pools.length, `Number of V2 candidate pools that fit first heuristic`);
2906
+ const subgraphPools = [...buildV2Pools, ...V3sortedPools, ...V4sortedPools];
2907
+ const tokenAddresses = _(subgraphPools)
2908
+ .flatMap((subgraphPool) => [subgraphPool.token0.id, subgraphPool.token1.id])
2909
+ .compact()
2910
+ .uniq()
2911
+ .value();
2912
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} pools we are considering`);
2913
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, routingConfig);
2914
+ const V4tokenPairsRaw = _.map(V4sortedPools, (subgraphPool) => {
2915
+ // native currency is not erc20 token, therefore there's no way to retrieve native currency metadata as the erc20 token.
2916
+ const tokenA = isNativeCurrency(subgraphPool.token0.id)
2917
+ ? nativeOnChain(chainId)
2918
+ : tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
2919
+ const tokenB = isNativeCurrency(subgraphPool.token1.id)
2920
+ ? nativeOnChain(chainId)
2921
+ : tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
2922
+ let fee;
2923
+ try {
2924
+ fee = Number(subgraphPool.feeTier);
2925
+ }
2926
+ catch (err) {
2927
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier}/${subgraphPool.tickSpacing}/${subgraphPool.hooks} because fee tier not supported`);
2928
+ return undefined;
2929
+ }
2930
+ if (!tokenA || !tokenB) {
2931
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee}/${subgraphPool.tickSpacing}/${subgraphPool.hooks} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
2932
+ return undefined;
2933
+ }
2934
+ return [
2935
+ tokenA,
2936
+ tokenB,
2937
+ fee,
2938
+ Number(subgraphPool.tickSpacing),
2939
+ subgraphPool.hooks,
2940
+ ];
2941
+ });
2942
+ const V4tokenPairs = _.compact(V4tokenPairsRaw);
2943
+ const V3tokenPairsRaw = _.map(V3sortedPools, (subgraphPool) => {
2944
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
2945
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
2946
+ let fee;
2947
+ try {
2948
+ fee = parseFeeAmount(subgraphPool.feeTier);
2949
+ }
2950
+ catch (err) {
2951
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier} because fee tier not supported`);
2952
+ return undefined;
2953
+ }
2954
+ if (!tokenA || !tokenB) {
2955
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
2956
+ return undefined;
2957
+ }
2958
+ return [tokenA, tokenB, fee];
2959
+ });
2960
+ const V3tokenPairs = _.compact(V3tokenPairsRaw);
2961
+ const V2tokenPairsRaw = _.map(buildV2Pools, (subgraphPool) => {
2962
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
2963
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
2964
+ if (!tokenA || !tokenB) {
2965
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}`);
2966
+ return undefined;
2967
+ }
2968
+ return [tokenA, tokenB];
2969
+ });
2970
+ const V2tokenPairs = _.compact(V2tokenPairsRaw);
2971
+ metric.putMetric('MixedPoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
2972
+ const beforePoolsLoad = Date.now();
2973
+ const [V2poolAccessor, V3poolAccessor, V4poolAccessor] = await Promise.all([
2974
+ v2poolProvider.getPools(V2tokenPairs, routingConfig),
2975
+ v3poolProvider.getPools(V3tokenPairs, routingConfig),
2976
+ v4PoolProvider.getPools(V4tokenPairs, routingConfig),
2977
+ ]);
2978
+ metric.putMetric('MixedPoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
2979
+ /// @dev a bit tricky here since the original V2CandidateSelections object included pools that we may have dropped
2980
+ /// as part of the heuristic. We need to reconstruct a new object with the v3 pools too.
2981
+ const buildPoolsBySelection = (key) => {
2982
+ return [
2983
+ ...buildV2Pools.filter((pool) => V2candidatePools.selections[key].map((p) => p.id).includes(pool.id)),
2984
+ ...V3candidatePools.selections[key],
2985
+ ...V4candidatePools.selections[key],
2986
+ ];
2987
+ };
2988
+ const poolsBySelection = {
2989
+ protocol: Protocol.MIXED,
2990
+ selections: {
2991
+ topByBaseWithTokenIn: buildPoolsBySelection('topByBaseWithTokenIn'),
2992
+ topByBaseWithTokenOut: buildPoolsBySelection('topByBaseWithTokenOut'),
2993
+ topByDirectSwapPool: buildPoolsBySelection('topByDirectSwapPool'),
2994
+ topByEthQuoteTokenPool: buildPoolsBySelection('topByEthQuoteTokenPool'),
2995
+ topByTVL: buildPoolsBySelection('topByTVL'),
2996
+ topByTVLUsingTokenIn: buildPoolsBySelection('topByTVLUsingTokenIn'),
2997
+ topByTVLUsingTokenOut: buildPoolsBySelection('topByTVLUsingTokenOut'),
2998
+ topByTVLUsingTokenInSecondHops: buildPoolsBySelection('topByTVLUsingTokenInSecondHops'),
2999
+ topByTVLUsingTokenOutSecondHops: buildPoolsBySelection('topByTVLUsingTokenOutSecondHops'),
3000
+ },
3001
+ };
3002
+ return {
3003
+ V2poolAccessor,
3004
+ V3poolAccessor,
3005
+ V4poolAccessor,
3006
+ candidatePools: poolsBySelection,
3007
+ subgraphPools,
3008
+ };
3009
+ }
3010
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LWNhbmRpZGF0ZS1wb29scy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9yb3V0ZXJzL2FscGhhLXJvdXRlci9mdW5jdGlvbnMvZ2V0LWNhbmRpZGF0ZS1wb29scy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ25FLE9BQU8sRUFBRSxPQUFPLEVBQW1CLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRTlFLE9BQU8sQ0FBQyxNQUFNLFFBQVEsQ0FBQztBQUV2QixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUN2RSxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLGdCQUFnQixFQUtoQixxQkFBcUIsRUFDckIscUJBQXFCLEVBQ3JCLHFCQUFxQixFQUNyQixxQkFBcUIsR0FNdEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQ0wsSUFBSSxFQUNKLGNBQWMsRUFDZCxTQUFTLEVBQ1QsbUJBQW1CLEVBQ25CLFNBQVMsRUFDVCxtQkFBbUIsRUFDbkIsWUFBWSxFQUNaLFFBQVEsRUFDUixPQUFPLEVBQ1AsV0FBVyxFQUNYLFlBQVksRUFDWixZQUFZLEVBQ1osbUJBQW1CLEVBQ25CLGtCQUFrQixFQUNsQixXQUFXLEVBQ1gsWUFBWSxFQUNaLFdBQVcsRUFDWCxtQkFBbUIsRUFDbkIsZUFBZSxFQUNmLGVBQWUsRUFDZixlQUFlLEVBQ2YsY0FBYyxFQUNkLGdCQUFnQixFQUNoQixnQkFBZ0IsRUFDaEIsc0JBQXNCLEVBQ3RCLGdCQUFnQixFQUNoQixnQkFBZ0IsRUFFaEIsVUFBVSxFQUNWLGFBQWEsRUFDYixvQkFBb0IsRUFDcEIsU0FBUyxFQUNULFNBQVMsRUFDVCxpQkFBaUIsRUFDakIsUUFBUSxFQUNSLG9CQUFvQixFQUNwQixZQUFZLEVBQ1osYUFBYSxFQUNiLGFBQWEsRUFDYixv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