@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,2280 @@
1
+ import { BigNumber } from '@ethersproject/bignumber';
2
+ import { JsonRpcProvider } from '@ethersproject/providers';
3
+ import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list';
4
+ import { Protocol, SwapRouter, ZERO } from '@ring-protocol/router-sdk';
5
+ import { ChainId, Fraction, Token, TradeType, } from '@ring-protocol/sdk-core';
6
+ import { Pool, Position, SqrtPriceMath, TickMath } from '@ring-protocol/v3-sdk';
7
+ import retry from 'async-retry';
8
+ import JSBI from 'jsbi';
9
+ import _ from 'lodash';
10
+ import NodeCache from 'node-cache';
11
+ import { CachedRoutes, CacheMode, CachingGasStationProvider, CachingTokenProviderWithFallback, CachingV2PoolProvider,
12
+ // CachingV2SubgraphProvider,
13
+ CachingV3PoolProvider,
14
+ // CachingV3SubgraphProvider,
15
+ // CachingV4SubgraphProvider,
16
+ EIP1559GasPriceProvider, ETHGasStationInfoProvider, LegacyGasPriceProvider, NodeJSCache, OnChainGasPriceProvider, OnChainQuoteProvider, RingFewCachingV2PoolProvider,
17
+ // RingFewCachingV2SubgraphProvider,
18
+ RingFewStaticV2SubgraphProvider, RingFewV2SubgraphProviderWithFallBacks, RingswapMulticallProvider, RingV2PoolProvider, RingV2QuoteProvider, SimulationStatus, StaticV2SubgraphProvider, StaticV3SubgraphProvider, StaticV4SubgraphProvider, SwapRouterProvider, TokenPropertiesProvider, UniswapMulticallProvider,
19
+ // URISubgraphProvider,
20
+ V2QuoteProvider, V2SubgraphProviderWithFallBacks, V3SubgraphProviderWithFallBacks, V4SubgraphProviderWithFallBacks, } from '../../providers';
21
+ import { CachingTokenListProvider, } from '../../providers/caching-token-list-provider';
22
+ import { PortionProvider, } from '../../providers/portion-provider';
23
+ import { OnChainTokenFeeFetcher } from '../../providers/token-fee-fetcher';
24
+ import { TokenProvider } from '../../providers/token-provider';
25
+ import { TokenValidatorProvider, } from '../../providers/token-validator-provider';
26
+ import { V2PoolProvider, } from '../../providers/v2/pool-provider';
27
+ import { ArbitrumGasDataProvider, } from '../../providers/v3/gas-data-provider';
28
+ import { V3PoolProvider, } from '../../providers/v3/pool-provider';
29
+ import { CachingV4PoolProvider } from '../../providers/v4/caching-pool-provider';
30
+ import { V4PoolProvider, } from '../../providers/v4/pool-provider';
31
+ import { Erc20__factory } from '../../types/other/factories/Erc20__factory';
32
+ import { getAddress, getAddressLowerCase, getApplicableV4FeesTickspacingsHooks, HooksOptions, MIXED_SUPPORTED, shouldWipeoutCachedRoutes, SWAP_ROUTER_02_ADDRESSES, V4_SUPPORTED, WRAPPED_NATIVE_CURRENCY, } from '../../util';
33
+ import { CurrencyAmount } from '../../util/amounts';
34
+ import { FEW_WRAPPED_NATIVE_CURRENCY, ID_TO_CHAIN_ID,
35
+ // ID_TO_NETWORK_NAME,
36
+ RING_FEW_V2_SUPPORTED, V2_SUPPORTED, } from '../../util/chains';
37
+ import { getHighestLiquidityV3FewTokenUSDPool, getHighestLiquidityV3NativeFewTokenPool, getHighestLiquidityV3NativePool, getHighestLiquidityV3USDPool, } from '../../util/gas-factory-helpers';
38
+ import { log } from '../../util/log';
39
+ import { buildSwapMethodParameters, buildTrade, } from '../../util/methodParameters';
40
+ import { metric, MetricLoggerUnit } from '../../util/metric';
41
+ import { BATCH_PARAMS, BLOCK_NUMBER_CONFIGS, DEFAULT_BATCH_PARAMS, DEFAULT_BLOCK_NUMBER_CONFIGS, DEFAULT_GAS_ERROR_FAILURE_OVERRIDES, DEFAULT_RETRY_OPTIONS, DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES, GAS_ERROR_FAILURE_OVERRIDES, RETRY_OPTIONS, SUCCESS_RATE_FAILURE_OVERRIDES, } from '../../util/onchainQuoteProviderConfigs';
42
+ import { UNSUPPORTED_TOKENS } from '../../util/unsupported-tokens';
43
+ import { SwapToRatioStatus, SwapType, } from '../router';
44
+ import { UniversalRouterVersion } from '@ring-protocol/universal-router-sdk';
45
+ import { DEFAULT_BLOCKS_TO_LIVE } from '../../util/defaultBlocksToLive';
46
+ import { INTENT } from '../../util/intent';
47
+ import { serializeRouteIds } from '../../util/serializeRouteIds';
48
+ import { DEFAULT_ROUTING_CONFIG_BY_CHAIN, ETH_GAS_STATION_API_URL, } from './config';
49
+ import { getBestSwapRoute } from './functions/best-swap-route';
50
+ import { calculateRatioAmountIn } from './functions/calculate-ratio-amount-in';
51
+ import { getMixedCrossLiquidityCandidatePools, getRingFewV2CandidatePools, getUniswapFewTokenV2CandidatePools, getUniswapFewTokenV3CandidatePools, getUniswapV4FewTokenCandidatePools, getV2CandidatePools, getV3CandidatePools, getV4CandidatePools, } from './functions/get-candidate-pools';
52
+ import { NATIVE_OVERHEAD } from './gas-models/gas-costs';
53
+ import { MixedRouteHeuristicGasModelFactory } from './gas-models/mixedRoute/mixed-route-heuristic-gas-model';
54
+ import { V2HeuristicGasModelFactory } from './gas-models/v2/v2-heuristic-gas-model';
55
+ import { V3HeuristicGasModelFactory } from './gas-models/v3/v3-heuristic-gas-model';
56
+ import { UniswapFewV3HeuristicGasModelFactory } from './gas-models/uniswapFewV3/v3-heuristic-gas-model';
57
+ import { V4HeuristicGasModelFactory } from './gas-models/v4/v4-heuristic-gas-model';
58
+ import { UniswapFewV4HeuristicGasModelFactory } from './gas-models/uniswapFewV4/v4-heuristic-gas-model';
59
+ import { MixedQuoter, V2Quoter, V3Quoter } from './quoters';
60
+ import { V4Quoter } from './quoters/v4-quoter';
61
+ import { UniswapFewV4Quoter } from './quoters/uniswap-few-v4-quoter';
62
+ import { UniswapFewV3Quoter } from './quoters/uniswap-few-v3-quoter';
63
+ import { RingFewV2Quoter } from './quoters/few-v2-quoter';
64
+ import { RingFewV2HeuristicGasModelFactory } from './gas-models/fewV2/v2-heuristic-gas-model';
65
+ import { getFewTokenFromOriginalToken } from '@ring-protocol/few-v2-sdk';
66
+ import { isFewToken } from '../../util/fewAddress';
67
+ import { startTimer, endTimer, getPerfReport, clearPerfData } from '../../util/simple-perf-tracker';
68
+ export class MapWithLowerCaseKey extends Map {
69
+ set(key, value) {
70
+ return super.set(key.toLowerCase(), value);
71
+ }
72
+ }
73
+ export class LowerCaseStringArray extends Array {
74
+ constructor(...items) {
75
+ // Convert all items to lowercase before calling the parent constructor
76
+ super(...items.map((item) => item.toLowerCase()));
77
+ }
78
+ }
79
+ export class AlphaRouter {
80
+ constructor({ chainId, provider, multicall2Provider, ringFewV2Multicall2Provider, v4SubgraphProvider, v4PoolProvider, v3PoolProvider, onChainQuoteProvider, v2PoolProvider, ringFewV2PoolProvider, v2QuoteProvider, ringFewV2QuoteProvider, v2SubgraphProvider, ringFewV2SubgraphProvider, tokenProvider, blockedTokenListProvider, v3SubgraphProvider, gasPriceProvider, v4GasModelFactory, uniswapFewV4GasModelFactory, v3GasModelFactory, uniswapFewV3GasModelFactory, v2GasModelFactory, ringFewV2GasModelFactory, mixedRouteGasModelFactory, swapRouterProvider, tokenValidatorProvider, arbitrumGasDataProvider, simulator, routeCachingProvider, tokenPropertiesProvider, portionProvider, v2Supported, ringFewV2Supported, v4Supported, mixedSupported, v4PoolParams, cachedRoutesCacheInvalidationFixRolloutPercentage, }) {
81
+ clearPerfData();
82
+ this.chainId = chainId;
83
+ this.provider = provider;
84
+ this.multicall2Provider =
85
+ multicall2Provider !== null && multicall2Provider !== void 0 ? multicall2Provider : new UniswapMulticallProvider(chainId, provider, 375000);
86
+ this.ringFewV2Multicall2Provider =
87
+ ringFewV2Multicall2Provider !== null && ringFewV2Multicall2Provider !== void 0 ? ringFewV2Multicall2Provider : new RingswapMulticallProvider(chainId, provider, 375000);
88
+ this.v4PoolProvider =
89
+ v4PoolProvider !== null && v4PoolProvider !== void 0 ? v4PoolProvider : new CachingV4PoolProvider(this.chainId, new V4PoolProvider(ID_TO_CHAIN_ID(chainId), this.multicall2Provider), new NodeJSCache(new NodeCache({ stdTTL: 360, useClones: false })));
90
+ this.v3PoolProvider =
91
+ v3PoolProvider !== null && v3PoolProvider !== void 0 ? v3PoolProvider : new CachingV3PoolProvider(this.chainId, new V3PoolProvider(ID_TO_CHAIN_ID(chainId), this.multicall2Provider), new NodeJSCache(new NodeCache({ stdTTL: 360, useClones: false })));
92
+ this.simulator = simulator;
93
+ this.routeCachingProvider = routeCachingProvider;
94
+ if (onChainQuoteProvider) {
95
+ this.onChainQuoteProvider = onChainQuoteProvider;
96
+ }
97
+ else {
98
+ switch (chainId) {
99
+ case ChainId.OPTIMISM:
100
+ case ChainId.OPTIMISM_GOERLI:
101
+ case ChainId.OPTIMISM_SEPOLIA:
102
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, this.ringFewV2Multicall2Provider, {
103
+ retries: 2,
104
+ minTimeout: 100,
105
+ maxTimeout: 1000,
106
+ }, (_) => {
107
+ return {
108
+ multicallChunk: 110,
109
+ gasLimitPerCall: 1200000,
110
+ quoteMinSuccessRate: 0.1,
111
+ };
112
+ }, (_) => {
113
+ return {
114
+ gasLimitOverride: 3000000,
115
+ multicallChunk: 45,
116
+ };
117
+ }, (_) => {
118
+ return {
119
+ gasLimitOverride: 3000000,
120
+ multicallChunk: 45,
121
+ };
122
+ }, (_) => {
123
+ return {
124
+ baseBlockOffset: -10,
125
+ rollback: {
126
+ enabled: true,
127
+ attemptsBeforeRollback: 1,
128
+ rollbackBlockOffset: -10,
129
+ },
130
+ };
131
+ });
132
+ break;
133
+ case ChainId.BASE:
134
+ case ChainId.BLAST:
135
+ case ChainId.ZORA:
136
+ case ChainId.WORLDCHAIN:
137
+ case ChainId.UNICHAIN_SEPOLIA:
138
+ case ChainId.MONAD_TESTNET:
139
+ case ChainId.BASE_SEPOLIA:
140
+ case ChainId.UNICHAIN:
141
+ case ChainId.BASE_GOERLI:
142
+ case ChainId.SONEIUM:
143
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, this.ringFewV2Multicall2Provider, {
144
+ retries: 2,
145
+ minTimeout: 100,
146
+ maxTimeout: 1000,
147
+ }, (_) => {
148
+ return {
149
+ multicallChunk: 80,
150
+ gasLimitPerCall: 1200000,
151
+ quoteMinSuccessRate: 0.1,
152
+ };
153
+ }, (_) => {
154
+ return {
155
+ gasLimitOverride: 3000000,
156
+ multicallChunk: 45,
157
+ };
158
+ }, (_) => {
159
+ return {
160
+ gasLimitOverride: 3000000,
161
+ multicallChunk: 45,
162
+ };
163
+ }, (_) => {
164
+ return {
165
+ baseBlockOffset: -10,
166
+ rollback: {
167
+ enabled: true,
168
+ attemptsBeforeRollback: 1,
169
+ rollbackBlockOffset: -10,
170
+ },
171
+ };
172
+ });
173
+ break;
174
+ case ChainId.ZKSYNC:
175
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, this.ringFewV2Multicall2Provider, {
176
+ retries: 2,
177
+ minTimeout: 100,
178
+ maxTimeout: 1000,
179
+ }, (_) => {
180
+ return {
181
+ multicallChunk: 27,
182
+ gasLimitPerCall: 3000000,
183
+ quoteMinSuccessRate: 0.1,
184
+ };
185
+ }, (_) => {
186
+ return {
187
+ gasLimitOverride: 6000000,
188
+ multicallChunk: 13,
189
+ };
190
+ }, (_) => {
191
+ return {
192
+ gasLimitOverride: 6000000,
193
+ multicallChunk: 13,
194
+ };
195
+ }, (_) => {
196
+ return {
197
+ baseBlockOffset: -10,
198
+ rollback: {
199
+ enabled: true,
200
+ attemptsBeforeRollback: 1,
201
+ rollbackBlockOffset: -10,
202
+ },
203
+ };
204
+ });
205
+ break;
206
+ case ChainId.ARBITRUM_ONE:
207
+ case ChainId.ARBITRUM_GOERLI:
208
+ case ChainId.ARBITRUM_SEPOLIA:
209
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, this.ringFewV2Multicall2Provider, {
210
+ retries: 2,
211
+ minTimeout: 100,
212
+ maxTimeout: 1000,
213
+ }, (_) => {
214
+ return {
215
+ multicallChunk: 10,
216
+ gasLimitPerCall: 12000000,
217
+ quoteMinSuccessRate: 0.1,
218
+ };
219
+ }, (_) => {
220
+ return {
221
+ gasLimitOverride: 30000000,
222
+ multicallChunk: 6,
223
+ };
224
+ }, (_) => {
225
+ return {
226
+ gasLimitOverride: 30000000,
227
+ multicallChunk: 6,
228
+ };
229
+ });
230
+ break;
231
+ case ChainId.CELO:
232
+ case ChainId.CELO_ALFAJORES:
233
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, this.ringFewV2Multicall2Provider, {
234
+ retries: 2,
235
+ minTimeout: 100,
236
+ maxTimeout: 1000,
237
+ }, (_) => {
238
+ return {
239
+ multicallChunk: 10,
240
+ gasLimitPerCall: 5000000,
241
+ quoteMinSuccessRate: 0.1,
242
+ };
243
+ }, (_) => {
244
+ return {
245
+ gasLimitOverride: 5000000,
246
+ multicallChunk: 5,
247
+ };
248
+ }, (_) => {
249
+ return {
250
+ gasLimitOverride: 6250000,
251
+ multicallChunk: 4,
252
+ };
253
+ });
254
+ break;
255
+ case ChainId.POLYGON_MUMBAI:
256
+ case ChainId.SEPOLIA:
257
+ case ChainId.MAINNET:
258
+ case ChainId.POLYGON:
259
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, this.ringFewV2Multicall2Provider, RETRY_OPTIONS[chainId], (_) => BATCH_PARAMS[chainId], (_) => GAS_ERROR_FAILURE_OVERRIDES[chainId], (_) => SUCCESS_RATE_FAILURE_OVERRIDES[chainId], (_) => BLOCK_NUMBER_CONFIGS[chainId]);
260
+ break;
261
+ default:
262
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, this.ringFewV2Multicall2Provider, DEFAULT_RETRY_OPTIONS, (_) => DEFAULT_BATCH_PARAMS, (_) => DEFAULT_GAS_ERROR_FAILURE_OVERRIDES, (_) => DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES, (_) => DEFAULT_BLOCK_NUMBER_CONFIGS);
263
+ break;
264
+ }
265
+ }
266
+ if (tokenValidatorProvider) {
267
+ this.tokenValidatorProvider = tokenValidatorProvider;
268
+ }
269
+ else if (this.chainId === ChainId.MAINNET) {
270
+ this.tokenValidatorProvider = new TokenValidatorProvider(this.chainId, this.multicall2Provider, new NodeJSCache(new NodeCache({ stdTTL: 30000, useClones: false })));
271
+ }
272
+ if (tokenPropertiesProvider) {
273
+ this.tokenPropertiesProvider = tokenPropertiesProvider;
274
+ }
275
+ else {
276
+ this.tokenPropertiesProvider = new TokenPropertiesProvider(this.chainId, new NodeJSCache(new NodeCache({ stdTTL: 86400, useClones: false })), new OnChainTokenFeeFetcher(this.chainId, provider));
277
+ }
278
+ this.v2PoolProvider =
279
+ v2PoolProvider !== null && v2PoolProvider !== void 0 ? v2PoolProvider : new CachingV2PoolProvider(chainId, new V2PoolProvider(chainId, this.multicall2Provider, this.tokenPropertiesProvider), new NodeJSCache(new NodeCache({ stdTTL: 60, useClones: false })));
280
+ this.ringFewV2PoolProvider =
281
+ ringFewV2PoolProvider !== null && ringFewV2PoolProvider !== void 0 ? ringFewV2PoolProvider : new RingFewCachingV2PoolProvider(chainId, new RingV2PoolProvider(chainId, this.multicall2Provider, this.tokenPropertiesProvider), new NodeJSCache(new NodeCache({ stdTTL: 60, useClones: false })));
282
+ this.v2QuoteProvider = v2QuoteProvider !== null && v2QuoteProvider !== void 0 ? v2QuoteProvider : new V2QuoteProvider();
283
+ this.ringFewV2QuoteProvider = ringFewV2QuoteProvider !== null && ringFewV2QuoteProvider !== void 0 ? ringFewV2QuoteProvider : new RingV2QuoteProvider();
284
+ this.blockedTokenListProvider =
285
+ blockedTokenListProvider !== null && blockedTokenListProvider !== void 0 ? blockedTokenListProvider : new CachingTokenListProvider(chainId, UNSUPPORTED_TOKENS, new NodeJSCache(new NodeCache({ stdTTL: 3600, useClones: false })));
286
+ this.tokenProvider =
287
+ tokenProvider !== null && tokenProvider !== void 0 ? tokenProvider : new CachingTokenProviderWithFallback(chainId, new NodeJSCache(new NodeCache({ stdTTL: 3600, useClones: false })), new CachingTokenListProvider(chainId, DEFAULT_TOKEN_LIST, new NodeJSCache(new NodeCache({ stdTTL: 3600, useClones: false }))), new TokenProvider(chainId, this.multicall2Provider));
288
+ this.portionProvider = portionProvider !== null && portionProvider !== void 0 ? portionProvider : new PortionProvider();
289
+ // const chainName = ID_TO_NETWORK_NAME(chainId);
290
+ // ipfs urls in the following format: `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/${protocol}/${chainName}.json`;
291
+ if (v2SubgraphProvider) {
292
+ this.v2SubgraphProvider = v2SubgraphProvider;
293
+ }
294
+ else {
295
+ this.v2SubgraphProvider = new V2SubgraphProviderWithFallBacks([
296
+ // new CachingV2SubgraphProvider(
297
+ // chainId,
298
+ // new URISubgraphProvider(
299
+ // chainId,
300
+ // `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v2/${chainName}.json`,
301
+ // undefined,
302
+ // 0
303
+ // ),
304
+ // new NodeJSCache(new NodeCache({ stdTTL: 300, useClones: false }))
305
+ // ),
306
+ new StaticV2SubgraphProvider(chainId),
307
+ ]);
308
+ }
309
+ if (ringFewV2SubgraphProvider) {
310
+ this.ringFewV2SubgraphProvider = ringFewV2SubgraphProvider;
311
+ }
312
+ else {
313
+ this.ringFewV2SubgraphProvider = new RingFewV2SubgraphProviderWithFallBacks([
314
+ // new RingFewCachingV2SubgraphProvider(
315
+ // chainId,
316
+ // new URISubgraphProvider(
317
+ // chainId,
318
+ // `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v2/${chainName}.json`,
319
+ // undefined,
320
+ // 0
321
+ // ),
322
+ // new NodeJSCache(new NodeCache({ stdTTL: 300, useClones: false }))
323
+ // ),
324
+ new RingFewStaticV2SubgraphProvider(chainId),
325
+ ]);
326
+ }
327
+ if (v3SubgraphProvider) {
328
+ this.v3SubgraphProvider = v3SubgraphProvider;
329
+ }
330
+ else {
331
+ this.v3SubgraphProvider = new V3SubgraphProviderWithFallBacks([
332
+ // new CachingV3SubgraphProvider(
333
+ // chainId,
334
+ // new URISubgraphProvider(
335
+ // chainId,
336
+ // `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v3/${chainName}.json`,
337
+ // undefined,
338
+ // 0
339
+ // ),
340
+ // new NodeJSCache(new NodeCache({ stdTTL: 300, useClones: false }))
341
+ // ),
342
+ new StaticV3SubgraphProvider(chainId, this.v3PoolProvider),
343
+ ]);
344
+ }
345
+ this.v4PoolParams =
346
+ v4PoolParams !== null && v4PoolParams !== void 0 ? v4PoolParams : getApplicableV4FeesTickspacingsHooks(chainId);
347
+ if (v4SubgraphProvider) {
348
+ this.v4SubgraphProvider = v4SubgraphProvider;
349
+ }
350
+ else {
351
+ this.v4SubgraphProvider = new V4SubgraphProviderWithFallBacks([
352
+ // new CachingV4SubgraphProvider(
353
+ // chainId,
354
+ // new URISubgraphProvider(
355
+ // chainId,
356
+ // `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v4/${chainName}.json`,
357
+ // undefined,
358
+ // 0
359
+ // ),
360
+ // new NodeJSCache(new NodeCache({ stdTTL: 300, useClones: false }))
361
+ // ),
362
+ new StaticV4SubgraphProvider(chainId, this.v4PoolProvider, this.v4PoolParams),
363
+ ]);
364
+ }
365
+ let gasPriceProviderInstance;
366
+ if (JsonRpcProvider.isProvider(this.provider)) {
367
+ gasPriceProviderInstance = new OnChainGasPriceProvider(chainId, new EIP1559GasPriceProvider(this.provider), new LegacyGasPriceProvider(this.provider));
368
+ }
369
+ else {
370
+ gasPriceProviderInstance = new ETHGasStationInfoProvider(ETH_GAS_STATION_API_URL);
371
+ }
372
+ this.gasPriceProvider =
373
+ gasPriceProvider !== null && gasPriceProvider !== void 0 ? gasPriceProvider : new CachingGasStationProvider(chainId, gasPriceProviderInstance, new NodeJSCache(new NodeCache({ stdTTL: 7, useClones: false })));
374
+ this.v4GasModelFactory =
375
+ v4GasModelFactory !== null && v4GasModelFactory !== void 0 ? v4GasModelFactory : new V4HeuristicGasModelFactory(this.provider);
376
+ this.uniswapFewV4GasModelFactory =
377
+ uniswapFewV4GasModelFactory !== null && uniswapFewV4GasModelFactory !== void 0 ? uniswapFewV4GasModelFactory : new UniswapFewV4HeuristicGasModelFactory(this.provider);
378
+ this.v3GasModelFactory =
379
+ v3GasModelFactory !== null && v3GasModelFactory !== void 0 ? v3GasModelFactory : new V3HeuristicGasModelFactory(this.provider);
380
+ this.uniswapFewV3GasModelFactory =
381
+ uniswapFewV3GasModelFactory !== null && uniswapFewV3GasModelFactory !== void 0 ? uniswapFewV3GasModelFactory : new UniswapFewV3HeuristicGasModelFactory(this.provider);
382
+ this.v2GasModelFactory =
383
+ v2GasModelFactory !== null && v2GasModelFactory !== void 0 ? v2GasModelFactory : new V2HeuristicGasModelFactory(this.provider);
384
+ this.ringFewV2GasModelFactory =
385
+ ringFewV2GasModelFactory !== null && ringFewV2GasModelFactory !== void 0 ? ringFewV2GasModelFactory : new RingFewV2HeuristicGasModelFactory(this.provider);
386
+ this.mixedRouteGasModelFactory =
387
+ mixedRouteGasModelFactory !== null && mixedRouteGasModelFactory !== void 0 ? mixedRouteGasModelFactory : new MixedRouteHeuristicGasModelFactory();
388
+ this.swapRouterProvider =
389
+ swapRouterProvider !== null && swapRouterProvider !== void 0 ? swapRouterProvider : new SwapRouterProvider(this.multicall2Provider, this.chainId);
390
+ if (chainId === ChainId.ARBITRUM_ONE ||
391
+ chainId === ChainId.ARBITRUM_GOERLI) {
392
+ this.l2GasDataProvider =
393
+ arbitrumGasDataProvider !== null && arbitrumGasDataProvider !== void 0 ? arbitrumGasDataProvider : new ArbitrumGasDataProvider(chainId, this.provider);
394
+ }
395
+ // Initialize the Quoters.
396
+ // Quoters are an abstraction encapsulating the business logic of fetching routes and quotes.
397
+ this.v2Quoter = new V2Quoter(this.v2SubgraphProvider, this.v2PoolProvider, this.v2QuoteProvider, this.v2GasModelFactory, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider, this.l2GasDataProvider);
398
+ this.ringFewV2Quoter = new RingFewV2Quoter(this.ringFewV2SubgraphProvider, this.ringFewV2PoolProvider, this.ringFewV2QuoteProvider, this.ringFewV2GasModelFactory, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider, this.l2GasDataProvider);
399
+ this.v3Quoter = new V3Quoter(this.v3SubgraphProvider, this.v3PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
400
+ this.uniswapFewV3Quoter = new UniswapFewV3Quoter(this.v3SubgraphProvider, this.v3PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
401
+ this.v4Quoter = new V4Quoter(this.v4SubgraphProvider, this.v4PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
402
+ this.uniswapFewV4Quoter = new UniswapFewV4Quoter(this.v4SubgraphProvider, this.v4PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
403
+ this.mixedQuoter = new MixedQuoter(this.v4SubgraphProvider, this.v4PoolProvider, this.v3SubgraphProvider, this.v3PoolProvider, this.v2SubgraphProvider, this.v2PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
404
+ this.v2Supported = v2Supported !== null && v2Supported !== void 0 ? v2Supported : V2_SUPPORTED;
405
+ this.ringFewV2Supported = ringFewV2Supported !== null && ringFewV2Supported !== void 0 ? ringFewV2Supported : RING_FEW_V2_SUPPORTED;
406
+ this.v4Supported = v4Supported !== null && v4Supported !== void 0 ? v4Supported : V4_SUPPORTED;
407
+ this.mixedSupported = mixedSupported !== null && mixedSupported !== void 0 ? mixedSupported : MIXED_SUPPORTED;
408
+ this.cachedRoutesCacheInvalidationFixRolloutPercentage =
409
+ cachedRoutesCacheInvalidationFixRolloutPercentage;
410
+ }
411
+ async routeToRatio(token0Balance, token1Balance, position, swapAndAddConfig, swapAndAddOptions, routingConfig = DEFAULT_ROUTING_CONFIG_BY_CHAIN(this.chainId)) {
412
+ if (token1Balance.currency.wrapped.sortsBefore(token0Balance.currency.wrapped)) {
413
+ [token0Balance, token1Balance] = [token1Balance, token0Balance];
414
+ }
415
+ let preSwapOptimalRatio = this.calculateOptimalRatio(position, position.pool.sqrtRatioX96, true);
416
+ // set up parameters according to which token will be swapped
417
+ let zeroForOne;
418
+ if (position.pool.tickCurrent > position.tickUpper) {
419
+ zeroForOne = true;
420
+ }
421
+ else if (position.pool.tickCurrent < position.tickLower) {
422
+ zeroForOne = false;
423
+ }
424
+ else {
425
+ zeroForOne = new Fraction(token0Balance.quotient, token1Balance.quotient).greaterThan(preSwapOptimalRatio);
426
+ if (!zeroForOne)
427
+ preSwapOptimalRatio = preSwapOptimalRatio.invert();
428
+ }
429
+ const [inputBalance, outputBalance] = zeroForOne
430
+ ? [token0Balance, token1Balance]
431
+ : [token1Balance, token0Balance];
432
+ let optimalRatio = preSwapOptimalRatio;
433
+ let postSwapTargetPool = position.pool;
434
+ let exchangeRate = zeroForOne
435
+ ? position.pool.token0Price
436
+ : position.pool.token1Price;
437
+ let swap = null;
438
+ let ratioAchieved = false;
439
+ let n = 0;
440
+ // iterate until we find a swap with a sufficient ratio or return null
441
+ while (!ratioAchieved) {
442
+ n++;
443
+ if (n > swapAndAddConfig.maxIterations) {
444
+ log.info('max iterations exceeded');
445
+ return {
446
+ status: SwapToRatioStatus.NO_ROUTE_FOUND,
447
+ error: 'max iterations exceeded',
448
+ };
449
+ }
450
+ const amountToSwap = calculateRatioAmountIn(optimalRatio, exchangeRate, inputBalance, outputBalance);
451
+ if (amountToSwap.equalTo(0)) {
452
+ log.info(`no swap needed: amountToSwap = 0`);
453
+ return {
454
+ status: SwapToRatioStatus.NO_SWAP_NEEDED,
455
+ };
456
+ }
457
+ swap = await this.route(amountToSwap, outputBalance.currency, TradeType.EXACT_INPUT, undefined, {
458
+ ...DEFAULT_ROUTING_CONFIG_BY_CHAIN(this.chainId),
459
+ ...routingConfig,
460
+ /// @dev We do not want to query for mixedRoutes for routeToRatio as they are not supported
461
+ /// [Protocol.V3, Protocol.V2] will make sure we only query for V3 and V2
462
+ protocols: [Protocol.V3, Protocol.V2],
463
+ });
464
+ if (!swap) {
465
+ log.info('no route found from this.route()');
466
+ return {
467
+ status: SwapToRatioStatus.NO_ROUTE_FOUND,
468
+ error: 'no route found',
469
+ };
470
+ }
471
+ const inputBalanceUpdated = inputBalance.subtract(swap.trade.inputAmount);
472
+ const outputBalanceUpdated = outputBalance.add(swap.trade.outputAmount);
473
+ const newRatio = inputBalanceUpdated.divide(outputBalanceUpdated);
474
+ let targetPoolPriceUpdate;
475
+ swap.route.forEach((route) => {
476
+ if (route.protocol === Protocol.V3) {
477
+ const v3Route = route;
478
+ v3Route.route.pools.forEach((pool, i) => {
479
+ if (pool.token0.equals(position.pool.token0) &&
480
+ pool.token1.equals(position.pool.token1) &&
481
+ pool.fee === position.pool.fee) {
482
+ targetPoolPriceUpdate = JSBI.BigInt(v3Route.sqrtPriceX96AfterList[i].toString());
483
+ optimalRatio = this.calculateOptimalRatio(position, JSBI.BigInt(targetPoolPriceUpdate.toString()), zeroForOne);
484
+ }
485
+ });
486
+ }
487
+ });
488
+ if (!targetPoolPriceUpdate) {
489
+ optimalRatio = preSwapOptimalRatio;
490
+ }
491
+ ratioAchieved =
492
+ newRatio.equalTo(optimalRatio) ||
493
+ this.absoluteValue(newRatio.asFraction.divide(optimalRatio).subtract(1)).lessThan(swapAndAddConfig.ratioErrorTolerance);
494
+ if (ratioAchieved && targetPoolPriceUpdate) {
495
+ postSwapTargetPool = new Pool(position.pool.token0, position.pool.token1, position.pool.fee, targetPoolPriceUpdate, position.pool.liquidity, TickMath.getTickAtSqrtRatio(targetPoolPriceUpdate), position.pool.tickDataProvider);
496
+ }
497
+ exchangeRate = swap.trade.outputAmount.divide(swap.trade.inputAmount);
498
+ log.info({
499
+ exchangeRate: exchangeRate.asFraction.toFixed(18),
500
+ optimalRatio: optimalRatio.asFraction.toFixed(18),
501
+ newRatio: newRatio.asFraction.toFixed(18),
502
+ inputBalanceUpdated: inputBalanceUpdated.asFraction.toFixed(18),
503
+ outputBalanceUpdated: outputBalanceUpdated.asFraction.toFixed(18),
504
+ ratioErrorTolerance: swapAndAddConfig.ratioErrorTolerance.toFixed(18),
505
+ iterationN: n.toString(),
506
+ }, 'QuoteToRatio Iteration Parameters');
507
+ if (exchangeRate.equalTo(0)) {
508
+ log.info('exchangeRate to 0');
509
+ return {
510
+ status: SwapToRatioStatus.NO_ROUTE_FOUND,
511
+ error: 'insufficient liquidity to swap to optimal ratio',
512
+ };
513
+ }
514
+ }
515
+ if (!swap) {
516
+ return {
517
+ status: SwapToRatioStatus.NO_ROUTE_FOUND,
518
+ error: 'no route found',
519
+ };
520
+ }
521
+ let methodParameters;
522
+ if (swapAndAddOptions) {
523
+ methodParameters = await this.buildSwapAndAddMethodParameters(swap.trade, swapAndAddOptions, {
524
+ initialBalanceTokenIn: inputBalance,
525
+ initialBalanceTokenOut: outputBalance,
526
+ preLiquidityPosition: position,
527
+ });
528
+ }
529
+ return {
530
+ status: SwapToRatioStatus.SUCCESS,
531
+ result: { ...swap, methodParameters, optimalRatio, postSwapTargetPool },
532
+ };
533
+ }
534
+ /**
535
+ * @inheritdoc IRouter
536
+ */
537
+ async route(amount, quoteCurrency, tradeType, swapConfig, partialRoutingConfig = {}) {
538
+ var _a, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
539
+ const originalAmount = amount;
540
+ const fewAmountToken = getFewTokenFromOriginalToken(originalAmount.currency.wrapped, this.chainId);
541
+ let fewAmount = CurrencyAmount.fromRawAmount(fewAmountToken, originalAmount.quotient); // 在 Blast 网络需要注意 origin token 和 fewtoken 的 decimals 差异
542
+ // const originalFewAmount = fewAmount;
543
+ const { currencyIn, currencyOut } = this.determineCurrencyInOutFromTradeType(tradeType, amount, quoteCurrency);
544
+ const fewTokenIn = currencyIn instanceof Token
545
+ ? getFewTokenFromOriginalToken(currencyIn, this.chainId)
546
+ : currencyIn.isNative
547
+ ? getFewTokenFromOriginalToken(currencyIn.wrapped, this.chainId)
548
+ : null;
549
+ const fewTokenOut = currencyOut instanceof Token
550
+ ? getFewTokenFromOriginalToken(currencyOut, this.chainId)
551
+ : currencyOut.isNative
552
+ ? getFewTokenFromOriginalToken(currencyOut.wrapped, this.chainId)
553
+ : null;
554
+ const fewQuoteToken = quoteCurrency instanceof Token
555
+ ? getFewTokenFromOriginalToken(quoteCurrency, this.chainId)
556
+ : quoteCurrency.isNative
557
+ ? getFewTokenFromOriginalToken(quoteCurrency.wrapped, this.chainId)
558
+ : null;
559
+ const tokenOutProperties = await this.tokenPropertiesProvider.getTokensProperties([currencyOut], partialRoutingConfig);
560
+ const feeTakenOnTransfer = (_c = (_a = tokenOutProperties[getAddressLowerCase(currencyOut)]) === null || _a === void 0 ? void 0 : _a.tokenFeeResult) === null || _c === void 0 ? void 0 : _c.feeTakenOnTransfer;
561
+ const externalTransferFailed = (_e = (_d = tokenOutProperties[getAddressLowerCase(currencyOut)]) === null || _d === void 0 ? void 0 : _d.tokenFeeResult) === null || _e === void 0 ? void 0 : _e.externalTransferFailed;
562
+ // We want to log the fee on transfer output tokens that we are taking fee or not
563
+ // Ideally the trade size (normalized in USD) would be ideal to log here, but we don't have spot price of output tokens here.
564
+ // We have to make sure token out is FOT with either buy/sell fee bps > 0
565
+ if (((_h = (_g = (_f = tokenOutProperties[getAddressLowerCase(currencyOut)]) === null || _f === void 0 ? void 0 : _f.tokenFeeResult) === null || _g === void 0 ? void 0 : _g.buyFeeBps) === null || _h === void 0 ? void 0 : _h.gt(0)) ||
566
+ ((_l = (_k = (_j = tokenOutProperties[getAddressLowerCase(currencyOut)]) === null || _j === void 0 ? void 0 : _j.tokenFeeResult) === null || _k === void 0 ? void 0 : _k.sellFeeBps) === null || _l === void 0 ? void 0 : _l.gt(0))) {
567
+ if (feeTakenOnTransfer || externalTransferFailed) {
568
+ // also to be extra safe, in case of FOT with feeTakenOnTransfer or externalTransferFailed,
569
+ // we nullify the fee and flat fee to avoid any potential issues.
570
+ // although neither web nor wallet should use the calldata returned from routing/SOR
571
+ if ((swapConfig === null || swapConfig === void 0 ? void 0 : swapConfig.type) === SwapType.UNIVERSAL_ROUTER) {
572
+ swapConfig.fee = undefined;
573
+ swapConfig.flatFee = undefined;
574
+ }
575
+ metric.putMetric('TokenOutFeeOnTransferNotTakingFee', 1, MetricLoggerUnit.Count);
576
+ }
577
+ else {
578
+ metric.putMetric('TokenOutFeeOnTransferTakingFee', 1, MetricLoggerUnit.Count);
579
+ }
580
+ }
581
+ if (tradeType === TradeType.EXACT_OUTPUT) {
582
+ const portionAmount = this.portionProvider.getPortionAmount(amount, tradeType, feeTakenOnTransfer, externalTransferFailed, swapConfig);
583
+ if (portionAmount && portionAmount.greaterThan(ZERO)) {
584
+ // In case of exact out swap, before we route, we need to make sure that the
585
+ // token out amount accounts for flat portion, and token in amount after the best swap route contains the token in equivalent of portion.
586
+ // In other words, in case a pool's LP fee bps is lower than the portion bps (0.01%/0.05% for v3), a pool can go insolvency.
587
+ // This is because instead of the swapper being responsible for the portion,
588
+ // the pool instead gets responsible for the portion.
589
+ // The addition below avoids that situation.
590
+ amount = amount.add(portionAmount);
591
+ }
592
+ const portionFewAmount = this.portionProvider.getPortionAmount(fewAmount, tradeType, feeTakenOnTransfer, externalTransferFailed, swapConfig);
593
+ if (portionFewAmount && portionFewAmount.greaterThan(ZERO)) {
594
+ // In case of exact out swap, before we route, we need to make sure that the
595
+ // token out few amount accounts for flat portion, and token in few amount after the best swap route contains the token in equivalent of portion.
596
+ // In other words, in case a pool's LP fee bps is lower than the portion bps (0.01%/0.05% for v3), a pool can go insolvency.
597
+ // This is because instead of the swapper being responsible for the portion,
598
+ // the pool instead gets responsible for the portion.
599
+ // The addition below avoids that situation.
600
+ fewAmount = fewAmount.add(portionFewAmount.wrapped);
601
+ }
602
+ }
603
+ metric.setProperty('chainId', this.chainId);
604
+ metric.setProperty('pair', `${currencyIn.symbol}/${currencyOut.symbol}`);
605
+ metric.setProperty('tokenIn', getAddress(currencyIn));
606
+ metric.setProperty('tokenOut', getAddress(currencyOut));
607
+ metric.setProperty('tradeType', tradeType === TradeType.EXACT_INPUT ? 'ExactIn' : 'ExactOut');
608
+ metric.putMetric(`QuoteRequestedForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
609
+ // Get a block number to specify in all our calls. Ensures data we fetch from chain is
610
+ // from the same block.
611
+ const blockNumber = (_m = partialRoutingConfig.blockNumber) !== null && _m !== void 0 ? _m : this.getBlockNumberPromise();
612
+ const routingConfig = _.merge({
613
+ // These settings could be changed by the partialRoutingConfig
614
+ useCachedRoutes: true,
615
+ writeToCachedRoutes: true,
616
+ optimisticCachedRoutes: false,
617
+ }, DEFAULT_ROUTING_CONFIG_BY_CHAIN(this.chainId), partialRoutingConfig, { blockNumber });
618
+ if (routingConfig.debugRouting) {
619
+ log.warn(`Finalized routing config is ${JSON.stringify(routingConfig)}`);
620
+ }
621
+ const gasPriceWei = await this.getGasPriceWei(await blockNumber, await partialRoutingConfig.blockNumber);
622
+ // const gasTokenAccessor = await this.tokenProvider.getTokens([routingConfig.gasToken!]);
623
+ const gasToken = routingConfig.gasToken
624
+ ? (await this.tokenProvider.getTokens([routingConfig.gasToken])).getTokenByAddress(routingConfig.gasToken)
625
+ : undefined;
626
+ const providerConfig = {
627
+ ...routingConfig,
628
+ blockNumber,
629
+ additionalGasOverhead: NATIVE_OVERHEAD(this.chainId, amount.currency, quoteCurrency),
630
+ gasToken,
631
+ externalTransferFailed,
632
+ feeTakenOnTransfer,
633
+ };
634
+ startTimer('alpha-router.route.getGasModels');
635
+ const { ringFewV2GasModel: ringFewV2GasModel, v2GasModel: v2GasModel, fewV2GasModel: fewV2GasModel, v3GasModel: v3GasModel, fewV3GasModel: fewV3GasModel, v4GasModel: v4GasModel, fewV4GasModel: fewV4GasModel, mixedRouteGasModel: mixedRouteGasModel, } = await this.getGasModels(gasPriceWei, amount.currency.wrapped, quoteCurrency.wrapped, providerConfig);
636
+ endTimer('alpha-router.route.getGasModels');
637
+ // Create a Set to sanitize the protocols input, a Set of undefined becomes an empty set,
638
+ // Then create an Array from the values of that Set.
639
+ const protocols = Array.from(new Set(routingConfig.protocols).values());
640
+ startTimer('alpha-router.route.getCacheMode');
641
+ const cacheMode = (_o = routingConfig.overwriteCacheMode) !== null && _o !== void 0 ? _o : (await ((_p = this.routeCachingProvider) === null || _p === void 0 ? void 0 : _p.getCacheMode(this.chainId, amount, quoteCurrency, tradeType, protocols)));
642
+ endTimer('alpha-router.route.getCacheMode');
643
+ // const fewCacheMode =
644
+ // routingConfig.overwriteCacheMode ??
645
+ // (await this.routeCachingProvider?.getCacheMode(
646
+ // this.chainId,
647
+ // fewAmount,
648
+ // fewQuoteToken!,
649
+ // tradeType,
650
+ // protocols
651
+ // ));
652
+ // Fetch CachedRoutes
653
+ let cachedRoutes;
654
+ // Fetch fewCachedRoutes
655
+ let fewCachedRoutes;
656
+ // Decide whether to use cached routes or not - If |enabledAndRequestedProtocolsMatch| is true we are good to use cached routes.
657
+ // In order to use cached routes, we need to have all enabled protocols specified in the request.
658
+ // By default, all protocols are enabled but for UniversalRouterVersion.V1_2, V4 is not.
659
+ // - ref: https://github.com/Uniswap/routing-api/blob/663b607d80d9249f85e7ab0925a611ec3701da2a/lib/util/supportedProtocolVersions.ts#L15
660
+ // So we take this into account when deciding whether to use cached routes or not.
661
+ // We only want to use cache if all enabled protocols are specified (V2,V3,V4? + MIXED). In any other case, use onchain path.
662
+ // - Cache is optimized for global search, not for specific protocol(s) search.
663
+ // For legacy systems (SWAP_ROUTER_02) or missing swapConfig, follow UniversalRouterVersion.V1_2 logic.
664
+ const availableProtocolsSet = new Set(Object.values(Protocol));
665
+ const requestedProtocolsSet = new Set(protocols);
666
+ const swapRouter = !swapConfig ||
667
+ swapConfig.type === SwapType.SWAP_ROUTER_02 ||
668
+ (swapConfig.type === SwapType.UNIVERSAL_ROUTER &&
669
+ swapConfig.version === UniversalRouterVersion.V1_2);
670
+ if (swapRouter) {
671
+ availableProtocolsSet.delete(Protocol.V4);
672
+ if (requestedProtocolsSet.has(Protocol.V4)) {
673
+ requestedProtocolsSet.delete(Protocol.V4);
674
+ }
675
+ }
676
+ const enabledAndRequestedProtocolsMatch = availableProtocolsSet.size === requestedProtocolsSet.size &&
677
+ [...availableProtocolsSet].every((protocol) => requestedProtocolsSet.has(protocol));
678
+ // If the requested protocols do not match the enabled protocols, we need to set the hooks options to NO_HOOKS.
679
+ if (!requestedProtocolsSet.has(Protocol.V4)) {
680
+ routingConfig.hooksOptions = HooksOptions.NO_HOOKS;
681
+ }
682
+ // If hooksOptions not specified and it's not a swapRouter (i.e. Universal Router it is),
683
+ // we should also set it to HOOKS_INCLUSIVE, as this is default behavior even without hooksOptions.
684
+ if (!routingConfig.hooksOptions) {
685
+ routingConfig.hooksOptions = HooksOptions.HOOKS_INCLUSIVE;
686
+ }
687
+ log.debug('UniversalRouterVersion_CacheGate_Check', {
688
+ availableProtocolsSet: Array.from(availableProtocolsSet),
689
+ requestedProtocolsSet: Array.from(requestedProtocolsSet),
690
+ enabledAndRequestedProtocolsMatch,
691
+ swapConfigType: swapConfig === null || swapConfig === void 0 ? void 0 : swapConfig.type,
692
+ swapConfigUniversalRouterVersion: (swapConfig === null || swapConfig === void 0 ? void 0 : swapConfig.type) === SwapType.UNIVERSAL_ROUTER
693
+ ? swapConfig === null || swapConfig === void 0 ? void 0 : swapConfig.version
694
+ : 'N/A',
695
+ });
696
+ startTimer('alpha-router.route.isAllowedToEnterCachedRoutes');
697
+ const isAllowedToEnterCachedRoutes = AlphaRouter.isAllowedToEnterCachedRoutes(routingConfig.intent, routingConfig.hooksOptions, swapRouter);
698
+ if (routingConfig.useCachedRoutes &&
699
+ cacheMode !== CacheMode.Darkmode &&
700
+ isAllowedToEnterCachedRoutes) {
701
+ if (enabledAndRequestedProtocolsMatch) {
702
+ if (protocols.includes(Protocol.V4) &&
703
+ (currencyIn.isNative || currencyOut.isNative)) {
704
+ const [wrappedNativeCachedRoutes, nativeCachedRoutes] = await Promise.all([
705
+ (_q = this.routeCachingProvider) === null || _q === void 0 ? void 0 : _q.getCachedRoute(this.chainId, CurrencyAmount.fromRawAmount(amount.currency.wrapped, amount.quotient), quoteCurrency.wrapped, tradeType, protocols, await blockNumber, routingConfig.optimisticCachedRoutes),
706
+ (_r = this.routeCachingProvider) === null || _r === void 0 ? void 0 : _r.getCachedRoute(this.chainId, amount, quoteCurrency, tradeType, [Protocol.V4], await blockNumber, routingConfig.optimisticCachedRoutes),
707
+ ]);
708
+ if ((wrappedNativeCachedRoutes &&
709
+ (wrappedNativeCachedRoutes === null || wrappedNativeCachedRoutes === void 0 ? void 0 : wrappedNativeCachedRoutes.routes.length) > 0) ||
710
+ (nativeCachedRoutes && (nativeCachedRoutes === null || nativeCachedRoutes === void 0 ? void 0 : nativeCachedRoutes.routes.length) > 0)) {
711
+ cachedRoutes = new CachedRoutes({
712
+ routes: [
713
+ ...((_s = nativeCachedRoutes === null || nativeCachedRoutes === void 0 ? void 0 : nativeCachedRoutes.routes) !== null && _s !== void 0 ? _s : []),
714
+ ...((_t = wrappedNativeCachedRoutes === null || wrappedNativeCachedRoutes === void 0 ? void 0 : wrappedNativeCachedRoutes.routes) !== null && _t !== void 0 ? _t : []),
715
+ ],
716
+ chainId: this.chainId,
717
+ currencyIn: currencyIn,
718
+ currencyOut: currencyOut,
719
+ protocolsCovered: protocols,
720
+ blockNumber: await blockNumber,
721
+ tradeType: tradeType,
722
+ originalAmount: (_v = (_u = wrappedNativeCachedRoutes === null || wrappedNativeCachedRoutes === void 0 ? void 0 : wrappedNativeCachedRoutes.originalAmount) !== null && _u !== void 0 ? _u : nativeCachedRoutes === null || nativeCachedRoutes === void 0 ? void 0 : nativeCachedRoutes.originalAmount) !== null && _v !== void 0 ? _v : amount.quotient.toString(),
723
+ blocksToLive: (_x = (_w = wrappedNativeCachedRoutes === null || wrappedNativeCachedRoutes === void 0 ? void 0 : wrappedNativeCachedRoutes.blocksToLive) !== null && _w !== void 0 ? _w : nativeCachedRoutes === null || nativeCachedRoutes === void 0 ? void 0 : nativeCachedRoutes.blocksToLive) !== null && _x !== void 0 ? _x : DEFAULT_BLOCKS_TO_LIVE[this.chainId],
724
+ });
725
+ }
726
+ }
727
+ else {
728
+ cachedRoutes = await ((_y = this.routeCachingProvider) === null || _y === void 0 ? void 0 : _y.getCachedRoute(this.chainId, amount, quoteCurrency, tradeType, protocols, await blockNumber, routingConfig.optimisticCachedRoutes));
729
+ fewCachedRoutes = await ((_z = this.routeCachingProvider) === null || _z === void 0 ? void 0 : _z.getCachedRoute(this.chainId, fewAmount, fewQuoteToken, tradeType, protocols, await blockNumber, routingConfig.optimisticCachedRoutes));
730
+ }
731
+ }
732
+ }
733
+ endTimer('alpha-router.route.isAllowedToEnterCachedRoutes');
734
+ if (shouldWipeoutCachedRoutes(cachedRoutes, routingConfig)) {
735
+ cachedRoutes = undefined;
736
+ }
737
+ if (shouldWipeoutCachedRoutes(fewCachedRoutes, routingConfig)) {
738
+ fewCachedRoutes = undefined;
739
+ }
740
+ metric.putMetric(routingConfig.useCachedRoutes
741
+ ? 'GetQuoteUsingCachedRoutes'
742
+ : 'GetQuoteNotUsingCachedRoutes', 1, MetricLoggerUnit.Count);
743
+ startTimer('alpha-router.route.getCachedRoute');
744
+ if (cacheMode &&
745
+ routingConfig.useCachedRoutes &&
746
+ cacheMode !== CacheMode.Darkmode &&
747
+ !cachedRoutes) {
748
+ metric.putMetric(`GetCachedRoute_miss_${cacheMode}`, 1, MetricLoggerUnit.Count);
749
+ log.info({
750
+ currencyIn: currencyIn.symbol,
751
+ currencyInAddress: getAddress(currencyIn),
752
+ currencyOut: currencyOut.symbol,
753
+ currencyOutAddress: getAddress(currencyOut),
754
+ cacheMode,
755
+ amount: amount.toExact(),
756
+ chainId: this.chainId,
757
+ tradeType: this.tradeTypeStr(tradeType),
758
+ }, `GetCachedRoute miss ${cacheMode} for ${this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType)}`);
759
+ }
760
+ else if (cachedRoutes && routingConfig.useCachedRoutes) {
761
+ metric.putMetric(`GetCachedRoute_hit_${cacheMode}`, 1, MetricLoggerUnit.Count);
762
+ log.info({
763
+ currencyIn: currencyIn.symbol,
764
+ currencyInAddress: getAddress(currencyIn),
765
+ currencyOut: currencyOut.symbol,
766
+ currencyOutAddress: getAddress(currencyOut),
767
+ cacheMode,
768
+ amount: amount.toExact(),
769
+ chainId: this.chainId,
770
+ tradeType: this.tradeTypeStr(tradeType),
771
+ }, `GetCachedRoute hit ${cacheMode} for ${this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType)}`);
772
+ }
773
+ endTimer('alpha-router.route.getCachedRoute');
774
+ startTimer('alpha-router.route.getSwapRouteFromCache');
775
+ let swapRouteFromCachePromise = Promise.resolve(null);
776
+ if (cachedRoutes) {
777
+ swapRouteFromCachePromise = this.getSwapRouteFromCache(currencyIn, currencyOut, cachedRoutes, await blockNumber, amount, fewAmount, quoteCurrency, fewQuoteToken, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig);
778
+ }
779
+ endTimer('alpha-router.route.getSwapRouteFromCache');
780
+ startTimer('alpha-router.route.getUniswapFewTokenSwapRouteFromCache');
781
+ let uniswapFewSwapRouteFromCachePromise = Promise.resolve(null);
782
+ if (fewCachedRoutes) {
783
+ uniswapFewSwapRouteFromCachePromise = this.getUniswapFewTokenSwapRouteFromCache(fewTokenIn, fewTokenOut, fewCachedRoutes, await blockNumber, amount, fewAmount, quoteCurrency, fewQuoteToken, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig);
784
+ }
785
+ endTimer('alpha-router.route.getUniswapFewTokenSwapRouteFromCache');
786
+ startTimer('alpha-router.route.getSwapRouteFromChain');
787
+ let swapRouteFromChainPromise = Promise.resolve(null);
788
+ if (!cachedRoutes || cacheMode !== CacheMode.Livemode) {
789
+ swapRouteFromChainPromise = this.getSwapRouteFromChain(amount, fewAmount, currencyIn, fewTokenIn, currencyOut, fewTokenOut, protocols, quoteCurrency, fewQuoteToken, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, ringFewV2GasModel, swapConfig, providerConfig);
790
+ }
791
+ endTimer('alpha-router.route.getSwapRouteFromChain');
792
+ startTimer('alpha-router.route.getUniswapFewTokenSwapRouteFromChain');
793
+ let uniswapFewSwapRouteFromChainPromise = Promise.resolve(null);
794
+ if (!cachedRoutes || cacheMode !== CacheMode.Livemode) {
795
+ //cachedRoutes is undefined
796
+ uniswapFewSwapRouteFromChainPromise = this.getUniswapFewTokenSwapRouteFromChain(amount, fewAmount, currencyIn, fewTokenIn, currencyOut, fewTokenOut, protocols, quoteCurrency, fewQuoteToken, tradeType, routingConfig,
797
+ // v3GasModel,
798
+ fewV3GasModel,
799
+ // v4GasModel,
800
+ fewV4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, fewV2GasModel,
801
+ // ringFewV2GasModel,
802
+ providerConfig);
803
+ }
804
+ endTimer('alpha-router.route.getUniswapFewTokenSwapRouteFromChain');
805
+ // let swapRouteFromRingFewChainPromise: Promise<BestSwapRoute | null> =
806
+ // Promise.resolve(null);
807
+ // if (!fewCachedRoutes || cacheMode !== CacheMode.Livemode) {
808
+ // swapRouteFromRingFewChainPromise = this.getSwapRouteFromChain(
809
+ // fewAmount!,
810
+ // fewTokenIn!,
811
+ // fewTokenOut!,
812
+ // protocols,
813
+ // fewQuoteToken!,
814
+ // tradeType,
815
+ // routingConfig,
816
+ // v3GasModel,
817
+ // v4GasModel,
818
+ // mixedRouteGasModel,
819
+ // gasPriceWei,
820
+ // ringFewV2GasModel,
821
+ // swapConfig,
822
+ // providerConfig
823
+ // );
824
+ // }
825
+ startTimer('alpha-router.route.getSwapRouteFromCache_Chain');
826
+ const [swapRouteFromCache, uniswapFewSwapRouteFromCache,] = await Promise.all([
827
+ swapRouteFromCachePromise,
828
+ uniswapFewSwapRouteFromCachePromise
829
+ ]);
830
+ const [swapRouteFromChainRaw, uniswapFewSwapRouteFromChainRaw,] = await Promise.all([
831
+ swapRouteFromChainPromise,
832
+ uniswapFewSwapRouteFromChainPromise
833
+ ]);
834
+ const [percents] = this.getAmountDistribution(amount, routingConfig);
835
+ const allRoutesWithValidQuotes = [...(swapRouteFromChainRaw || []), ...(uniswapFewSwapRouteFromChainRaw || [])];
836
+ const swapRouteFromChain = await getBestSwapRoute(amount, percents, allRoutesWithValidQuotes, tradeType, this.chainId, routingConfig, this.portionProvider, v2GasModel, v3GasModel, v4GasModel, swapConfig, providerConfig);
837
+ if (swapRouteFromChain) {
838
+ // this.emitPoolSelectionMetrics(
839
+ // swapRouteFromChain,
840
+ // [],
841
+ // currencyIn,
842
+ // currencyOut
843
+ // );
844
+ }
845
+ endTimer('alpha-router.route.getSwapRouteFromCache_Chain');
846
+ let swapRouteRaw;
847
+ let hitsCachedRoute = false;
848
+ if (cacheMode === CacheMode.Livemode && swapRouteFromCache) {
849
+ log.info(`CacheMode is ${cacheMode}, and we are using swapRoute from cache`);
850
+ hitsCachedRoute = true;
851
+ swapRouteRaw = swapRouteFromCache;
852
+ }
853
+ else {
854
+ log.info(`CacheMode is ${cacheMode}, and we are using materialized swapRoute`);
855
+ swapRouteRaw = swapRouteFromChain;
856
+ }
857
+ let uniswapFewSwapRouteRaw;
858
+ if (cacheMode === CacheMode.Livemode && uniswapFewSwapRouteFromCache) {
859
+ log.info(`CacheMode is ${cacheMode}, and we are using swapRoute from cache`);
860
+ hitsCachedRoute = true;
861
+ uniswapFewSwapRouteRaw = uniswapFewSwapRouteFromCache;
862
+ }
863
+ else {
864
+ log.info(`CacheMode is ${cacheMode}, and we are using materialized swapRoute`);
865
+ uniswapFewSwapRouteRaw = swapRouteFromChain;
866
+ }
867
+ // let ringFewSwapRouteRaw: BestSwapRoute | null;
868
+ // let hitsCachedRingFewSRoute = false;
869
+ // if (cacheMode === CacheMode.Livemode && swapRouteFromRingFewCache) {
870
+ // log.info(
871
+ // `CacheMode is ${cacheMode}, and we are using swapRoute from cache`
872
+ // );
873
+ // hitsCachedRingFewSRoute = true;
874
+ // ringFewSwapRouteRaw = swapRouteFromRingFewCache;
875
+ // } else {
876
+ // log.info(
877
+ // `CacheMode is ${cacheMode}, and we are using materialized swapRoute`
878
+ // );
879
+ // ringFewSwapRouteRaw = swapRouteFromRingFewChain;
880
+ // }
881
+ startTimer('alpha-router.route.tapcompareCachedRoute');
882
+ if (cacheMode === CacheMode.Tapcompare &&
883
+ swapRouteFromCache &&
884
+ swapRouteFromChain) {
885
+ const quoteDiff = swapRouteFromChain.quote.subtract(swapRouteFromCache.quote);
886
+ const quoteGasAdjustedDiff = swapRouteFromChain.quoteGasAdjusted.subtract(swapRouteFromCache.quoteGasAdjusted);
887
+ const gasUsedDiff = swapRouteFromChain.estimatedGasUsed.sub(swapRouteFromCache.estimatedGasUsed);
888
+ // Only log if quoteDiff is different from 0, or if quoteGasAdjustedDiff and gasUsedDiff are both different from 0
889
+ if (!quoteDiff.equalTo(0) ||
890
+ !(quoteGasAdjustedDiff.equalTo(0) || gasUsedDiff.eq(0))) {
891
+ try {
892
+ // Calculates the percentage of the difference with respect to the quoteFromChain (not from cache)
893
+ const misquotePercent = quoteGasAdjustedDiff
894
+ .divide(swapRouteFromChain.quoteGasAdjusted)
895
+ .multiply(100);
896
+ metric.putMetric(`TapcompareCachedRoute_quoteGasAdjustedDiffPercent`, Number(misquotePercent.toExact()), MetricLoggerUnit.Percent);
897
+ log.warn({
898
+ quoteFromChain: swapRouteFromChain.quote.toExact(),
899
+ quoteFromCache: swapRouteFromCache.quote.toExact(),
900
+ quoteDiff: quoteDiff.toExact(),
901
+ quoteGasAdjustedFromChain: swapRouteFromChain.quoteGasAdjusted.toExact(),
902
+ quoteGasAdjustedFromCache: swapRouteFromCache.quoteGasAdjusted.toExact(),
903
+ quoteGasAdjustedDiff: quoteGasAdjustedDiff.toExact(),
904
+ gasUsedFromChain: swapRouteFromChain.estimatedGasUsed.toString(),
905
+ gasUsedFromCache: swapRouteFromCache.estimatedGasUsed.toString(),
906
+ gasUsedDiff: gasUsedDiff.toString(),
907
+ routesFromChain: swapRouteFromChain.routes.toString(),
908
+ routesFromCache: swapRouteFromCache.routes.toString(),
909
+ amount: amount.toExact(),
910
+ originalAmount: cachedRoutes === null || cachedRoutes === void 0 ? void 0 : cachedRoutes.originalAmount,
911
+ pair: this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType),
912
+ blockNumber,
913
+ }, `Comparing quotes between Chain and Cache for ${this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType)}`);
914
+ }
915
+ catch (error) {
916
+ // This is in response to the 'division by zero' error
917
+ // during https://uniswapteam.slack.com/archives/C059TGEC57W/p1723997015399579
918
+ if (error instanceof RangeError &&
919
+ error.message.includes('Division by zero')) {
920
+ log.error({
921
+ quoteGasAdjustedDiff: quoteGasAdjustedDiff.toExact(),
922
+ swapRouteFromChainQuoteGasAdjusted: swapRouteFromChain.quoteGasAdjusted.toExact(),
923
+ }, 'Error calculating misquote percent');
924
+ metric.putMetric(`TapcompareCachedRoute_quoteGasAdjustedDiffPercent_divzero`, 1, MetricLoggerUnit.Count);
925
+ }
926
+ // Log but don't throw here - this is only for logging.
927
+ }
928
+ }
929
+ }
930
+ endTimer('alpha-router.route.tapcompareCachedRoute');
931
+ if (!swapRouteRaw && !uniswapFewSwapRouteRaw) {
932
+ return null;
933
+ }
934
+ // Use either swapRouteRaw or uniswapFewSwapRouteRaw as the source of route data
935
+ // We already checked above that at least one is non-null, so we can safely assert non-null
936
+ const routeSource = swapRouteRaw;
937
+ // Now we can safely destructure since routeSource is guaranteed to be non-null
938
+ const { quote, quoteGasAdjusted, estimatedGasUsed, routes: routeAmounts, estimatedGasUsedQuoteToken, estimatedGasUsedUSD, estimatedGasUsedGasToken, } = routeSource;
939
+ metric.putMetric(`QuoteFoundForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
940
+ // Build Trade object that represents the optimal swap.
941
+ const trade = buildTrade(currencyIn, fewTokenIn, currencyOut, fewTokenOut, tradeType, routeAmounts);
942
+ let methodParameters;
943
+ // If user provided recipient, deadline etc. we also generate the calldata required to execute
944
+ // the swap and return it too.
945
+ if (swapConfig) {
946
+ methodParameters = buildSwapMethodParameters(trade, swapConfig, this.chainId);
947
+ }
948
+ const tokenOutAmount = tradeType === TradeType.EXACT_OUTPUT
949
+ ? originalAmount // we need to pass in originalAmount instead of amount, because amount already added portionAmount in case of exact out swap
950
+ : quote;
951
+ const portionAmount = this.portionProvider.getPortionAmount(tokenOutAmount, tradeType, feeTakenOnTransfer, externalTransferFailed, swapConfig);
952
+ const portionQuoteAmount = this.portionProvider.getPortionQuoteAmount(tradeType, quote, amount, // we need to pass in amount instead of originalAmount here, because amount here needs to add the portion for exact out
953
+ portionAmount);
954
+ // we need to correct quote and quote gas adjusted for exact output when portion is part of the exact out swap
955
+ const correctedQuote = this.portionProvider.getQuote(tradeType, quote, portionQuoteAmount);
956
+ const correctedQuoteGasAdjusted = this.portionProvider.getQuoteGasAdjusted(tradeType, quoteGasAdjusted, portionQuoteAmount);
957
+ const quoteGasAndPortionAdjusted = this.portionProvider.getQuoteGasAndPortionAdjusted(tradeType, quoteGasAdjusted, portionAmount);
958
+ const swapRoute = {
959
+ quote: correctedQuote,
960
+ quoteGasAdjusted: correctedQuoteGasAdjusted,
961
+ estimatedGasUsed,
962
+ estimatedGasUsedQuoteToken,
963
+ estimatedGasUsedUSD,
964
+ estimatedGasUsedGasToken,
965
+ gasPriceWei,
966
+ route: routeAmounts,
967
+ trade,
968
+ methodParameters,
969
+ blockNumber: BigNumber.from(await blockNumber),
970
+ hitsCachedRoute: hitsCachedRoute,
971
+ portionAmount: portionAmount,
972
+ quoteGasAndPortionAdjusted: quoteGasAndPortionAdjusted,
973
+ };
974
+ if (swapConfig &&
975
+ swapConfig.simulate &&
976
+ methodParameters &&
977
+ methodParameters.calldata) {
978
+ if (!this.simulator) {
979
+ throw new Error('Simulator not initialized!');
980
+ }
981
+ log.info(JSON.stringify({ swapConfig, methodParameters, providerConfig }, null, 2), `Starting simulation`);
982
+ const fromAddress = swapConfig.simulate.fromAddress;
983
+ const beforeSimulate = Date.now();
984
+ const swapRouteWithSimulation = await this.simulator.simulate(fromAddress, swapConfig, swapRoute, amount,
985
+ // Quote will be in WETH even if quoteCurrency is ETH
986
+ // So we init a new CurrencyAmount object here
987
+ CurrencyAmount.fromRawAmount(quoteCurrency, quote.quotient.toString()), providerConfig);
988
+ metric.putMetric('SimulateTransaction', Date.now() - beforeSimulate, MetricLoggerUnit.Milliseconds);
989
+ if (routingConfig.intent === INTENT.CACHING) {
990
+ if (swapRouteWithSimulation.simulationStatus) {
991
+ await this.performCachingIntention(currencyIn, currencyOut, tradeType, amount, protocols, await blockNumber, routingConfig, swapRouteWithSimulation.simulationStatus, swapRouteWithSimulation.route);
992
+ }
993
+ else {
994
+ log.info('Simulation status is null');
995
+ }
996
+ }
997
+ return swapRouteWithSimulation;
998
+ }
999
+ getPerfReport();
1000
+ return swapRoute;
1001
+ }
1002
+ /**
1003
+ * Performs the caching intention for the given simulation status and route.
1004
+ *
1005
+ * @param currencyIn the currency in
1006
+ * @param currencyOut the currency out
1007
+ * @param tradeType the trade type
1008
+ * @param amount the amount
1009
+ * @param protocols the protocols
1010
+ * @param blockNumber the block number
1011
+ * @param routingConfig the routing config
1012
+ * @param simulationStatus the simulation status
1013
+ * @param simulationRoute the simulation route
1014
+ */
1015
+ async performCachingIntention(currencyIn, currencyOut, tradeType, amount, protocols, blockNumber, routingConfig, simulationStatus, simulationRoute) {
1016
+ // due to fire and forget nature, we already take note that we should set new cached routes during the new path
1017
+ metric.putMetric(`SetCachedRoute_NewPath`, 1, MetricLoggerUnit.Count);
1018
+ log.info(simulationStatus, 'Simulation status');
1019
+ if (this.shouldCacheRoute(simulationStatus)) {
1020
+ const routesToCache = CachedRoutes.fromRoutesWithValidQuotes(simulationRoute, this.chainId, currencyIn, currencyOut, protocols.sort(), blockNumber, tradeType, amount.toExact());
1021
+ await this.setCachedRoutesAndLog(amount, currencyIn, currencyOut, tradeType, 'SetCachedRoute_NewPath', routesToCache, routingConfig.cachedRoutesRouteIds);
1022
+ }
1023
+ }
1024
+ /**
1025
+ * @param simulationStatus the status of the simulation
1026
+ * @returns true if the route should be cached, false otherwise
1027
+ */
1028
+ shouldCacheRoute(simulationStatus) {
1029
+ // Do not cache the route for the following reasons:
1030
+ // 1. failed when tenderly sim failed for unknown reason
1031
+ // 2. slippage since we know swap is bound to fail
1032
+ // 3. transfer from failed since we know swap is bound to fail
1033
+ return (simulationStatus !== SimulationStatus.Failed &&
1034
+ simulationStatus !== SimulationStatus.SlippageTooLow &&
1035
+ simulationStatus !== SimulationStatus.TransferFromFailed);
1036
+ }
1037
+ async setCachedRoutesAndLog(amount, currencyIn, currencyOut, tradeType, metricsPrefix, routesToCache, cachedRoutesRouteIds) {
1038
+ var _a;
1039
+ if (routesToCache) {
1040
+ const cachedRoutesChanged = cachedRoutesRouteIds !== undefined &&
1041
+ // it's possible that top cached routes may be split routes,
1042
+ // so that we always serialize all the top 8 retrieved cached routes vs the top routes.
1043
+ !cachedRoutesRouteIds.startsWith(serializeRouteIds(routesToCache.routes.map((r) => r.routeId)));
1044
+ if (cachedRoutesChanged) {
1045
+ metric.putMetric('cachedRoutesChanged', 1, MetricLoggerUnit.Count);
1046
+ metric.putMetric(`cachedRoutesChanged_chainId${currencyIn.chainId}`, 1, MetricLoggerUnit.Count);
1047
+ metric.putMetric(`cachedRoutesChanged_chainId${currencyOut.chainId}_pair${currencyIn.symbol}${currencyOut.symbol}`, 1, MetricLoggerUnit.Count);
1048
+ }
1049
+ else {
1050
+ metric.putMetric('cachedRoutesNotChanged', 1, MetricLoggerUnit.Count);
1051
+ metric.putMetric(`cachedRoutesNotChanged_chainId${currencyIn.chainId}`, 1, MetricLoggerUnit.Count);
1052
+ metric.putMetric(`cachedRoutesNotChanged_chainId${currencyOut.chainId}_pair${currencyIn.symbol}${currencyOut.symbol}`, 1, MetricLoggerUnit.Count);
1053
+ }
1054
+ await ((_a = this.routeCachingProvider) === null || _a === void 0 ? void 0 : _a.setCachedRoute(routesToCache, amount).then((success) => {
1055
+ const status = success ? 'success' : 'rejected';
1056
+ metric.putMetric(`${metricsPrefix}_${status}`, 1, MetricLoggerUnit.Count);
1057
+ }).catch((reason) => {
1058
+ log.error({
1059
+ reason: reason,
1060
+ tokenPair: this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType),
1061
+ }, `SetCachedRoute failure`);
1062
+ metric.putMetric(`${metricsPrefix}_failure`, 1, MetricLoggerUnit.Count);
1063
+ }));
1064
+ }
1065
+ else {
1066
+ metric.putMetric(`${metricsPrefix}_unnecessary`, 1, MetricLoggerUnit.Count);
1067
+ }
1068
+ }
1069
+ async getSwapRouteFromCache(currencyIn, currencyOut, cachedRoutes, blockNumber, amount, fewAmount, quoteCurrency, fewQuoteToken, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig) {
1070
+ var _a, _c, _d, _e, _f, _g;
1071
+ const tokenPairProperties = await this.tokenPropertiesProvider.getTokensProperties([currencyIn, currencyOut], providerConfig);
1072
+ const sellTokenIsFot = (_d = (_c = (_a = tokenPairProperties[getAddressLowerCase(currencyIn)]) === null || _a === void 0 ? void 0 : _a.tokenFeeResult) === null || _c === void 0 ? void 0 : _c.sellFeeBps) === null || _d === void 0 ? void 0 : _d.gt(0);
1073
+ const buyTokenIsFot = (_g = (_f = (_e = tokenPairProperties[getAddressLowerCase(currencyOut)]) === null || _e === void 0 ? void 0 : _e.tokenFeeResult) === null || _f === void 0 ? void 0 : _f.buyFeeBps) === null || _g === void 0 ? void 0 : _g.gt(0);
1074
+ const fotInDirectSwap = sellTokenIsFot || buyTokenIsFot;
1075
+ log.info({
1076
+ protocols: cachedRoutes.protocolsCovered,
1077
+ tradeType: cachedRoutes.tradeType,
1078
+ cachedBlockNumber: cachedRoutes.blockNumber,
1079
+ quoteBlockNumber: blockNumber,
1080
+ }, 'Routing across CachedRoute');
1081
+ const quotePromises = [];
1082
+ const v4Routes = cachedRoutes.routes.filter((route) => route.protocol === Protocol.V4);
1083
+ const v3Routes = cachedRoutes.routes.filter((route) => route.protocol === Protocol.V3);
1084
+ const v2Routes = cachedRoutes.routes.filter((route) => route.protocol === Protocol.V2);
1085
+ const ringFewV2Routes = cachedRoutes.routes.filter((route) => route.protocol === Protocol.FEWV2);
1086
+ const mixedRoutes = cachedRoutes.routes.filter((route) => route.protocol === Protocol.MIXED);
1087
+ let percents;
1088
+ let amounts;
1089
+ if (cachedRoutes.routes.length > 1) {
1090
+ // If we have more than 1 route, we will quote the different percents for it, following the regular process
1091
+ [percents, amounts] = this.getAmountDistribution(amount, routingConfig);
1092
+ }
1093
+ else if (cachedRoutes.routes.length == 1) {
1094
+ [percents, amounts] = [[100], [amount]];
1095
+ }
1096
+ else {
1097
+ // In this case this means that there's no route, so we return null
1098
+ return Promise.resolve(null);
1099
+ }
1100
+ let fewPercents;
1101
+ let fewAmounts;
1102
+ if (cachedRoutes.routes.length > 1) {
1103
+ // If we have more than 1 route, we will quote the different percents for it, following the regular process
1104
+ [fewPercents, fewAmounts] = this.getAmountDistribution(fewAmount, routingConfig);
1105
+ }
1106
+ else if (cachedRoutes.routes.length == 1) {
1107
+ [fewPercents, fewAmounts] = [[100], [fewAmount]];
1108
+ }
1109
+ else {
1110
+ // In this case this means that there's no route, so we return null
1111
+ return Promise.resolve(null);
1112
+ }
1113
+ if (v4Routes.length > 0) {
1114
+ const v4RoutesFromCache = v4Routes.map((cachedRoute) => cachedRoute.route);
1115
+ metric.putMetric('SwapRouteFromCache_V4_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1116
+ const beforeGetQuotes = Date.now();
1117
+ quotePromises.push(this.v4Quoter
1118
+ .getQuotes(v4RoutesFromCache, amounts, percents, quoteCurrency, tradeType, routingConfig, undefined, v4GasModel)
1119
+ .then((result) => {
1120
+ metric.putMetric(`SwapRouteFromCache_V4_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1121
+ return result;
1122
+ }));
1123
+ }
1124
+ if (!fotInDirectSwap) {
1125
+ if (v3Routes.length > 0) {
1126
+ const v3RoutesFromCache = v3Routes.map((cachedRoute) => cachedRoute.route);
1127
+ metric.putMetric('SwapRouteFromCache_V3_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1128
+ const beforeGetQuotes = Date.now();
1129
+ quotePromises.push(this.v3Quoter
1130
+ .getQuotes(v3RoutesFromCache, amounts, percents, quoteCurrency.wrapped, tradeType, routingConfig, undefined, v3GasModel)
1131
+ .then((result) => {
1132
+ metric.putMetric(`SwapRouteFromCache_V3_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1133
+ return result;
1134
+ }));
1135
+ }
1136
+ }
1137
+ if (v2Routes.length > 0) {
1138
+ const v2RoutesFromCache = v2Routes.map((cachedRoute) => cachedRoute.route);
1139
+ metric.putMetric('SwapRouteFromCache_V2_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1140
+ const beforeGetQuotes = Date.now();
1141
+ quotePromises.push(this.v2Quoter
1142
+ .refreshRoutesThenGetQuotes(cachedRoutes.currencyIn.wrapped, cachedRoutes.currencyOut.wrapped, v2RoutesFromCache, amounts, percents, quoteCurrency.wrapped, tradeType, routingConfig, gasPriceWei)
1143
+ .then((result) => {
1144
+ metric.putMetric(`SwapRouteFromCache_V2_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1145
+ return result;
1146
+ }));
1147
+ }
1148
+ if (ringFewV2Routes.length > 0) {
1149
+ const ringFewV2RoutesFromCache = ringFewV2Routes.map((cachedRoute) => cachedRoute.route);
1150
+ metric.putMetric('SwapRouteFromCache_RingFewV2_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1151
+ const beforeGetQuotes = Date.now();
1152
+ quotePromises.push(this.ringFewV2Quoter
1153
+ .refreshRoutesThenGetQuotes(cachedRoutes.currencyIn.wrapped, cachedRoutes.currencyOut.wrapped, ringFewV2RoutesFromCache, fewAmounts, fewPercents, fewQuoteToken.wrapped, tradeType, routingConfig, gasPriceWei)
1154
+ .then((result) => {
1155
+ metric.putMetric(`SwapRouteFromCache_RingFewV2_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1156
+ return result;
1157
+ }));
1158
+ }
1159
+ if (!fotInDirectSwap) {
1160
+ if (mixedRoutes.length > 0) {
1161
+ const mixedRoutesFromCache = mixedRoutes.map((cachedRoute) => cachedRoute.route);
1162
+ metric.putMetric('SwapRouteFromCache_Mixed_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1163
+ const beforeGetQuotes = Date.now();
1164
+ quotePromises.push(this.mixedQuoter
1165
+ .getQuotes(mixedRoutesFromCache, amounts, percents, quoteCurrency.wrapped, tradeType, routingConfig, undefined, mixedRouteGasModel)
1166
+ .then((result) => {
1167
+ metric.putMetric(`SwapRouteFromCache_Mixed_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1168
+ return result;
1169
+ }));
1170
+ }
1171
+ }
1172
+ const getQuotesResults = await Promise.all(quotePromises);
1173
+ const allRoutesWithValidQuotes = _.flatMap(getQuotesResults, (quoteResult) => quoteResult.routesWithValidQuotes);
1174
+ return getBestSwapRoute(amount, percents, allRoutesWithValidQuotes, tradeType, this.chainId, routingConfig, this.portionProvider, v2GasModel, v3GasModel, v4GasModel, swapConfig, providerConfig);
1175
+ }
1176
+ async getUniswapFewTokenSwapRouteFromCache(fewTokenIn, fewTokenOut, fewCachedRoutes, blockNumber, amount, fewAmount, quoteCurrency, fewQuoteToken, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig) {
1177
+ var _a, _c, _d, _e, _f, _g;
1178
+ const tokenPairProperties = await this.tokenPropertiesProvider.getTokensProperties([fewTokenIn, fewTokenOut], providerConfig);
1179
+ const sellTokenIsFot = (_d = (_c = (_a = tokenPairProperties[getAddressLowerCase(fewTokenIn)]) === null || _a === void 0 ? void 0 : _a.tokenFeeResult) === null || _c === void 0 ? void 0 : _c.sellFeeBps) === null || _d === void 0 ? void 0 : _d.gt(0);
1180
+ const buyTokenIsFot = (_g = (_f = (_e = tokenPairProperties[getAddressLowerCase(fewTokenOut)]) === null || _e === void 0 ? void 0 : _e.tokenFeeResult) === null || _f === void 0 ? void 0 : _f.buyFeeBps) === null || _g === void 0 ? void 0 : _g.gt(0);
1181
+ const fotInDirectSwap = sellTokenIsFot || buyTokenIsFot;
1182
+ log.info({
1183
+ protocols: fewCachedRoutes.protocolsCovered,
1184
+ tradeType: fewCachedRoutes.tradeType,
1185
+ cachedBlockNumber: fewCachedRoutes.blockNumber,
1186
+ quoteBlockNumber: blockNumber,
1187
+ }, 'Routing across CachedRoute');
1188
+ const quotePromises = [];
1189
+ const v4Routes = fewCachedRoutes.routes.filter((route) => route.protocol === Protocol.V4);
1190
+ const v3Routes = fewCachedRoutes.routes.filter((route) => route.protocol === Protocol.V3);
1191
+ const v2Routes = fewCachedRoutes.routes.filter((route) => route.protocol === Protocol.V2);
1192
+ const ringFewV2Routes = fewCachedRoutes.routes.filter((route) => route.protocol === Protocol.FEWV2);
1193
+ const mixedRoutes = fewCachedRoutes.routes.filter((route) => route.protocol === Protocol.MIXED);
1194
+ let percents;
1195
+ let amounts;
1196
+ if (fewCachedRoutes.routes.length > 1) {
1197
+ // If we have more than 1 route, we will quote the different percents for it, following the regular process
1198
+ [percents, amounts] = this.getAmountDistribution(amount, routingConfig);
1199
+ }
1200
+ else if (fewCachedRoutes.routes.length == 1) {
1201
+ [percents, amounts] = [[100], [amount]];
1202
+ }
1203
+ else {
1204
+ // In this case this means that there's no route, so we return null
1205
+ return Promise.resolve(null);
1206
+ }
1207
+ let fewPercents;
1208
+ let fewAmounts;
1209
+ if (fewCachedRoutes.routes.length > 1) {
1210
+ // If we have more than 1 route, we will quote the different percents for it, following the regular process
1211
+ [fewPercents, fewAmounts] = this.getAmountDistribution(fewAmount, routingConfig);
1212
+ }
1213
+ else if (fewCachedRoutes.routes.length == 1) {
1214
+ [fewPercents, fewAmounts] = [[100], [fewAmount]];
1215
+ }
1216
+ else {
1217
+ // In this case this means that there's no route, so we return null
1218
+ return Promise.resolve(null);
1219
+ }
1220
+ if (v4Routes.length > 0) {
1221
+ const v4RoutesFromCache = v4Routes.map((cachedRoute) => cachedRoute.route);
1222
+ metric.putMetric('SwapRouteFromCache_V4_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1223
+ const beforeGetQuotes = Date.now();
1224
+ quotePromises.push(this.v4Quoter
1225
+ .getQuotes(v4RoutesFromCache, amounts, percents, quoteCurrency, tradeType, routingConfig, undefined, v4GasModel)
1226
+ .then((result) => {
1227
+ metric.putMetric(`SwapRouteFromCache_V4_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1228
+ return result;
1229
+ }));
1230
+ }
1231
+ if (!fotInDirectSwap) {
1232
+ if (v3Routes.length > 0) {
1233
+ const v3RoutesFromCache = v3Routes.map((cachedRoute) => cachedRoute.route);
1234
+ metric.putMetric('SwapRouteFromCache_V3_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1235
+ const beforeGetQuotes = Date.now();
1236
+ quotePromises.push(this.v3Quoter
1237
+ .getQuotes(v3RoutesFromCache, amounts, percents, quoteCurrency.wrapped, tradeType, routingConfig, undefined, v3GasModel)
1238
+ .then((result) => {
1239
+ metric.putMetric(`SwapRouteFromCache_V3_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1240
+ return result;
1241
+ }));
1242
+ }
1243
+ }
1244
+ if (v2Routes.length > 0) {
1245
+ const v2RoutesFromCache = v2Routes.map((cachedRoute) => cachedRoute.route);
1246
+ metric.putMetric('SwapRouteFromCache_V2_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1247
+ const beforeGetQuotes = Date.now();
1248
+ quotePromises.push(this.v2Quoter
1249
+ .refreshRoutesThenGetQuotes(fewCachedRoutes.currencyIn.wrapped, fewCachedRoutes.currencyOut.wrapped, v2RoutesFromCache, amounts, percents, quoteCurrency.wrapped, tradeType, routingConfig, gasPriceWei)
1250
+ .then((result) => {
1251
+ metric.putMetric(`SwapRouteFromCache_V2_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1252
+ return result;
1253
+ }));
1254
+ }
1255
+ if (ringFewV2Routes.length > 0) {
1256
+ const ringFewV2RoutesFromCache = ringFewV2Routes.map((cachedRoute) => cachedRoute.route);
1257
+ metric.putMetric('SwapRouteFromCache_RingFewV2_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1258
+ const beforeGetQuotes = Date.now();
1259
+ quotePromises.push(this.ringFewV2Quoter
1260
+ .refreshRoutesThenGetQuotes(fewCachedRoutes.currencyIn.wrapped, fewCachedRoutes.currencyOut.wrapped, ringFewV2RoutesFromCache, fewAmounts, fewPercents, fewQuoteToken.wrapped, tradeType, routingConfig, gasPriceWei)
1261
+ .then((result) => {
1262
+ metric.putMetric(`SwapRouteFromCache_RingFewV2_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1263
+ return result;
1264
+ }));
1265
+ }
1266
+ if (!fotInDirectSwap) {
1267
+ if (mixedRoutes.length > 0) {
1268
+ const mixedRoutesFromCache = mixedRoutes.map((cachedRoute) => cachedRoute.route);
1269
+ metric.putMetric('SwapRouteFromCache_Mixed_GetQuotes_Request', 1, MetricLoggerUnit.Count);
1270
+ const beforeGetQuotes = Date.now();
1271
+ quotePromises.push(this.mixedQuoter
1272
+ .getQuotes(mixedRoutesFromCache, amounts, percents, quoteCurrency.wrapped, tradeType, routingConfig, undefined, mixedRouteGasModel)
1273
+ .then((result) => {
1274
+ metric.putMetric(`SwapRouteFromCache_Mixed_GetQuotes_Load`, Date.now() - beforeGetQuotes, MetricLoggerUnit.Milliseconds);
1275
+ return result;
1276
+ }));
1277
+ }
1278
+ }
1279
+ const getQuotesResults = await Promise.all(quotePromises);
1280
+ const allRoutesWithValidQuotes = _.flatMap(getQuotesResults, (quoteResult) => quoteResult.routesWithValidQuotes);
1281
+ return getBestSwapRoute(amount, percents, allRoutesWithValidQuotes, tradeType, this.chainId, routingConfig, this.portionProvider, v2GasModel, v3GasModel, v4GasModel, swapConfig, providerConfig);
1282
+ }
1283
+ async getSwapRouteFromChain(amount, fewAmount, currencyIn, fewTokenIn, currencyOut, fewTokenOut, protocols, quoteCurrency, fewQuoteToken, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, ringFewV2GasModel, swapConfig, providerConfig) {
1284
+ var _a, _c, _d, _e, _f, _g, _h, _j, _k, _l;
1285
+ const tokenPairProperties = await this.tokenPropertiesProvider.getTokensProperties([currencyIn, currencyOut], providerConfig);
1286
+ if (!swapConfig) {
1287
+ //
1288
+ }
1289
+ // const fewTokenPairProperties =
1290
+ // await this.tokenPropertiesProvider.getTokensProperties(
1291
+ // [fewTokenIn, fewTokenOut],
1292
+ // providerConfig
1293
+ // );
1294
+ const sellTokenIsFot = (_d = (_c = (_a = tokenPairProperties[getAddressLowerCase(currencyIn)]) === null || _a === void 0 ? void 0 : _a.tokenFeeResult) === null || _c === void 0 ? void 0 : _c.sellFeeBps) === null || _d === void 0 ? void 0 : _d.gt(0);
1295
+ const buyTokenIsFot = (_g = (_f = (_e = tokenPairProperties[getAddressLowerCase(currencyOut)]) === null || _e === void 0 ? void 0 : _e.tokenFeeResult) === null || _f === void 0 ? void 0 : _f.buyFeeBps) === null || _g === void 0 ? void 0 : _g.gt(0);
1296
+ const fotInDirectSwap = sellTokenIsFot || buyTokenIsFot;
1297
+ // const sellTokenIsFewFot =
1298
+ // fewTokenPairProperties[
1299
+ // getAddressLowerCase(fewTokenIn)
1300
+ // ]?.tokenFeeResult?.sellFeeBps?.gt(0);
1301
+ // const buyTokenIsFewFot =
1302
+ // fewTokenPairProperties[
1303
+ // getAddressLowerCase(fewTokenOut)
1304
+ // ]?.tokenFeeResult?.buyFeeBps?.gt(0);
1305
+ // const fewFotInDirectSwap = sellTokenIsFewFot || buyTokenIsFewFot;
1306
+ // Generate our distribution of amounts, i.e. fractions of the input amount.
1307
+ // We will get quotes for fractions of the input amount for different routes, then
1308
+ // combine to generate split routes.
1309
+ const [percents, amounts] = this.getAmountDistribution(amount, routingConfig);
1310
+ const [fewPercents, fewAmounts] = this.getAmountDistribution(fewAmount, routingConfig);
1311
+ const noProtocolsSpecified = protocols.length === 0;
1312
+ const v4ProtocolSpecified = protocols.includes(Protocol.V4);
1313
+ const v3ProtocolSpecified = protocols.includes(Protocol.V3);
1314
+ const v2ProtocolSpecified = protocols.includes(Protocol.V2);
1315
+ const ringFewV2ProtocolSpecified = protocols.includes(Protocol.FEWV2);
1316
+ const v2SupportedInChain = (_h = this.v2Supported) === null || _h === void 0 ? void 0 : _h.includes(this.chainId);
1317
+ const ringFewV2SupportedInChain = (_j = this.ringFewV2Supported) === null || _j === void 0 ? void 0 : _j.includes(this.chainId);
1318
+ const v4SupportedInChain = (_k = this.v4Supported) === null || _k === void 0 ? void 0 : _k.includes(this.chainId);
1319
+ const shouldQueryMixedProtocol = protocols.includes(Protocol.MIXED) ||
1320
+ (noProtocolsSpecified && v2SupportedInChain && ringFewV2SupportedInChain && v4SupportedInChain);
1321
+ // const shouldQueryRingFewV2Protocol =
1322
+ // protocols.includes(Protocol.FEWV2) ||
1323
+ // (noProtocolsSpecified && ringFewV2SupportedInChain);
1324
+ const mixedProtocolAllowed = ((_l = this.mixedSupported) === null || _l === void 0 ? void 0 : _l.includes(this.chainId)) &&
1325
+ tradeType === TradeType.EXACT_INPUT;
1326
+ const beforeGetCandidates = Date.now();
1327
+ let v4CandidatePoolsPromise = Promise.resolve(undefined);
1328
+ // we are explicitly requiring people to specify v4 for now
1329
+ if (v4SupportedInChain && (v4ProtocolSpecified || noProtocolsSpecified)) {
1330
+ // if (v4ProtocolSpecified || noProtocolsSpecified) {
1331
+ v4CandidatePoolsPromise = getV4CandidatePools({
1332
+ currencyIn: currencyIn,
1333
+ currencyOut: currencyOut,
1334
+ tokenProvider: this.tokenProvider,
1335
+ blockedTokenListProvider: this.blockedTokenListProvider,
1336
+ poolProvider: this.v4PoolProvider,
1337
+ routeType: tradeType,
1338
+ subgraphProvider: this.v4SubgraphProvider,
1339
+ routingConfig,
1340
+ chainId: this.chainId,
1341
+ v4PoolParams: this.v4PoolParams,
1342
+ }).then((candidatePools) => {
1343
+ metric.putMetric('GetV4CandidatePools', Date.now() - beforeGetCandidates, MetricLoggerUnit.Milliseconds);
1344
+ return candidatePools;
1345
+ });
1346
+ }
1347
+ let v3CandidatePoolsPromise = Promise.resolve(undefined);
1348
+ if (!fotInDirectSwap) {
1349
+ if (v3ProtocolSpecified || noProtocolsSpecified) {
1350
+ const tokenIn = currencyIn.wrapped;
1351
+ const tokenOut = currencyOut.wrapped;
1352
+ v3CandidatePoolsPromise = getV3CandidatePools({
1353
+ tokenIn,
1354
+ tokenOut,
1355
+ tokenProvider: this.tokenProvider,
1356
+ blockedTokenListProvider: this.blockedTokenListProvider,
1357
+ poolProvider: this.v3PoolProvider,
1358
+ routeType: tradeType,
1359
+ subgraphProvider: this.v3SubgraphProvider,
1360
+ routingConfig,
1361
+ chainId: this.chainId,
1362
+ }).then((candidatePools) => {
1363
+ metric.putMetric('GetV3CandidatePools', Date.now() - beforeGetCandidates, MetricLoggerUnit.Milliseconds);
1364
+ return candidatePools;
1365
+ });
1366
+ }
1367
+ }
1368
+ let v2CandidatePoolsPromise = Promise.resolve(undefined);
1369
+ if (v2SupportedInChain && (v2ProtocolSpecified || noProtocolsSpecified)) {
1370
+ const tokenIn = currencyIn.wrapped;
1371
+ const tokenOut = currencyOut.wrapped;
1372
+ // Fetch all the pools that we will consider routing via. There are thousands
1373
+ // of pools, so we filter them to a set of candidate pools that we expect will
1374
+ // result in good prices.
1375
+ v2CandidatePoolsPromise = getV2CandidatePools({
1376
+ tokenIn,
1377
+ tokenOut,
1378
+ tokenProvider: this.tokenProvider,
1379
+ blockedTokenListProvider: this.blockedTokenListProvider,
1380
+ poolProvider: this.v2PoolProvider,
1381
+ routeType: tradeType,
1382
+ subgraphProvider: this.v2SubgraphProvider,
1383
+ routingConfig,
1384
+ chainId: this.chainId,
1385
+ }).then((candidatePools) => {
1386
+ metric.putMetric('GetV2CandidatePools', Date.now() - beforeGetCandidates, MetricLoggerUnit.Milliseconds);
1387
+ return candidatePools;
1388
+ });
1389
+ }
1390
+ let ringFewV2CandidatePoolsPromise = Promise.resolve(undefined);
1391
+ if (ringFewV2SupportedInChain && (ringFewV2ProtocolSpecified || noProtocolsSpecified)) {
1392
+ const tokenIn = fewTokenIn;
1393
+ const tokenOut = fewTokenOut;
1394
+ ringFewV2CandidatePoolsPromise = getRingFewV2CandidatePools({
1395
+ tokenIn,
1396
+ tokenOut,
1397
+ tokenProvider: this.tokenProvider,
1398
+ blockedTokenListProvider: this.blockedTokenListProvider,
1399
+ poolProvider: this.ringFewV2PoolProvider,
1400
+ routeType: tradeType,
1401
+ subgraphProvider: this.ringFewV2SubgraphProvider,
1402
+ routingConfig,
1403
+ chainId: this.chainId,
1404
+ }).then((candidatePools) => {
1405
+ metric.putMetric('GetRingFewV2CandidatePools', Date.now() - beforeGetCandidates, MetricLoggerUnit.Milliseconds);
1406
+ return candidatePools;
1407
+ });
1408
+ }
1409
+ const quotePromises = [];
1410
+ // for v4, for now we explicitly require people to specify
1411
+ if (v4SupportedInChain && v4ProtocolSpecified) {
1412
+ log.info({ protocols, tradeType }, 'Routing across V4');
1413
+ metric.putMetric('SwapRouteFromChain_V4_GetRoutesThenQuotes_Request', 1, MetricLoggerUnit.Count);
1414
+ const beforeGetRoutesThenQuotes = Date.now();
1415
+ quotePromises.push(v4CandidatePoolsPromise.then((v4CandidatePools) => this.v4Quoter
1416
+ .getRoutesThenQuotes(currencyIn, currencyOut, amount, amounts, percents, quoteCurrency, v4CandidatePools, tradeType, routingConfig, v4GasModel)
1417
+ .then((result) => {
1418
+ metric.putMetric(`SwapRouteFromChain_V4_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, MetricLoggerUnit.Milliseconds);
1419
+ return result;
1420
+ })));
1421
+ }
1422
+ if (!fotInDirectSwap) {
1423
+ // Maybe Quote V3 - if V3 is specified, or no protocol is specified
1424
+ if (v3ProtocolSpecified || noProtocolsSpecified) {
1425
+ log.info({ protocols, tradeType }, 'Routing across V3');
1426
+ metric.putMetric('SwapRouteFromChain_V3_GetRoutesThenQuotes_Request', 1, MetricLoggerUnit.Count);
1427
+ const beforeGetRoutesThenQuotes = Date.now();
1428
+ const tokenIn = currencyIn.wrapped;
1429
+ const tokenOut = currencyOut.wrapped;
1430
+ quotePromises.push(v3CandidatePoolsPromise.then((v3CandidatePools) => this.v3Quoter
1431
+ .getRoutesThenQuotes(tokenIn, tokenOut, amount, amounts, percents, quoteCurrency.wrapped, v3CandidatePools, tradeType, routingConfig, v3GasModel)
1432
+ .then((result) => {
1433
+ metric.putMetric(`SwapRouteFromChain_V3_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, MetricLoggerUnit.Milliseconds);
1434
+ return result;
1435
+ })));
1436
+ }
1437
+ }
1438
+ // Maybe Quote V2 - if V2 is specified, or no protocol is specified AND v2 is supported in this chain
1439
+ if (v2SupportedInChain && (v2ProtocolSpecified || noProtocolsSpecified)) {
1440
+ log.info({ protocols, tradeType }, 'Routing across V2');
1441
+ metric.putMetric('SwapRouteFromChain_V2_GetRoutesThenQuotes_Request', 1, MetricLoggerUnit.Count);
1442
+ const beforeGetRoutesThenQuotes = Date.now();
1443
+ const tokenIn = currencyIn.wrapped;
1444
+ const tokenOut = currencyOut.wrapped;
1445
+ quotePromises.push(v2CandidatePoolsPromise.then((v2CandidatePools) => this.v2Quoter
1446
+ .getRoutesThenQuotes(tokenIn, tokenOut, amount, amounts, percents, quoteCurrency.wrapped, v2CandidatePools, tradeType, routingConfig, v2GasModel, gasPriceWei)
1447
+ .then((result) => {
1448
+ metric.putMetric(`SwapRouteFromChain_V2_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, MetricLoggerUnit.Milliseconds);
1449
+ return result;
1450
+ })));
1451
+ }
1452
+ // Maybe Quote RingFewV2 - if RingFewV2 is specified, or no protocol is specified AND ringFewV2 is supported in this chain
1453
+ if (ringFewV2SupportedInChain && (ringFewV2ProtocolSpecified || noProtocolsSpecified)) {
1454
+ log.info({ protocols, tradeType }, 'Routing across RingFewV2');
1455
+ metric.putMetric('SwapRouteFromChain_RingFewV2_GetRoutesThenQuotes_Request', 1, MetricLoggerUnit.Count);
1456
+ const beforeGetRoutesThenQuotes = Date.now();
1457
+ const tokenIn = fewTokenIn;
1458
+ const tokenOut = fewTokenOut;
1459
+ quotePromises.push(ringFewV2CandidatePoolsPromise.then((ringFewV2CandidatePools) => this.ringFewV2Quoter
1460
+ .getRoutesThenQuotes(tokenIn, tokenOut, fewAmount, fewAmounts, fewPercents, fewQuoteToken.wrapped, ringFewV2CandidatePools, tradeType, routingConfig, ringFewV2GasModel, gasPriceWei)
1461
+ .then((result) => {
1462
+ metric.putMetric(`SwapRouteFromChain_RingFewV2_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, MetricLoggerUnit.Milliseconds);
1463
+ return result;
1464
+ })));
1465
+ }
1466
+ if (!fotInDirectSwap) {
1467
+ // Maybe Quote mixed routes
1468
+ // if MixedProtocol is specified or no protocol is specified and v2 is supported AND tradeType is ExactIn
1469
+ // AND is Mainnet or Gorli
1470
+ // Also make sure there are at least 2 protocols provided besides MIXED, before entering mixed quoter
1471
+ if (shouldQueryMixedProtocol &&
1472
+ mixedProtocolAllowed &&
1473
+ protocols.filter((protocol) => protocol !== Protocol.MIXED).length >= 2) {
1474
+ log.info({ protocols, tradeType }, 'Routing across MixedRoutes');
1475
+ metric.putMetric('SwapRouteFromChain_Mixed_GetRoutesThenQuotes_Request', 1, MetricLoggerUnit.Count);
1476
+ const beforeGetRoutesThenQuotes = Date.now();
1477
+ quotePromises.push(Promise.all([
1478
+ v4CandidatePoolsPromise,
1479
+ v3CandidatePoolsPromise,
1480
+ v2CandidatePoolsPromise,
1481
+ ringFewV2CandidatePoolsPromise,
1482
+ ]).then(async ([v4CandidatePools, v3CandidatePools, v2CandidatePools, ringFewV2CandidatePools]) => {
1483
+ const tokenIn = currencyIn.wrapped;
1484
+ const tokenOut = currencyOut.wrapped;
1485
+ const crossLiquidityPools = await getMixedCrossLiquidityCandidatePools({
1486
+ tokenIn,
1487
+ tokenOut,
1488
+ blockNumber: routingConfig.blockNumber,
1489
+ v2SubgraphProvider: this.v2SubgraphProvider,
1490
+ v3SubgraphProvider: this.v3SubgraphProvider,
1491
+ v2Candidates: v2CandidatePools,
1492
+ v3Candidates: v3CandidatePools,
1493
+ v4Candidates: v4CandidatePools,
1494
+ });
1495
+ return this.mixedQuoter
1496
+ .getRoutesThenQuotes(tokenIn, tokenOut, amount, amounts, percents, quoteCurrency.wrapped, [
1497
+ v4CandidatePools,
1498
+ v3CandidatePools,
1499
+ v2CandidatePools,
1500
+ ringFewV2CandidatePools,
1501
+ crossLiquidityPools,
1502
+ ], tradeType, routingConfig, mixedRouteGasModel)
1503
+ .then((result) => {
1504
+ metric.putMetric(`SwapRouteFromChain_Mixed_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, MetricLoggerUnit.Milliseconds);
1505
+ return result;
1506
+ });
1507
+ }));
1508
+ }
1509
+ }
1510
+ const getQuotesResults = await Promise.all(quotePromises);
1511
+ const allRoutesWithValidQuotes = [];
1512
+ const allCandidatePools = [];
1513
+ getQuotesResults.forEach((getQuoteResult) => {
1514
+ allRoutesWithValidQuotes.push(...getQuoteResult.routesWithValidQuotes);
1515
+ if (getQuoteResult.candidatePools) {
1516
+ allCandidatePools.push(getQuoteResult.candidatePools);
1517
+ }
1518
+ });
1519
+ if (allRoutesWithValidQuotes.length === 0) {
1520
+ log.info({ allRoutesWithValidQuotes }, 'Received no valid quotes');
1521
+ return null;
1522
+ }
1523
+ return allRoutesWithValidQuotes;
1524
+ /*
1525
+ // Given all the quotes for all the amounts for all the routes, find the best combination.
1526
+ const bestSwapRoute = await getBestSwapRoute(
1527
+ amount,
1528
+ percents,
1529
+ allRoutesWithValidQuotes,
1530
+ tradeType,
1531
+ this.chainId,
1532
+ routingConfig,
1533
+ this.portionProvider,
1534
+ v2GasModel,
1535
+ v3GasModel,
1536
+ v4GasModel,
1537
+ swapConfig,
1538
+ providerConfig
1539
+ );
1540
+
1541
+ if (bestSwapRoute) {
1542
+ this.emitPoolSelectionMetrics(
1543
+ bestSwapRoute,
1544
+ allCandidatePools,
1545
+ currencyIn,
1546
+ currencyOut
1547
+ );
1548
+ }
1549
+
1550
+ return bestSwapRoute;
1551
+ */
1552
+ }
1553
+ // for uniswap fewToken
1554
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1555
+ async getUniswapFewTokenSwapRouteFromChain(amount, fewAmount, currencyIn, fewTokenIn, currencyOut, fewTokenOut, protocols, _quoteCurrency, fewQuoteToken, tradeType, routingConfig,
1556
+ // v3GasModel: IGasModel<V3RouteWithValidQuote>,
1557
+ fewV3GasModel,
1558
+ // v4GasModel: IGasModel<V4RouteWithValidQuote>,
1559
+ fewV4GasModel, _mixedRouteGasModel, gasPriceWei, _v2GasModel, fewV2GasModel,
1560
+ // ringFewV2GasModel?: IGasModel<RingFewV2RouteWithValidQuote>,
1561
+ providerConfig) {
1562
+ var _a, _c, _d, _e, _f, _g, _h, _j, _k, _l;
1563
+ const tokenPairProperties = await this.tokenPropertiesProvider.getTokensProperties([currencyIn, currencyOut], providerConfig);
1564
+ const sellTokenIsFot = (_d = (_c = (_a = tokenPairProperties[getAddressLowerCase(currencyIn)]) === null || _a === void 0 ? void 0 : _a.tokenFeeResult) === null || _c === void 0 ? void 0 : _c.sellFeeBps) === null || _d === void 0 ? void 0 : _d.gt(0);
1565
+ const buyTokenIsFot = (_g = (_f = (_e = tokenPairProperties[getAddressLowerCase(currencyOut)]) === null || _e === void 0 ? void 0 : _e.tokenFeeResult) === null || _f === void 0 ? void 0 : _f.buyFeeBps) === null || _g === void 0 ? void 0 : _g.gt(0);
1566
+ const fotInDirectSwap = sellTokenIsFot || buyTokenIsFot;
1567
+ // Generate our distribution of amounts, i.e. fractions of the input amount.
1568
+ // We will get quotes for fractions of the input amount for different routes, then
1569
+ // combine to generate split routes.
1570
+ const [_amounts] = this.getAmountDistribution(amount, routingConfig);
1571
+ const [fewPercents, fewAmounts] = this.getAmountDistribution(fewAmount, routingConfig);
1572
+ // const tokenIn = fewTokenIn;
1573
+ // const tokenOut = fewTokenOut;
1574
+ const noProtocolsSpecified = protocols.length === 0;
1575
+ const v4ProtocolSpecified = protocols.includes(Protocol.V4);
1576
+ const v3ProtocolSpecified = protocols.includes(Protocol.V3);
1577
+ const v2ProtocolSpecified = protocols.includes(Protocol.V2);
1578
+ //@ts-ignore
1579
+ const _ringFewV2ProtocolSpecified = protocols.includes(Protocol.FEWV2);
1580
+ const v2SupportedInChain = (_h = this.v2Supported) === null || _h === void 0 ? void 0 : _h.includes(this.chainId);
1581
+ const ringFewV2SupportedInChain = (_j = this.ringFewV2Supported) === null || _j === void 0 ? void 0 : _j.includes(this.chainId);
1582
+ const v4SupportedInChain = (_k = this.v4Supported) === null || _k === void 0 ? void 0 : _k.includes(this.chainId);
1583
+ //@ts-ignore
1584
+ const _shouldQueryMixedProtocol = protocols.includes(Protocol.MIXED) ||
1585
+ (noProtocolsSpecified && v2SupportedInChain && ringFewV2SupportedInChain && v4SupportedInChain);
1586
+ //@ts-ignore
1587
+ const _mixedProtocolAllowed = ((_l = this.mixedSupported) === null || _l === void 0 ? void 0 : _l.includes(this.chainId)) &&
1588
+ tradeType === TradeType.EXACT_INPUT;
1589
+ const beforeGetCandidates = Date.now();
1590
+ let v4CandidatePoolsPromise = Promise.resolve(undefined);
1591
+ // we are explicitly requiring people to specify v4 for now
1592
+ if (v4SupportedInChain && (v4ProtocolSpecified || noProtocolsSpecified)) {
1593
+ // if (v4ProtocolSpecified || noProtocolsSpecified) {
1594
+ v4CandidatePoolsPromise = getUniswapV4FewTokenCandidatePools({
1595
+ currencyIn: fewTokenIn,
1596
+ currencyOut: fewTokenOut,
1597
+ tokenProvider: this.tokenProvider,
1598
+ blockedTokenListProvider: this.blockedTokenListProvider,
1599
+ poolProvider: this.v4PoolProvider,
1600
+ routeType: tradeType,
1601
+ subgraphProvider: this.v4SubgraphProvider,
1602
+ routingConfig,
1603
+ chainId: this.chainId,
1604
+ v4PoolParams: this.v4PoolParams,
1605
+ }).then((candidatePools) => {
1606
+ metric.putMetric('GetV4CandidatePools', Date.now() - beforeGetCandidates, MetricLoggerUnit.Milliseconds);
1607
+ return candidatePools;
1608
+ });
1609
+ }
1610
+ let v3CandidatePoolsPromise = Promise.resolve(undefined);
1611
+ if (!fotInDirectSwap) {
1612
+ if (v3ProtocolSpecified || noProtocolsSpecified) {
1613
+ v3CandidatePoolsPromise = getUniswapFewTokenV3CandidatePools({
1614
+ tokenIn: fewTokenIn,
1615
+ tokenOut: fewTokenOut,
1616
+ tokenProvider: this.tokenProvider,
1617
+ blockedTokenListProvider: this.blockedTokenListProvider,
1618
+ poolProvider: this.v3PoolProvider,
1619
+ routeType: tradeType,
1620
+ subgraphProvider: this.v3SubgraphProvider,
1621
+ routingConfig,
1622
+ chainId: this.chainId,
1623
+ }).then((candidatePools) => {
1624
+ metric.putMetric('GetV3CandidatePools', Date.now() - beforeGetCandidates, MetricLoggerUnit.Milliseconds);
1625
+ return candidatePools;
1626
+ });
1627
+ }
1628
+ }
1629
+ let v2CandidatePoolsPromise = Promise.resolve(undefined);
1630
+ if (v2SupportedInChain && (v2ProtocolSpecified || noProtocolsSpecified)) {
1631
+ // Fetch all the pools that we will consider routing via. There are thousands
1632
+ // of pools, so we filter them to a set of candidate pools that we expect will
1633
+ // result in good prices.
1634
+ v2CandidatePoolsPromise = getUniswapFewTokenV2CandidatePools({
1635
+ tokenIn: fewTokenIn,
1636
+ tokenOut: fewTokenOut,
1637
+ tokenProvider: this.tokenProvider,
1638
+ blockedTokenListProvider: this.blockedTokenListProvider,
1639
+ poolProvider: this.v2PoolProvider,
1640
+ routeType: tradeType,
1641
+ subgraphProvider: this.v2SubgraphProvider,
1642
+ routingConfig,
1643
+ chainId: this.chainId,
1644
+ }).then((candidatePools) => {
1645
+ metric.putMetric('getUniswapFewTokenV2CandidatePools', Date.now() - beforeGetCandidates, MetricLoggerUnit.Milliseconds);
1646
+ return candidatePools;
1647
+ });
1648
+ }
1649
+ // FEWV2 这里查询的是 origin token 的 pool
1650
+ // let ringFewV2CandidatePoolsPromise: Promise<RingFewV2CandidatePools | undefined> =
1651
+ // Promise.resolve(undefined);
1652
+ // if (ringFewV2SupportedInChain && (ringFewV2ProtocolSpecified || noProtocolsSpecified)) {
1653
+ // const tokenIn = currencyIn.wrapped;
1654
+ // const tokenOut = currencyOut.wrapped;
1655
+ // ringFewV2CandidatePoolsPromise = getRingFewV2CandidatePools({
1656
+ // tokenIn,
1657
+ // tokenOut,
1658
+ // tokenProvider: this.tokenProvider,
1659
+ // blockedTokenListProvider: this.blockedTokenListProvider,
1660
+ // poolProvider: this.ringFewV2PoolProvider,
1661
+ // routeType: tradeType,
1662
+ // subgraphProvider: this.ringFewV2SubgraphProvider,
1663
+ // routingConfig,
1664
+ // chainId: this.chainId,
1665
+ // }).then((candidatePools) => {
1666
+ // metric.putMetric(
1667
+ // 'GetRingFewV2CandidatePools',
1668
+ // Date.now() - beforeGetCandidates,
1669
+ // MetricLoggerUnit.Milliseconds
1670
+ // );
1671
+ // return candidatePools;
1672
+ // });
1673
+ // }
1674
+ const quotePromises = [];
1675
+ // for v4, for now we explicitly require people to specify
1676
+ if (v4SupportedInChain && v4ProtocolSpecified) {
1677
+ log.info({ protocols, tradeType }, 'Routing across V4');
1678
+ metric.putMetric('SwapRouteFromChain_V4_GetRoutesThenQuotes_Request', 1, MetricLoggerUnit.Count);
1679
+ const beforeGetRoutesThenQuotes = Date.now();
1680
+ quotePromises.push(v4CandidatePoolsPromise.then((v4CandidatePools) => this.uniswapFewV4Quoter
1681
+ .getRoutesThenQuotes(fewTokenIn, fewTokenOut, fewAmount, fewAmounts, fewPercents, fewQuoteToken, v4CandidatePools, tradeType, routingConfig, fewV4GasModel)
1682
+ .then((result) => {
1683
+ metric.putMetric(`SwapRouteFromChain_V4_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, MetricLoggerUnit.Milliseconds);
1684
+ return result;
1685
+ })));
1686
+ }
1687
+ if (!fotInDirectSwap) {
1688
+ // Maybe Quote V3 - if V3 is specified, or no protocol is specified
1689
+ if (v3ProtocolSpecified || noProtocolsSpecified) {
1690
+ log.info({ protocols, tradeType }, 'Routing across V3');
1691
+ metric.putMetric('SwapRouteFromChain_V3_GetRoutesThenQuotes_Request', 1, MetricLoggerUnit.Count);
1692
+ const beforeGetRoutesThenQuotes = Date.now();
1693
+ quotePromises.push(v3CandidatePoolsPromise.then((v3CandidatePools) => this.uniswapFewV3Quoter
1694
+ .getRoutesThenQuotes(fewTokenIn, fewTokenOut, fewAmount, fewAmounts, fewPercents, fewQuoteToken, v3CandidatePools, tradeType, routingConfig, fewV3GasModel)
1695
+ .then((result) => {
1696
+ metric.putMetric(`SwapRouteFromChain_V3_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, MetricLoggerUnit.Milliseconds);
1697
+ return result;
1698
+ })));
1699
+ }
1700
+ }
1701
+ // Maybe Quote V2 - if V2 is specified, or no protocol is specified AND v2 is supported in this chain
1702
+ if (v2SupportedInChain && (v2ProtocolSpecified || noProtocolsSpecified)) {
1703
+ log.info({ protocols, tradeType }, 'Routing across V2');
1704
+ metric.putMetric('SwapRouteFromChain_V2_GetRoutesThenQuotes_Request', 1, MetricLoggerUnit.Count);
1705
+ const beforeGetRoutesThenQuotes = Date.now();
1706
+ quotePromises.push(v2CandidatePoolsPromise.then((v2CandidatePools) => this.v2Quoter
1707
+ .getRoutesThenQuotes(fewTokenIn, fewTokenOut, fewAmount, fewAmounts, fewPercents, fewQuoteToken, v2CandidatePools, tradeType, routingConfig, fewV2GasModel, gasPriceWei)
1708
+ .then((result) => {
1709
+ metric.putMetric(`SwapRouteFromChain_V2_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, MetricLoggerUnit.Milliseconds);
1710
+ return result;
1711
+ })));
1712
+ }
1713
+ // Maybe Quote RingFewV2 - if RingFewV2 is specified, or no protocol is specified AND ringFewV2 is supported in this chain
1714
+ // if (ringFewV2SupportedInChain && (ringFewV2ProtocolSpecified || noProtocolsSpecified)) {
1715
+ // log.info({ protocols, tradeType }, 'Routing across RingFewV2');
1716
+ // metric.putMetric(
1717
+ // 'SwapRouteFromChain_RingFewV2_GetRoutesThenQuotes_Request',
1718
+ // 1,
1719
+ // MetricLoggerUnit.Count
1720
+ // );
1721
+ // const beforeGetRoutesThenQuotes = Date.now();
1722
+ // const tokenIn = currencyIn.wrapped;
1723
+ // const tokenOut = currencyOut.wrapped;
1724
+ // quotePromises.push(
1725
+ // ringFewV2CandidatePoolsPromise.then((ringFewV2CandidatePools) =>
1726
+ // this.ringFewV2Quoter
1727
+ // .getRoutesThenQuotes(
1728
+ // tokenIn,
1729
+ // tokenOut,
1730
+ // amount,
1731
+ // amounts,
1732
+ // percents,
1733
+ // quoteCurrency.wrapped,
1734
+ // ringFewV2CandidatePools!,
1735
+ // tradeType,
1736
+ // routingConfig,
1737
+ // v2GasModel,
1738
+ // gasPriceWei
1739
+ // )
1740
+ // .then((result) => {
1741
+ // metric.putMetric(
1742
+ // `SwapRouteFromChain_RingFewV2_GetRoutesThenQuotes_Load`,
1743
+ // Date.now() - beforeGetRoutesThenQuotes,
1744
+ // MetricLoggerUnit.Milliseconds
1745
+ // );
1746
+ // return result;
1747
+ // })
1748
+ // )
1749
+ // );
1750
+ // }
1751
+ // if (!fotInDirectSwap) {
1752
+ // // Maybe Quote mixed routes
1753
+ // // if MixedProtocol is specified or no protocol is specified and v2 is supported AND tradeType is ExactIn
1754
+ // // AND is Mainnet or Gorli
1755
+ // // Also make sure there are at least 2 protocols provided besides MIXED, before entering mixed quoter
1756
+ // if (
1757
+ // shouldQueryMixedProtocol &&
1758
+ // mixedProtocolAllowed &&
1759
+ // protocols.filter((protocol) => protocol !== Protocol.MIXED).length >= 2
1760
+ // ) {
1761
+ // log.info({ protocols, tradeType }, 'Routing across MixedRoutes');
1762
+ // metric.putMetric(
1763
+ // 'SwapRouteFromChain_Mixed_GetRoutesThenQuotes_Request',
1764
+ // 1,
1765
+ // MetricLoggerUnit.Count
1766
+ // );
1767
+ // const beforeGetRoutesThenQuotes = Date.now();
1768
+ // quotePromises.push(
1769
+ // Promise.all([
1770
+ // v4CandidatePoolsPromise,
1771
+ // v3CandidatePoolsPromise,
1772
+ // v2CandidatePoolsPromise,
1773
+ // ringFewV2CandidatePoolsPromise,
1774
+ // ]).then(
1775
+ // async ([v4CandidatePools, v3CandidatePools, v2CandidatePools, ringFewV2CandidatePools]) => {
1776
+ // const tokenIn = currencyIn.wrapped;
1777
+ // const tokenOut = currencyOut.wrapped;
1778
+ // const crossLiquidityPools =
1779
+ // await getMixedCrossLiquidityCandidatePools({
1780
+ // tokenIn,
1781
+ // tokenOut,
1782
+ // blockNumber: routingConfig.blockNumber,
1783
+ // v2SubgraphProvider: this.v2SubgraphProvider,
1784
+ // v3SubgraphProvider: this.v3SubgraphProvider,
1785
+ // v2Candidates: v2CandidatePools,
1786
+ // v3Candidates: v3CandidatePools,
1787
+ // v4Candidates: v4CandidatePools,
1788
+ // });
1789
+ // return this.mixedQuoter
1790
+ // .getRoutesThenQuotes(
1791
+ // tokenIn,
1792
+ // tokenOut,
1793
+ // amount,
1794
+ // amounts,
1795
+ // percents,
1796
+ // quoteCurrency.wrapped,
1797
+ // [
1798
+ // v4CandidatePools,
1799
+ // v3CandidatePools,
1800
+ // v2CandidatePools,
1801
+ // ringFewV2CandidatePools,
1802
+ // crossLiquidityPools,
1803
+ // ],
1804
+ // tradeType,
1805
+ // routingConfig,
1806
+ // mixedRouteGasModel
1807
+ // )
1808
+ // .then((result) => {
1809
+ // metric.putMetric(
1810
+ // `SwapRouteFromChain_Mixed_GetRoutesThenQuotes_Load`,
1811
+ // Date.now() - beforeGetRoutesThenQuotes,
1812
+ // MetricLoggerUnit.Milliseconds
1813
+ // );
1814
+ // return result;
1815
+ // });
1816
+ // }
1817
+ // )
1818
+ // );
1819
+ // }
1820
+ // }
1821
+ const getQuotesResults = await Promise.all(quotePromises);
1822
+ const allRoutesWithValidQuotes = [];
1823
+ const allCandidatePools = [];
1824
+ getQuotesResults.forEach((getQuoteResult) => {
1825
+ allRoutesWithValidQuotes.push(...getQuoteResult.routesWithValidQuotes);
1826
+ if (getQuoteResult.candidatePools) {
1827
+ allCandidatePools.push(getQuoteResult.candidatePools);
1828
+ }
1829
+ });
1830
+ if (allRoutesWithValidQuotes.length === 0) {
1831
+ log.info({ allRoutesWithValidQuotes }, 'Received no valid fewtokens quotes');
1832
+ return null;
1833
+ }
1834
+ return allRoutesWithValidQuotes;
1835
+ /*
1836
+ // Given all the quotes for all the amounts for all the routes, find the best combination.
1837
+ const bestSwapRoute = await getBestSwapRoute(
1838
+ amount,
1839
+ percents,
1840
+ allRoutesWithValidQuotes,
1841
+ tradeType,
1842
+ this.chainId,
1843
+ routingConfig,
1844
+ this.portionProvider,
1845
+ fewV2GasModel,
1846
+ fewV3GasModel,
1847
+ fewV4GasModel,
1848
+ swapConfig,
1849
+ providerConfig
1850
+ );
1851
+
1852
+ if (bestSwapRoute) {
1853
+ this.emitPoolSelectionMetrics(
1854
+ bestSwapRoute,
1855
+ allCandidatePools,
1856
+ currencyIn,
1857
+ currencyOut
1858
+ );
1859
+ }
1860
+
1861
+ return bestSwapRoute;
1862
+ */
1863
+ }
1864
+ tradeTypeStr(tradeType) {
1865
+ return tradeType === TradeType.EXACT_INPUT ? 'ExactIn' : 'ExactOut';
1866
+ }
1867
+ tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType) {
1868
+ return `${currencyIn.symbol}/${currencyOut.symbol}/${this.tradeTypeStr(tradeType)}/${this.chainId}`;
1869
+ }
1870
+ determineCurrencyInOutFromTradeType(tradeType, amount, quoteCurrency) {
1871
+ if (tradeType === TradeType.EXACT_INPUT) {
1872
+ return {
1873
+ currencyIn: amount.currency,
1874
+ currencyOut: quoteCurrency,
1875
+ };
1876
+ }
1877
+ else {
1878
+ return {
1879
+ currencyIn: quoteCurrency,
1880
+ currencyOut: amount.currency,
1881
+ };
1882
+ }
1883
+ }
1884
+ async getGasPriceWei(latestBlockNumber, requestBlockNumber) {
1885
+ // Track how long it takes to resolve this async call.
1886
+ const beforeGasTimestamp = Date.now();
1887
+ // Get an estimate of the gas price to use when estimating gas cost of different routes.
1888
+ const { gasPriceWei } = await this.gasPriceProvider.getGasPrice(latestBlockNumber, requestBlockNumber);
1889
+ metric.putMetric('GasPriceLoad', Date.now() - beforeGasTimestamp, MetricLoggerUnit.Milliseconds);
1890
+ return gasPriceWei;
1891
+ }
1892
+ async getGasModels(gasPriceWei, amountToken, quoteToken, providerConfig) {
1893
+ var _a, _c, _d;
1894
+ const beforeGasModel = Date.now();
1895
+ const fewQuoteToken = isFewToken(quoteToken)
1896
+ ? quoteToken
1897
+ : getFewTokenFromOriginalToken(quoteToken, this.chainId);
1898
+ const fewAmountToken = isFewToken(amountToken)
1899
+ ? amountToken
1900
+ : getFewTokenFromOriginalToken(amountToken, this.chainId);
1901
+ const usdPoolPromise = getHighestLiquidityV3USDPool(this.chainId, this.v3PoolProvider, providerConfig);
1902
+ const fewUsdPoolPromise = getHighestLiquidityV3FewTokenUSDPool(this.chainId, this.v3PoolProvider, providerConfig);
1903
+ const nativeCurrency = WRAPPED_NATIVE_CURRENCY[this.chainId];
1904
+ const fewNativeCurrency = FEW_WRAPPED_NATIVE_CURRENCY[this.chainId];
1905
+ const nativeAndQuoteTokenV3PoolPromise = !quoteToken.equals(nativeCurrency)
1906
+ ? getHighestLiquidityV3NativePool(quoteToken, this.v3PoolProvider, providerConfig)
1907
+ : Promise.resolve(null);
1908
+ const nativeAndAmountTokenV3PoolPromise = !amountToken.equals(nativeCurrency)
1909
+ ? getHighestLiquidityV3NativePool(amountToken, this.v3PoolProvider, providerConfig)
1910
+ : Promise.resolve(null);
1911
+ const fewNativeAndQuoteTokenV3PoolPromise = !fewQuoteToken.equals(fewNativeCurrency)
1912
+ ? getHighestLiquidityV3NativeFewTokenPool(fewQuoteToken, this.v3PoolProvider, providerConfig)
1913
+ : Promise.resolve(null);
1914
+ const fewNativeAndAmountTokenV3PoolPromise = !fewAmountToken.equals(fewNativeCurrency)
1915
+ ? getHighestLiquidityV3NativeFewTokenPool(fewAmountToken, this.v3PoolProvider, providerConfig)
1916
+ : Promise.resolve(null);
1917
+ // If a specific gas token is specified in the provider config
1918
+ // fetch the highest liq V3 pool with it and the native currency
1919
+ const nativeAndSpecifiedGasTokenV3PoolPromise = (providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken) &&
1920
+ !(providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken.equals(nativeCurrency))
1921
+ ? getHighestLiquidityV3NativePool(providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken, this.v3PoolProvider, providerConfig)
1922
+ : Promise.resolve(null);
1923
+ // If a specific gas token is specified in the provider config
1924
+ // fetch the highest liq V3 pool with it and the native currency
1925
+ const fewNativeAndSpecifiedGasTokenV3PoolPromise = (providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken) &&
1926
+ !(providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken.equals(fewNativeCurrency))
1927
+ ? getHighestLiquidityV3NativeFewTokenPool(providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken, this.v3PoolProvider, providerConfig)
1928
+ : Promise.resolve(null);
1929
+ const [usdPool, fewUsdPool, nativeAndQuoteTokenV3Pool, fewNativeAndQuoteTokenV3Pool, nativeAndAmountTokenV3Pool, fewNativeAndAmountTokenV3Pool, nativeAndSpecifiedGasTokenV3Pool, fewNativeAndSpecifiedGasTokenV3Pool,] = await Promise.all([
1930
+ usdPoolPromise,
1931
+ fewUsdPoolPromise,
1932
+ nativeAndQuoteTokenV3PoolPromise,
1933
+ fewNativeAndQuoteTokenV3PoolPromise,
1934
+ nativeAndAmountTokenV3PoolPromise,
1935
+ fewNativeAndAmountTokenV3PoolPromise,
1936
+ nativeAndSpecifiedGasTokenV3PoolPromise,
1937
+ fewNativeAndSpecifiedGasTokenV3PoolPromise,
1938
+ ]);
1939
+ const pools = {
1940
+ usdPool: usdPool,
1941
+ nativeAndQuoteTokenV3Pool: nativeAndQuoteTokenV3Pool,
1942
+ nativeAndAmountTokenV3Pool: nativeAndAmountTokenV3Pool,
1943
+ nativeAndSpecifiedGasTokenV3Pool: nativeAndSpecifiedGasTokenV3Pool,
1944
+ };
1945
+ const fewPools = {
1946
+ usdPool: fewUsdPool,
1947
+ nativeAndQuoteTokenV3Pool: fewNativeAndQuoteTokenV3Pool,
1948
+ nativeAndAmountTokenV3Pool: fewNativeAndAmountTokenV3Pool,
1949
+ nativeAndSpecifiedGasTokenV3Pool: fewNativeAndSpecifiedGasTokenV3Pool,
1950
+ };
1951
+ const v2GasModelPromise = ((_a = this.v2Supported) === null || _a === void 0 ? void 0 : _a.includes(this.chainId))
1952
+ ? this.v2GasModelFactory
1953
+ .buildGasModel({
1954
+ chainId: this.chainId,
1955
+ gasPriceWei,
1956
+ poolProvider: this.v2PoolProvider,
1957
+ token: quoteToken,
1958
+ l2GasDataProvider: this.l2GasDataProvider,
1959
+ providerConfig: providerConfig,
1960
+ })
1961
+ .catch((_) => undefined) // If v2 model throws uncaught exception, we return undefined v2 gas model, so there's a chance v3 route can go through
1962
+ : Promise.resolve(undefined);
1963
+ // uniswap fewtoken
1964
+ const fewV2GasModelPromise = ((_c = this.v2Supported) === null || _c === void 0 ? void 0 : _c.includes(this.chainId))
1965
+ ? this.v2GasModelFactory
1966
+ .buildGasModel({
1967
+ chainId: this.chainId,
1968
+ gasPriceWei,
1969
+ poolProvider: this.v2PoolProvider,
1970
+ token: fewQuoteToken,
1971
+ l2GasDataProvider: this.l2GasDataProvider,
1972
+ providerConfig: providerConfig,
1973
+ })
1974
+ .catch((_) => undefined) // If v2 model throws uncaught exception, we return undefined v2 gas model, so there's a chance v3 route can go through
1975
+ : Promise.resolve(undefined);
1976
+ const ringFewV2GasModelPromise = ((_d = this.ringFewV2Supported) === null || _d === void 0 ? void 0 : _d.includes(this.chainId))
1977
+ ? this.ringFewV2GasModelFactory
1978
+ .buildGasModel({
1979
+ chainId: this.chainId,
1980
+ gasPriceWei,
1981
+ poolProvider: this.ringFewV2PoolProvider,
1982
+ token: quoteToken,
1983
+ l2GasDataProvider: this.l2GasDataProvider,
1984
+ providerConfig: providerConfig,
1985
+ })
1986
+ .catch((_) => undefined) // If v2 model throws uncaught exception, we return undefined v2 gas model, so there's a chance v3 route can go through
1987
+ : Promise.resolve(undefined);
1988
+ const v3GasModelPromise = this.v3GasModelFactory.buildGasModel({
1989
+ chainId: this.chainId,
1990
+ gasPriceWei,
1991
+ pools,
1992
+ amountToken,
1993
+ quoteToken,
1994
+ v2poolProvider: this.v2PoolProvider,
1995
+ l2GasDataProvider: this.l2GasDataProvider,
1996
+ providerConfig: providerConfig,
1997
+ });
1998
+ const fewV3GasModelPromise = this.uniswapFewV3GasModelFactory.buildGasModel({
1999
+ chainId: this.chainId,
2000
+ gasPriceWei,
2001
+ pools: fewPools,
2002
+ amountToken: fewAmountToken,
2003
+ quoteToken: fewQuoteToken,
2004
+ v2poolProvider: this.v2PoolProvider,
2005
+ l2GasDataProvider: this.l2GasDataProvider,
2006
+ providerConfig: providerConfig,
2007
+ });
2008
+ const v4GasModelPromise = this.v4GasModelFactory.buildGasModel({
2009
+ chainId: this.chainId,
2010
+ gasPriceWei,
2011
+ pools,
2012
+ amountToken,
2013
+ quoteToken,
2014
+ v2poolProvider: this.v2PoolProvider,
2015
+ l2GasDataProvider: this.l2GasDataProvider,
2016
+ providerConfig: providerConfig,
2017
+ });
2018
+ const fewV4GasModelPromise = this.uniswapFewV4GasModelFactory.buildGasModel({
2019
+ chainId: this.chainId,
2020
+ gasPriceWei,
2021
+ pools: fewPools,
2022
+ amountToken: fewAmountToken,
2023
+ quoteToken: fewQuoteToken,
2024
+ v2poolProvider: this.v2PoolProvider,
2025
+ l2GasDataProvider: this.l2GasDataProvider,
2026
+ providerConfig: providerConfig,
2027
+ });
2028
+ const mixedRouteGasModelPromise = this.mixedRouteGasModelFactory.buildGasModel({
2029
+ chainId: this.chainId,
2030
+ gasPriceWei,
2031
+ pools,
2032
+ amountToken,
2033
+ quoteToken,
2034
+ v2poolProvider: this.v2PoolProvider,
2035
+ providerConfig: providerConfig,
2036
+ });
2037
+ const [ringFewV2GasModel, v2GasModel, fewV2GasModel, v3GasModel, fewV3GasModel, v4GasModel, fewV4GasModel, mixedRouteGasModel] = await Promise.all([
2038
+ ringFewV2GasModelPromise,
2039
+ v2GasModelPromise,
2040
+ fewV2GasModelPromise,
2041
+ v3GasModelPromise,
2042
+ fewV3GasModelPromise,
2043
+ v4GasModelPromise,
2044
+ fewV4GasModelPromise,
2045
+ mixedRouteGasModelPromise,
2046
+ ]);
2047
+ metric.putMetric('GasModelCreation', Date.now() - beforeGasModel, MetricLoggerUnit.Milliseconds);
2048
+ return {
2049
+ ringFewV2GasModel: ringFewV2GasModel,
2050
+ v2GasModel: v2GasModel,
2051
+ fewV2GasModel: fewV2GasModel,
2052
+ v3GasModel: v3GasModel,
2053
+ fewV3GasModel: fewV3GasModel,
2054
+ v4GasModel: v4GasModel,
2055
+ fewV4GasModel: fewV4GasModel,
2056
+ mixedRouteGasModel: mixedRouteGasModel,
2057
+ };
2058
+ }
2059
+ // Note multiplications here can result in a loss of precision in the amounts (e.g. taking 50% of 101)
2060
+ // This is reconcilled at the end of the algorithm by adding any lost precision to one of
2061
+ // the splits in the route.
2062
+ getAmountDistribution(amount, routingConfig) {
2063
+ const { distributionPercent } = routingConfig;
2064
+ const percents = [];
2065
+ const amounts = [];
2066
+ for (let i = 1; i <= 100 / distributionPercent; i++) {
2067
+ percents.push(i * distributionPercent);
2068
+ amounts.push(amount.multiply(new Fraction(i * distributionPercent, 100)));
2069
+ }
2070
+ return [percents, amounts];
2071
+ }
2072
+ async buildSwapAndAddMethodParameters(trade, swapAndAddOptions, swapAndAddParameters) {
2073
+ const { swapOptions: { recipient, slippageTolerance, deadline, inputTokenPermit }, addLiquidityOptions: addLiquidityConfig, } = swapAndAddOptions;
2074
+ const preLiquidityPosition = swapAndAddParameters.preLiquidityPosition;
2075
+ const finalBalanceTokenIn = swapAndAddParameters.initialBalanceTokenIn.subtract(trade.inputAmount);
2076
+ const finalBalanceTokenOut = swapAndAddParameters.initialBalanceTokenOut.add(trade.outputAmount);
2077
+ const approvalTypes = await this.swapRouterProvider.getApprovalType(finalBalanceTokenIn, finalBalanceTokenOut);
2078
+ const zeroForOne = finalBalanceTokenIn.currency.wrapped.sortsBefore(finalBalanceTokenOut.currency.wrapped);
2079
+ return {
2080
+ ...SwapRouter.swapAndAddCallParameters(trade, {
2081
+ recipient,
2082
+ slippageTolerance,
2083
+ deadlineOrPreviousBlockhash: deadline,
2084
+ inputTokenPermit,
2085
+ }, Position.fromAmounts({
2086
+ pool: preLiquidityPosition.pool,
2087
+ tickLower: preLiquidityPosition.tickLower,
2088
+ tickUpper: preLiquidityPosition.tickUpper,
2089
+ amount0: zeroForOne
2090
+ ? finalBalanceTokenIn.quotient.toString()
2091
+ : finalBalanceTokenOut.quotient.toString(),
2092
+ amount1: zeroForOne
2093
+ ? finalBalanceTokenOut.quotient.toString()
2094
+ : finalBalanceTokenIn.quotient.toString(),
2095
+ useFullPrecision: false,
2096
+ }), addLiquidityConfig, approvalTypes.approvalTokenIn, approvalTypes.approvalTokenOut),
2097
+ to: SWAP_ROUTER_02_ADDRESSES(this.chainId),
2098
+ };
2099
+ }
2100
+ // @ts-ignore
2101
+ emitPoolSelectionMetrics(swapRouteRaw, allPoolsBySelection, currencyIn, currencyOut) {
2102
+ const poolAddressesUsed = new Set();
2103
+ const { routes: routeAmounts } = swapRouteRaw;
2104
+ _(routeAmounts)
2105
+ .flatMap((routeAmount) => {
2106
+ const { poolIdentifiers: poolAddresses } = routeAmount;
2107
+ return poolAddresses;
2108
+ })
2109
+ .forEach((address) => {
2110
+ poolAddressesUsed.add(address.toLowerCase());
2111
+ });
2112
+ for (const poolsBySelection of allPoolsBySelection) {
2113
+ const { protocol } = poolsBySelection;
2114
+ _.forIn(poolsBySelection.selections, (pools, topNSelection) => {
2115
+ const topNUsed = _.findLastIndex(pools, (pool) => poolAddressesUsed.has(pool.id.toLowerCase())) + 1;
2116
+ metric.putMetric(_.capitalize(`${protocol}${topNSelection}`), topNUsed, MetricLoggerUnit.Count);
2117
+ });
2118
+ }
2119
+ let hasV4Route = false;
2120
+ let hasV3Route = false;
2121
+ let hasV2Route = false;
2122
+ let hasMixedRoute = false;
2123
+ for (const routeAmount of routeAmounts) {
2124
+ if (routeAmount.protocol === Protocol.V4) {
2125
+ hasV4Route = true;
2126
+ }
2127
+ if (routeAmount.protocol === Protocol.V3) {
2128
+ hasV3Route = true;
2129
+ }
2130
+ if (routeAmount.protocol === Protocol.V2) {
2131
+ hasV2Route = true;
2132
+ }
2133
+ if (routeAmount.protocol === Protocol.MIXED) {
2134
+ hasMixedRoute = true;
2135
+ }
2136
+ }
2137
+ if (hasMixedRoute && (hasV4Route || hasV3Route || hasV2Route)) {
2138
+ let metricsPrefix = 'Mixed';
2139
+ if (hasV4Route) {
2140
+ metricsPrefix += 'AndV4';
2141
+ }
2142
+ if (hasV3Route) {
2143
+ metricsPrefix += 'AndV3';
2144
+ }
2145
+ if (hasV2Route) {
2146
+ metricsPrefix += 'AndV2';
2147
+ }
2148
+ metric.putMetric(`${metricsPrefix}SplitRoute`, 1, MetricLoggerUnit.Count);
2149
+ metric.putMetric(`${metricsPrefix}SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2150
+ if (hasV4Route && (currencyIn.isNative || currencyOut.isNative)) {
2151
+ // Keep track of this edge case https://linear.app/uniswap/issue/ROUTE-303/tech-debt-split-route-can-have-different-ethweth-input-or-output#comment-bba53758
2152
+ metric.putMetric(`${metricsPrefix}SplitRouteWithNativeToken`, 1, MetricLoggerUnit.Count);
2153
+ metric.putMetric(`${metricsPrefix}SplitRouteWithNativeTokenForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2154
+ }
2155
+ }
2156
+ else if (hasV4Route && hasV3Route && hasV2Route) {
2157
+ metric.putMetric(`V4AndV3AndV2SplitRoute`, 1, MetricLoggerUnit.Count);
2158
+ metric.putMetric(`V4AndV3AndV2SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2159
+ if (currencyIn.isNative || currencyOut.isNative) {
2160
+ // Keep track of this edge case https://linear.app/uniswap/issue/ROUTE-303/tech-debt-split-route-can-have-different-ethweth-input-or-output#comment-bba53758
2161
+ metric.putMetric(`V4AndV3AndV2SplitRouteWithNativeToken`, 1, MetricLoggerUnit.Count);
2162
+ metric.putMetric(`V4AndV3AndV2SplitRouteWithNativeTokenForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2163
+ }
2164
+ }
2165
+ else if (hasMixedRoute) {
2166
+ if (routeAmounts.length > 1) {
2167
+ metric.putMetric(`MixedSplitRoute`, 1, MetricLoggerUnit.Count);
2168
+ metric.putMetric(`MixedSplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2169
+ }
2170
+ else {
2171
+ metric.putMetric(`MixedRoute`, 1, MetricLoggerUnit.Count);
2172
+ metric.putMetric(`MixedRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2173
+ }
2174
+ }
2175
+ else if (hasV4Route) {
2176
+ if (routeAmounts.length > 1) {
2177
+ metric.putMetric(`V4SplitRoute`, 1, MetricLoggerUnit.Count);
2178
+ metric.putMetric(`V4SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2179
+ }
2180
+ }
2181
+ else if (hasV3Route) {
2182
+ if (routeAmounts.length > 1) {
2183
+ metric.putMetric(`V3SplitRoute`, 1, MetricLoggerUnit.Count);
2184
+ metric.putMetric(`V3SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2185
+ }
2186
+ else {
2187
+ metric.putMetric(`V3Route`, 1, MetricLoggerUnit.Count);
2188
+ metric.putMetric(`V3RouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2189
+ }
2190
+ }
2191
+ else if (hasV2Route) {
2192
+ if (routeAmounts.length > 1) {
2193
+ metric.putMetric(`V2SplitRoute`, 1, MetricLoggerUnit.Count);
2194
+ metric.putMetric(`V2SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2195
+ }
2196
+ else {
2197
+ metric.putMetric(`V2Route`, 1, MetricLoggerUnit.Count);
2198
+ metric.putMetric(`V2RouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
2199
+ }
2200
+ }
2201
+ }
2202
+ calculateOptimalRatio(position, sqrtRatioX96, zeroForOne) {
2203
+ const upperSqrtRatioX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);
2204
+ const lowerSqrtRatioX96 = TickMath.getSqrtRatioAtTick(position.tickLower);
2205
+ // returns Fraction(0, 1) for any out of range position regardless of zeroForOne. Implication: function
2206
+ // cannot be used to determine the trading direction of out of range positions.
2207
+ if (JSBI.greaterThan(sqrtRatioX96, upperSqrtRatioX96) ||
2208
+ JSBI.lessThan(sqrtRatioX96, lowerSqrtRatioX96)) {
2209
+ return new Fraction(0, 1);
2210
+ }
2211
+ const precision = JSBI.BigInt('1' + '0'.repeat(18));
2212
+ let optimalRatio = new Fraction(SqrtPriceMath.getAmount0Delta(sqrtRatioX96, upperSqrtRatioX96, precision, true), SqrtPriceMath.getAmount1Delta(sqrtRatioX96, lowerSqrtRatioX96, precision, true));
2213
+ if (!zeroForOne)
2214
+ optimalRatio = optimalRatio.invert();
2215
+ return optimalRatio;
2216
+ }
2217
+ async userHasSufficientBalance(fromAddress, tradeType, amount, quote) {
2218
+ try {
2219
+ const neededBalance = tradeType === TradeType.EXACT_INPUT ? amount : quote;
2220
+ let balance;
2221
+ if (neededBalance.currency.isNative) {
2222
+ balance = await this.provider.getBalance(fromAddress);
2223
+ }
2224
+ else {
2225
+ const tokenContract = Erc20__factory.connect(neededBalance.currency.address, this.provider);
2226
+ balance = await tokenContract.balanceOf(fromAddress);
2227
+ }
2228
+ return balance.gte(BigNumber.from(neededBalance.quotient.toString()));
2229
+ }
2230
+ catch (e) {
2231
+ log.error(e, 'Error while checking user balance');
2232
+ return false;
2233
+ }
2234
+ }
2235
+ absoluteValue(fraction) {
2236
+ const numeratorAbs = JSBI.lessThan(fraction.numerator, JSBI.BigInt(0))
2237
+ ? JSBI.unaryMinus(fraction.numerator)
2238
+ : fraction.numerator;
2239
+ const denominatorAbs = JSBI.lessThan(fraction.denominator, JSBI.BigInt(0))
2240
+ ? JSBI.unaryMinus(fraction.denominator)
2241
+ : fraction.denominator;
2242
+ return new Fraction(numeratorAbs, denominatorAbs);
2243
+ }
2244
+ getBlockNumberPromise() {
2245
+ return retry(async (_b, attempt) => {
2246
+ if (attempt > 1) {
2247
+ log.info(`Get block number attempt ${attempt}`);
2248
+ }
2249
+ return this.provider.getBlockNumber();
2250
+ }, {
2251
+ retries: 2,
2252
+ minTimeout: 100,
2253
+ maxTimeout: 1000,
2254
+ });
2255
+ }
2256
+ // If we are requesting URv1.2, we need to keep entering cache
2257
+ // We want to skip cached routes access whenever "intent === INTENT.CACHING" or "hooksOption !== HooksOption.HOOKS_INCLUSIVE"
2258
+ // We keep this method as we might want to add more conditions in the future.
2259
+ static isAllowedToEnterCachedRoutes(intent, hooksOptions, swapRouter) {
2260
+ // intent takes highest precedence, as we need to ensure during caching intent, we do not enter cache no matter what
2261
+ if (intent !== undefined && intent === INTENT.CACHING) {
2262
+ return false;
2263
+ }
2264
+ // in case we have URv1.2 request during QUOTE intent, we assume cached routes correctly returns mixed route w/o v4, if mixed is best
2265
+ // or v2/v3 is the best.
2266
+ // implicitly it means hooksOptions no longer matters for URv1.2
2267
+ // swapRouter has higher precedence than hooksOptions, because in case of URv1.2, we set hooksOptions = NO_HOOKS as default,
2268
+ // but swapRouter does not have any v4 pool for routing, so swapRouter should always use caching during QUOTE intent.
2269
+ if (swapRouter) {
2270
+ return true;
2271
+ }
2272
+ // in case we have URv2.0, and we are in QUOTE intent, we only want to enter cache when hooksOptions is default, HOOKS_INCLUSIVE
2273
+ if (hooksOptions !== undefined &&
2274
+ hooksOptions !== HooksOptions.HOOKS_INCLUSIVE) {
2275
+ return false;
2276
+ }
2277
+ return true;
2278
+ }
2279
+ }
2280
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxwaGEtcm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3JvdXRlcnMvYWxwaGEtcm91dGVyL2FscGhhLXJvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFnQixlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN6RSxPQUFPLGtCQUFrQixNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFTLElBQUksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzlFLE9BQU8sRUFDTCxPQUFPLEVBRVAsUUFBUSxFQUNSLEtBQUssRUFDTCxTQUFTLEdBQ1YsTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDaEYsT0FBTyxLQUFLLE1BQU0sYUFBYSxDQUFDO0FBQ2hDLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLENBQUMsTUFBTSxRQUFRLENBQUM7QUFDdkIsT0FBTyxTQUFTLE1BQU0sWUFBWSxDQUFDO0FBRW5DLE9BQU8sRUFDTCxZQUFZLEVBQ1osU0FBUyxFQUNULHlCQUF5QixFQUN6QixnQ0FBZ0MsRUFDaEMscUJBQXFCO0FBQ3JCLDZCQUE2QjtBQUM3QixxQkFBcUI7QUFDckIsNkJBQTZCO0FBQzdCLDZCQUE2QjtBQUM3Qix1QkFBdUIsRUFDdkIseUJBQXlCLEVBV3pCLHNCQUFzQixFQUN0QixXQUFXLEVBQ1gsdUJBQXVCLEVBQ3ZCLG9CQUFvQixFQUNwQiw0QkFBNEI7QUFDNUIsb0NBQW9DO0FBQ3BDLCtCQUErQixFQUMvQixzQ0FBc0MsRUFDdEMseUJBQXlCLEVBQ3pCLGtCQUFrQixFQUNsQixtQkFBbUIsRUFDbkIsZ0JBQWdCLEVB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