@fanx-protocol/smart-order-router 0.0.1

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 (438) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/LICENSE +674 -0
  3. package/README.md +273 -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 +89 -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 +88 -0
  21. package/build/main/providers/caching/route/route-caching-provider.js +72 -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 +37 -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 +108 -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 +19 -0
  33. package/build/main/providers/eth-estimate-gas-provider.js +94 -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/gas-price-provider.d.ts +10 -0
  37. package/build/main/providers/gas-price-provider.js +10 -0
  38. package/build/main/providers/index.d.ts +38 -0
  39. package/build/main/providers/index.js +55 -0
  40. package/build/main/providers/legacy-gas-price-provider.d.ts +7 -0
  41. package/build/main/providers/legacy-gas-price-provider.js +18 -0
  42. package/build/main/providers/multicall-provider.d.ts +83 -0
  43. package/build/main/providers/multicall-provider.js +15 -0
  44. package/build/main/providers/multicall-uniswap-provider.d.ts +37 -0
  45. package/build/main/providers/multicall-uniswap-provider.js +164 -0
  46. package/build/main/providers/on-chain-gas-price-provider.d.ts +19 -0
  47. package/build/main/providers/on-chain-gas-price-provider.js +36 -0
  48. package/build/main/providers/on-chain-quote-provider.d.ts +258 -0
  49. package/build/main/providers/on-chain-quote-provider.js +693 -0
  50. package/build/main/providers/pool-provider.d.ts +44 -0
  51. package/build/main/providers/pool-provider.js +73 -0
  52. package/build/main/providers/portion-provider.d.ts +86 -0
  53. package/build/main/providers/portion-provider.js +118 -0
  54. package/build/main/providers/provider.d.ts +38 -0
  55. package/build/main/providers/provider.js +3 -0
  56. package/build/main/providers/simulation-provider.d.ts +43 -0
  57. package/build/main/providers/simulation-provider.js +136 -0
  58. package/build/main/providers/static-gas-price-provider.d.ts +7 -0
  59. package/build/main/providers/static-gas-price-provider.js +13 -0
  60. package/build/main/providers/subgraph-provider-with-fallback.d.ts +11 -0
  61. package/build/main/providers/subgraph-provider-with-fallback.js +25 -0
  62. package/build/main/providers/subgraph-provider.d.ts +51 -0
  63. package/build/main/providers/subgraph-provider.js +120 -0
  64. package/build/main/providers/swap-router-provider.d.ts +30 -0
  65. package/build/main/providers/swap-router-provider.js +42 -0
  66. package/build/main/providers/token-fee-fetcher.d.ts +31 -0
  67. package/build/main/providers/token-fee-fetcher.js +108 -0
  68. package/build/main/providers/token-properties-provider.d.ts +31 -0
  69. package/build/main/providers/token-properties-provider.js +118 -0
  70. package/build/main/providers/token-provider.d.ts +38 -0
  71. package/build/main/providers/token-provider.js +175 -0
  72. package/build/main/providers/token-validator-provider.d.ts +42 -0
  73. package/build/main/providers/token-validator-provider.js +99 -0
  74. package/build/main/providers/uri-subgraph-provider.d.ts +20 -0
  75. package/build/main/providers/uri-subgraph-provider.js +65 -0
  76. package/build/main/providers/v2/caching-pool-provider.d.ts +33 -0
  77. package/build/main/providers/v2/caching-pool-provider.js +89 -0
  78. package/build/main/providers/v2/caching-subgraph-provider.d.ts +19 -0
  79. package/build/main/providers/v2/caching-subgraph-provider.js +24 -0
  80. package/build/main/providers/v2/pool-provider.d.ts +63 -0
  81. package/build/main/providers/v2/pool-provider.js +138 -0
  82. package/build/main/providers/v2/quote-provider.d.ts +34 -0
  83. package/build/main/providers/v2/quote-provider.js +90 -0
  84. package/build/main/providers/v2/static-subgraph-provider.d.ts +19 -0
  85. package/build/main/providers/v2/static-subgraph-provider.js +75 -0
  86. package/build/main/providers/v2/subgraph-provider-with-fallback.d.ts +16 -0
  87. package/build/main/providers/v2/subgraph-provider-with-fallback.js +23 -0
  88. package/build/main/providers/v2/subgraph-provider.d.ts +36 -0
  89. package/build/main/providers/v2/subgraph-provider.js +174 -0
  90. package/build/main/providers/v2/uri-subgraph-provider.d.ts +4 -0
  91. package/build/main/providers/v2/uri-subgraph-provider.js +8 -0
  92. package/build/main/providers/v3/caching-pool-provider.d.ts +32 -0
  93. package/build/main/providers/v3/caching-pool-provider.js +84 -0
  94. package/build/main/providers/v3/caching-subgraph-provider.d.ts +19 -0
  95. package/build/main/providers/v3/caching-subgraph-provider.js +24 -0
  96. package/build/main/providers/v3/gas-data-provider.d.ts +39 -0
  97. package/build/main/providers/v3/gas-data-provider.js +26 -0
  98. package/build/main/providers/v3/pool-provider.d.ts +77 -0
  99. package/build/main/providers/v3/pool-provider.js +108 -0
  100. package/build/main/providers/v3/static-subgraph-provider.d.ts +21 -0
  101. package/build/main/providers/v3/static-subgraph-provider.js +89 -0
  102. package/build/main/providers/v3/subgraph-provider-with-fallback.d.ts +12 -0
  103. package/build/main/providers/v3/subgraph-provider-with-fallback.js +19 -0
  104. package/build/main/providers/v3/subgraph-provider.d.ts +46 -0
  105. package/build/main/providers/v3/subgraph-provider.js +54 -0
  106. package/build/main/providers/v3/uri-subgraph-provider.d.ts +4 -0
  107. package/build/main/providers/v3/uri-subgraph-provider.js +8 -0
  108. package/build/main/routers/alpha-router/alpha-router.d.ts +347 -0
  109. package/build/main/routers/alpha-router/alpha-router.js +1219 -0
  110. package/build/main/routers/alpha-router/config.d.ts +4 -0
  111. package/build/main/routers/alpha-router/config.js +40 -0
  112. package/build/main/routers/alpha-router/entities/index.d.ts +1 -0
  113. package/build/main/routers/alpha-router/entities/index.js +18 -0
  114. package/build/main/routers/alpha-router/entities/route-with-valid-quote.d.ts +167 -0
  115. package/build/main/routers/alpha-router/entities/route-with-valid-quote.js +166 -0
  116. package/build/main/routers/alpha-router/functions/best-swap-route.d.ts +22 -0
  117. package/build/main/routers/alpha-router/functions/best-swap-route.js +534 -0
  118. package/build/main/routers/alpha-router/functions/calculate-ratio-amount-in.d.ts +3 -0
  119. package/build/main/routers/alpha-router/functions/calculate-ratio-amount-in.js +18 -0
  120. package/build/main/routers/alpha-router/functions/compute-all-routes.d.ts +9 -0
  121. package/build/main/routers/alpha-router/functions/compute-all-routes.js +104 -0
  122. package/build/main/routers/alpha-router/functions/get-candidate-pools.d.ts +100 -0
  123. package/build/main/routers/alpha-router/functions/get-candidate-pools.js +1008 -0
  124. package/build/main/routers/alpha-router/gas-models/gas-costs.d.ts +12 -0
  125. package/build/main/routers/alpha-router/gas-models/gas-costs.js +90 -0
  126. package/build/main/routers/alpha-router/gas-models/gas-model.d.ts +106 -0
  127. package/build/main/routers/alpha-router/gas-models/gas-model.js +68 -0
  128. package/build/main/routers/alpha-router/gas-models/index.d.ts +2 -0
  129. package/build/main/routers/alpha-router/gas-models/index.js +19 -0
  130. package/build/main/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.d.ts +24 -0
  131. package/build/main/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.js +161 -0
  132. package/build/main/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.d.ts +15 -0
  133. package/build/main/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.js +185 -0
  134. package/build/main/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.d.ts +31 -0
  135. package/build/main/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.js +169 -0
  136. package/build/main/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.d.ts +26 -0
  137. package/build/main/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.js +41 -0
  138. package/build/main/routers/alpha-router/index.d.ts +4 -0
  139. package/build/main/routers/alpha-router/index.js +21 -0
  140. package/build/main/routers/alpha-router/quoters/base-quoter.d.ts +76 -0
  141. package/build/main/routers/alpha-router/quoters/base-quoter.js +76 -0
  142. package/build/main/routers/alpha-router/quoters/index.d.ts +5 -0
  143. package/build/main/routers/alpha-router/quoters/index.js +22 -0
  144. package/build/main/routers/alpha-router/quoters/mixed-quoter.d.ts +28 -0
  145. package/build/main/routers/alpha-router/quoters/mixed-quoter.js +154 -0
  146. package/build/main/routers/alpha-router/quoters/model/index.d.ts +1 -0
  147. package/build/main/routers/alpha-router/quoters/model/index.js +18 -0
  148. package/build/main/routers/alpha-router/quoters/model/results/get-quotes-result.d.ts +6 -0
  149. package/build/main/routers/alpha-router/quoters/model/results/get-quotes-result.js +3 -0
  150. package/build/main/routers/alpha-router/quoters/model/results/get-routes-result.d.ts +6 -0
  151. package/build/main/routers/alpha-router/quoters/model/results/get-routes-result.js +3 -0
  152. package/build/main/routers/alpha-router/quoters/model/results/index.d.ts +2 -0
  153. package/build/main/routers/alpha-router/quoters/model/results/index.js +19 -0
  154. package/build/main/routers/alpha-router/quoters/v2-quoter.d.ts +24 -0
  155. package/build/main/routers/alpha-router/quoters/v2-quoter.js +140 -0
  156. package/build/main/routers/alpha-router/quoters/v3-quoter.d.ts +19 -0
  157. package/build/main/routers/alpha-router/quoters/v3-quoter.js +117 -0
  158. package/build/main/routers/index.d.ts +3 -0
  159. package/build/main/routers/index.js +20 -0
  160. package/build/main/routers/router.d.ts +186 -0
  161. package/build/main/routers/router.js +55 -0
  162. package/build/main/tsconfig.tsbuildinfo +1 -0
  163. package/build/main/types/other/commons.d.ts +16 -0
  164. package/build/main/types/other/commons.js +6 -0
  165. package/build/main/types/other/factories/Erc20__factory.d.ts +45 -0
  166. package/build/main/types/other/factories/Erc20__factory.js +240 -0
  167. package/build/main/types/other/factories/GasDataArbitrum__factory.d.ts +18 -0
  168. package/build/main/types/other/factories/GasDataArbitrum__factory.js +58 -0
  169. package/build/main/types/other/factories/IMixedRouteQuoterV1__factory.d.ts +41 -0
  170. package/build/main/types/other/factories/IMixedRouteQuoterV1__factory.js +156 -0
  171. package/build/main/types/other/factories/ITokenValidator__factory.d.ts +22 -0
  172. package/build/main/types/other/factories/ITokenValidator__factory.js +78 -0
  173. package/build/main/types/other/factories/MixedRouteQuoterV2__factory.d.ts +86 -0
  174. package/build/main/types/other/factories/MixedRouteQuoterV2__factory.js +477 -0
  175. package/build/main/types/other/factories/Permit2__factory.d.ts +87 -0
  176. package/build/main/types/other/factories/Permit2__factory.js +936 -0
  177. package/build/main/types/other/factories/SwapRouter02__factory.d.ts +67 -0
  178. package/build/main/types/other/factories/SwapRouter02__factory.js +1098 -0
  179. package/build/main/types/other/factories/TokenFeeDetector__factory.d.ts +47 -0
  180. package/build/main/types/other/factories/TokenFeeDetector__factory.js +243 -0
  181. package/build/main/types/v2/commons.d.ts +16 -0
  182. package/build/main/types/v2/commons.js +6 -0
  183. package/build/main/types/v2/factories/IUniswapV2Pair__factory.d.ts +35 -0
  184. package/build/main/types/v2/factories/IUniswapV2Pair__factory.js +671 -0
  185. package/build/main/types/v3/commons.d.ts +16 -0
  186. package/build/main/types/v3/commons.js +6 -0
  187. package/build/main/types/v3/factories/IERC20Metadata__factory.d.ts +35 -0
  188. package/build/main/types/v3/factories/IERC20Metadata__factory.js +242 -0
  189. package/build/main/types/v3/factories/IQuoterV2__factory.d.ts +41 -0
  190. package/build/main/types/v3/factories/IQuoterV2__factory.js +220 -0
  191. package/build/main/types/v3/factories/IUniswapV3PoolState__factory.d.ts +22 -0
  192. package/build/main/types/v3/factories/IUniswapV3PoolState__factory.js +266 -0
  193. package/build/main/types/v3/factories/UniswapInterfaceMulticall__factory.d.ts +61 -0
  194. package/build/main/types/v3/factories/UniswapInterfaceMulticall__factory.js +127 -0
  195. package/build/main/util/addresses.d.ts +24 -0
  196. package/build/main/util/addresses.js +76 -0
  197. package/build/main/util/amounts.d.ts +9 -0
  198. package/build/main/util/amounts.js +73 -0
  199. package/build/main/util/chains.d.ts +31 -0
  200. package/build/main/util/chains.js +97 -0
  201. package/build/main/util/gas-factory-helpers.d.ts +33 -0
  202. package/build/main/util/gas-factory-helpers.js +463 -0
  203. package/build/main/util/index.d.ts +7 -0
  204. package/build/main/util/index.js +24 -0
  205. package/build/main/util/l2FeeChains.d.ts +2 -0
  206. package/build/main/util/l2FeeChains.js +13 -0
  207. package/build/main/util/log.d.ts +3 -0
  208. package/build/main/util/log.js +97 -0
  209. package/build/main/util/methodParameters.d.ts +5 -0
  210. package/build/main/util/methodParameters.js +183 -0
  211. package/build/main/util/metric.d.ts +48 -0
  212. package/build/main/util/metric.js +59 -0
  213. package/build/main/util/onchainQuoteProviderConfigs.d.ts +42 -0
  214. package/build/main/util/onchainQuoteProviderConfigs.js +74 -0
  215. package/build/main/util/protocols.d.ts +2 -0
  216. package/build/main/util/protocols.js +20 -0
  217. package/build/main/util/routes.d.ts +11 -0
  218. package/build/main/util/routes.js +149 -0
  219. package/build/main/util/unsupported-tokens.d.ts +37 -0
  220. package/build/main/util/unsupported-tokens.js +1119 -0
  221. package/build/module/index.d.ts +3 -0
  222. package/build/module/index.js +4 -0
  223. package/build/module/providers/cache-node.d.ts +10 -0
  224. package/build/module/providers/cache-node.js +29 -0
  225. package/build/module/providers/cache.d.ts +14 -0
  226. package/build/module/providers/cache.js +2 -0
  227. package/build/module/providers/caching/route/index.d.ts +2 -0
  228. package/build/module/providers/caching/route/index.js +3 -0
  229. package/build/module/providers/caching/route/model/cache-mode.d.ts +16 -0
  230. package/build/module/providers/caching/route/model/cache-mode.js +18 -0
  231. package/build/module/providers/caching/route/model/cached-route.d.ts +29 -0
  232. package/build/module/providers/caching/route/model/cached-route.js +85 -0
  233. package/build/module/providers/caching/route/model/cached-routes.d.ts +67 -0
  234. package/build/module/providers/caching/route/model/cached-routes.js +74 -0
  235. package/build/module/providers/caching/route/model/index.d.ts +3 -0
  236. package/build/module/providers/caching/route/model/index.js +4 -0
  237. package/build/module/providers/caching/route/route-caching-provider.d.ts +88 -0
  238. package/build/module/providers/caching/route/route-caching-provider.js +68 -0
  239. package/build/module/providers/caching-gas-provider.d.ts +23 -0
  240. package/build/module/providers/caching-gas-provider.js +37 -0
  241. package/build/module/providers/caching-subgraph-provider.d.ts +33 -0
  242. package/build/module/providers/caching-subgraph-provider.js +33 -0
  243. package/build/module/providers/caching-token-list-provider.d.ts +52 -0
  244. package/build/module/providers/caching-token-list-provider.js +140 -0
  245. package/build/module/providers/caching-token-provider.d.ts +24 -0
  246. package/build/module/providers/caching-token-provider.js +101 -0
  247. package/build/module/providers/eip-1559-gas-price-provider.d.ts +31 -0
  248. package/build/module/providers/eip-1559-gas-price-provider.js +64 -0
  249. package/build/module/providers/eth-estimate-gas-provider.d.ts +19 -0
  250. package/build/module/providers/eth-estimate-gas-provider.js +102 -0
  251. package/build/module/providers/eth-gas-station-info-gas-price-provider.d.ts +19 -0
  252. package/build/module/providers/eth-gas-station-info-gas-price-provider.js +29 -0
  253. package/build/module/providers/gas-price-provider.d.ts +10 -0
  254. package/build/module/providers/gas-price-provider.js +6 -0
  255. package/build/module/providers/index.d.ts +38 -0
  256. package/build/module/providers/index.js +39 -0
  257. package/build/module/providers/legacy-gas-price-provider.d.ts +7 -0
  258. package/build/module/providers/legacy-gas-price-provider.js +14 -0
  259. package/build/module/providers/multicall-provider.d.ts +83 -0
  260. package/build/module/providers/multicall-provider.js +11 -0
  261. package/build/module/providers/multicall-uniswap-provider.d.ts +37 -0
  262. package/build/module/providers/multicall-uniswap-provider.js +157 -0
  263. package/build/module/providers/on-chain-gas-price-provider.d.ts +19 -0
  264. package/build/module/providers/on-chain-gas-price-provider.js +32 -0
  265. package/build/module/providers/on-chain-quote-provider.d.ts +258 -0
  266. package/build/module/providers/on-chain-quote-provider.js +687 -0
  267. package/build/module/providers/pool-provider.d.ts +44 -0
  268. package/build/module/providers/pool-provider.js +66 -0
  269. package/build/module/providers/portion-provider.d.ts +86 -0
  270. package/build/module/providers/portion-provider.js +114 -0
  271. package/build/module/providers/provider.d.ts +38 -0
  272. package/build/module/providers/provider.js +2 -0
  273. package/build/module/providers/simulation-provider.d.ts +43 -0
  274. package/build/module/providers/simulation-provider.js +138 -0
  275. package/build/module/providers/static-gas-price-provider.d.ts +7 -0
  276. package/build/module/providers/static-gas-price-provider.js +9 -0
  277. package/build/module/providers/subgraph-provider-with-fallback.d.ts +11 -0
  278. package/build/module/providers/subgraph-provider-with-fallback.js +21 -0
  279. package/build/module/providers/subgraph-provider.d.ts +51 -0
  280. package/build/module/providers/subgraph-provider.js +113 -0
  281. package/build/module/providers/swap-router-provider.d.ts +30 -0
  282. package/build/module/providers/swap-router-provider.js +38 -0
  283. package/build/module/providers/token-fee-fetcher.d.ts +31 -0
  284. package/build/module/providers/token-fee-fetcher.js +104 -0
  285. package/build/module/providers/token-properties-provider.d.ts +31 -0
  286. package/build/module/providers/token-properties-provider.js +114 -0
  287. package/build/module/providers/token-provider.d.ts +38 -0
  288. package/build/module/providers/token-provider.js +164 -0
  289. package/build/module/providers/token-validator-provider.d.ts +42 -0
  290. package/build/module/providers/token-validator-provider.js +92 -0
  291. package/build/module/providers/uri-subgraph-provider.d.ts +20 -0
  292. package/build/module/providers/uri-subgraph-provider.js +58 -0
  293. package/build/module/providers/v2/caching-pool-provider.d.ts +33 -0
  294. package/build/module/providers/v2/caching-pool-provider.js +85 -0
  295. package/build/module/providers/v2/caching-subgraph-provider.d.ts +19 -0
  296. package/build/module/providers/v2/caching-subgraph-provider.js +20 -0
  297. package/build/module/providers/v2/pool-provider.d.ts +63 -0
  298. package/build/module/providers/v2/pool-provider.js +131 -0
  299. package/build/module/providers/v2/quote-provider.d.ts +34 -0
  300. package/build/module/providers/v2/quote-provider.js +86 -0
  301. package/build/module/providers/v2/static-subgraph-provider.d.ts +19 -0
  302. package/build/module/providers/v2/static-subgraph-provider.js +68 -0
  303. package/build/module/providers/v2/subgraph-provider-with-fallback.d.ts +16 -0
  304. package/build/module/providers/v2/subgraph-provider-with-fallback.js +19 -0
  305. package/build/module/providers/v2/subgraph-provider.d.ts +36 -0
  306. package/build/module/providers/v2/subgraph-provider.js +167 -0
  307. package/build/module/providers/v2/uri-subgraph-provider.d.ts +4 -0
  308. package/build/module/providers/v2/uri-subgraph-provider.js +4 -0
  309. package/build/module/providers/v3/caching-pool-provider.d.ts +32 -0
  310. package/build/module/providers/v3/caching-pool-provider.js +77 -0
  311. package/build/module/providers/v3/caching-subgraph-provider.d.ts +19 -0
  312. package/build/module/providers/v3/caching-subgraph-provider.js +20 -0
  313. package/build/module/providers/v3/gas-data-provider.d.ts +39 -0
  314. package/build/module/providers/v3/gas-data-provider.js +22 -0
  315. package/build/module/providers/v3/pool-provider.d.ts +77 -0
  316. package/build/module/providers/v3/pool-provider.js +101 -0
  317. package/build/module/providers/v3/static-subgraph-provider.d.ts +21 -0
  318. package/build/module/providers/v3/static-subgraph-provider.js +82 -0
  319. package/build/module/providers/v3/subgraph-provider-with-fallback.d.ts +12 -0
  320. package/build/module/providers/v3/subgraph-provider-with-fallback.js +15 -0
  321. package/build/module/providers/v3/subgraph-provider.d.ts +46 -0
  322. package/build/module/providers/v3/subgraph-provider.js +50 -0
  323. package/build/module/providers/v3/uri-subgraph-provider.d.ts +4 -0
  324. package/build/module/providers/v3/uri-subgraph-provider.js +4 -0
  325. package/build/module/routers/alpha-router/alpha-router.d.ts +347 -0
  326. package/build/module/routers/alpha-router/alpha-router.js +1229 -0
  327. package/build/module/routers/alpha-router/config.d.ts +4 -0
  328. package/build/module/routers/alpha-router/config.js +36 -0
  329. package/build/module/routers/alpha-router/entities/index.d.ts +1 -0
  330. package/build/module/routers/alpha-router/entities/index.js +2 -0
  331. package/build/module/routers/alpha-router/entities/route-with-valid-quote.d.ts +167 -0
  332. package/build/module/routers/alpha-router/entities/route-with-valid-quote.js +157 -0
  333. package/build/module/routers/alpha-router/functions/best-swap-route.d.ts +22 -0
  334. package/build/module/routers/alpha-router/functions/best-swap-route.js +526 -0
  335. package/build/module/routers/alpha-router/functions/calculate-ratio-amount-in.d.ts +3 -0
  336. package/build/module/routers/alpha-router/functions/calculate-ratio-amount-in.js +14 -0
  337. package/build/module/routers/alpha-router/functions/compute-all-routes.d.ts +9 -0
  338. package/build/module/routers/alpha-router/functions/compute-all-routes.js +97 -0
  339. package/build/module/routers/alpha-router/functions/get-candidate-pools.d.ts +100 -0
  340. package/build/module/routers/alpha-router/functions/get-candidate-pools.js +998 -0
  341. package/build/module/routers/alpha-router/gas-models/gas-costs.d.ts +12 -0
  342. package/build/module/routers/alpha-router/gas-models/gas-costs.js +79 -0
  343. package/build/module/routers/alpha-router/gas-models/gas-model.d.ts +106 -0
  344. package/build/module/routers/alpha-router/gas-models/gas-model.js +102 -0
  345. package/build/module/routers/alpha-router/gas-models/index.d.ts +2 -0
  346. package/build/module/routers/alpha-router/gas-models/index.js +3 -0
  347. package/build/module/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.d.ts +24 -0
  348. package/build/module/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.js +154 -0
  349. package/build/module/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.d.ts +15 -0
  350. package/build/module/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.js +181 -0
  351. package/build/module/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.d.ts +31 -0
  352. package/build/module/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.js +162 -0
  353. package/build/module/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.d.ts +26 -0
  354. package/build/module/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.js +37 -0
  355. package/build/module/routers/alpha-router/index.d.ts +4 -0
  356. package/build/module/routers/alpha-router/index.js +5 -0
  357. package/build/module/routers/alpha-router/quoters/base-quoter.d.ts +76 -0
  358. package/build/module/routers/alpha-router/quoters/base-quoter.js +69 -0
  359. package/build/module/routers/alpha-router/quoters/index.d.ts +5 -0
  360. package/build/module/routers/alpha-router/quoters/index.js +6 -0
  361. package/build/module/routers/alpha-router/quoters/mixed-quoter.d.ts +28 -0
  362. package/build/module/routers/alpha-router/quoters/mixed-quoter.js +152 -0
  363. package/build/module/routers/alpha-router/quoters/model/index.d.ts +1 -0
  364. package/build/module/routers/alpha-router/quoters/model/index.js +2 -0
  365. package/build/module/routers/alpha-router/quoters/model/results/get-quotes-result.d.ts +6 -0
  366. package/build/module/routers/alpha-router/quoters/model/results/get-quotes-result.js +2 -0
  367. package/build/module/routers/alpha-router/quoters/model/results/get-routes-result.d.ts +6 -0
  368. package/build/module/routers/alpha-router/quoters/model/results/get-routes-result.js +2 -0
  369. package/build/module/routers/alpha-router/quoters/model/results/index.d.ts +2 -0
  370. package/build/module/routers/alpha-router/quoters/model/results/index.js +3 -0
  371. package/build/module/routers/alpha-router/quoters/v2-quoter.d.ts +24 -0
  372. package/build/module/routers/alpha-router/quoters/v2-quoter.js +137 -0
  373. package/build/module/routers/alpha-router/quoters/v3-quoter.d.ts +19 -0
  374. package/build/module/routers/alpha-router/quoters/v3-quoter.js +110 -0
  375. package/build/module/routers/index.d.ts +3 -0
  376. package/build/module/routers/index.js +4 -0
  377. package/build/module/routers/router.d.ts +186 -0
  378. package/build/module/routers/router.js +47 -0
  379. package/build/module/tsconfig.module.tsbuildinfo +1 -0
  380. package/build/module/types/other/commons.d.ts +16 -0
  381. package/build/module/types/other/commons.js +5 -0
  382. package/build/module/types/other/factories/Erc20__factory.d.ts +45 -0
  383. package/build/module/types/other/factories/Erc20__factory.js +236 -0
  384. package/build/module/types/other/factories/GasDataArbitrum__factory.d.ts +18 -0
  385. package/build/module/types/other/factories/GasDataArbitrum__factory.js +54 -0
  386. package/build/module/types/other/factories/IMixedRouteQuoterV1__factory.d.ts +41 -0
  387. package/build/module/types/other/factories/IMixedRouteQuoterV1__factory.js +152 -0
  388. package/build/module/types/other/factories/ITokenValidator__factory.d.ts +22 -0
  389. package/build/module/types/other/factories/ITokenValidator__factory.js +74 -0
  390. package/build/module/types/other/factories/MixedRouteQuoterV2__factory.d.ts +86 -0
  391. package/build/module/types/other/factories/MixedRouteQuoterV2__factory.js +473 -0
  392. package/build/module/types/other/factories/Permit2__factory.d.ts +87 -0
  393. package/build/module/types/other/factories/Permit2__factory.js +932 -0
  394. package/build/module/types/other/factories/SwapRouter02__factory.d.ts +67 -0
  395. package/build/module/types/other/factories/SwapRouter02__factory.js +1094 -0
  396. package/build/module/types/other/factories/TokenFeeDetector__factory.d.ts +47 -0
  397. package/build/module/types/other/factories/TokenFeeDetector__factory.js +239 -0
  398. package/build/module/types/v2/commons.d.ts +16 -0
  399. package/build/module/types/v2/commons.js +5 -0
  400. package/build/module/types/v2/factories/IUniswapV2Pair__factory.d.ts +35 -0
  401. package/build/module/types/v2/factories/IUniswapV2Pair__factory.js +667 -0
  402. package/build/module/types/v3/commons.d.ts +16 -0
  403. package/build/module/types/v3/commons.js +5 -0
  404. package/build/module/types/v3/factories/IERC20Metadata__factory.d.ts +35 -0
  405. package/build/module/types/v3/factories/IERC20Metadata__factory.js +238 -0
  406. package/build/module/types/v3/factories/IQuoterV2__factory.d.ts +41 -0
  407. package/build/module/types/v3/factories/IQuoterV2__factory.js +216 -0
  408. package/build/module/types/v3/factories/IUniswapV3PoolState__factory.d.ts +22 -0
  409. package/build/module/types/v3/factories/IUniswapV3PoolState__factory.js +262 -0
  410. package/build/module/types/v3/factories/UniswapInterfaceMulticall__factory.d.ts +61 -0
  411. package/build/module/types/v3/factories/UniswapInterfaceMulticall__factory.js +123 -0
  412. package/build/module/util/addresses.d.ts +24 -0
  413. package/build/module/util/addresses.js +69 -0
  414. package/build/module/util/amounts.d.ts +9 -0
  415. package/build/module/util/amounts.js +62 -0
  416. package/build/module/util/chains.d.ts +31 -0
  417. package/build/module/util/chains.js +89 -0
  418. package/build/module/util/gas-factory-helpers.d.ts +33 -0
  419. package/build/module/util/gas-factory-helpers.js +446 -0
  420. package/build/module/util/index.d.ts +7 -0
  421. package/build/module/util/index.js +8 -0
  422. package/build/module/util/l2FeeChains.d.ts +2 -0
  423. package/build/module/util/l2FeeChains.js +10 -0
  424. package/build/module/util/log.d.ts +3 -0
  425. package/build/module/util/log.js +93 -0
  426. package/build/module/util/methodParameters.d.ts +5 -0
  427. package/build/module/util/methodParameters.js +181 -0
  428. package/build/module/util/metric.d.ts +48 -0
  429. package/build/module/util/metric.js +53 -0
  430. package/build/module/util/onchainQuoteProviderConfigs.d.ts +42 -0
  431. package/build/module/util/onchainQuoteProviderConfigs.js +76 -0
  432. package/build/module/util/protocols.d.ts +2 -0
  433. package/build/module/util/protocols.js +16 -0
  434. package/build/module/util/routes.d.ts +11 -0
  435. package/build/module/util/routes.js +137 -0
  436. package/build/module/util/unsupported-tokens.d.ts +37 -0
  437. package/build/module/util/unsupported-tokens.js +1116 -0
  438. package/package.json +133 -0
@@ -0,0 +1,1219 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AlphaRouter = exports.LowerCaseStringArray = exports.MapWithLowerCaseKey = void 0;
7
+ const bignumber_1 = require("@ethersproject/bignumber");
8
+ const providers_1 = require("@ethersproject/providers");
9
+ const router_sdk_1 = require("@fanx-protocol/router-sdk");
10
+ const sdk_core_1 = require("@fanx-protocol/sdk-core");
11
+ const universal_router_sdk_1 = require("@fanx-protocol/universal-router-sdk");
12
+ const v3_sdk_1 = require("@fanx-protocol/v3-sdk");
13
+ const default_token_list_1 = __importDefault(require("@uniswap/default-token-list"));
14
+ const async_retry_1 = __importDefault(require("async-retry"));
15
+ const jsbi_1 = __importDefault(require("jsbi"));
16
+ const lodash_1 = __importDefault(require("lodash"));
17
+ const node_cache_1 = __importDefault(require("node-cache"));
18
+ const providers_2 = require("../../providers");
19
+ const caching_token_list_provider_1 = require("../../providers/caching-token-list-provider");
20
+ const portion_provider_1 = require("../../providers/portion-provider");
21
+ const token_fee_fetcher_1 = require("../../providers/token-fee-fetcher");
22
+ const token_provider_1 = require("../../providers/token-provider");
23
+ const token_validator_provider_1 = require("../../providers/token-validator-provider");
24
+ const pool_provider_1 = require("../../providers/v2/pool-provider");
25
+ const gas_data_provider_1 = require("../../providers/v3/gas-data-provider");
26
+ const pool_provider_2 = require("../../providers/v3/pool-provider");
27
+ // import { CachingV4PoolProvider } from '../../providers/v4/caching-pool-provider';
28
+ // import {
29
+ // IV4PoolProvider,
30
+ // V4PoolProvider,
31
+ // } from '../../providers/v4/pool-provider';
32
+ const Erc20__factory_1 = require("../../types/other/factories/Erc20__factory");
33
+ const util_1 = require("../../util");
34
+ const amounts_1 = require("../../util/amounts");
35
+ const chains_1 = require("../../util/chains");
36
+ const gas_factory_helpers_1 = require("../../util/gas-factory-helpers");
37
+ const log_1 = require("../../util/log");
38
+ const methodParameters_1 = require("../../util/methodParameters");
39
+ const metric_1 = require("../../util/metric");
40
+ const onchainQuoteProviderConfigs_1 = require("../../util/onchainQuoteProviderConfigs");
41
+ const unsupported_tokens_1 = require("../../util/unsupported-tokens");
42
+ const router_1 = require("../router");
43
+ const config_1 = require("./config");
44
+ const best_swap_route_1 = require("./functions/best-swap-route");
45
+ const calculate_ratio_amount_in_1 = require("./functions/calculate-ratio-amount-in");
46
+ const get_candidate_pools_1 = require("./functions/get-candidate-pools");
47
+ const gas_costs_1 = require("./gas-models/gas-costs");
48
+ const mixed_route_heuristic_gas_model_1 = require("./gas-models/mixedRoute/mixed-route-heuristic-gas-model");
49
+ const v2_heuristic_gas_model_1 = require("./gas-models/v2/v2-heuristic-gas-model");
50
+ const v3_heuristic_gas_model_1 = require("./gas-models/v3/v3-heuristic-gas-model");
51
+ // import { V4HeuristicGasModelFactory } from './gas-models/v4/v4-heuristic-gas-model';
52
+ const quoters_1 = require("./quoters");
53
+ class MapWithLowerCaseKey extends Map {
54
+ set(key, value) {
55
+ return super.set(key.toLowerCase(), value);
56
+ }
57
+ }
58
+ exports.MapWithLowerCaseKey = MapWithLowerCaseKey;
59
+ class LowerCaseStringArray extends Array {
60
+ constructor(...items) {
61
+ // Convert all items to lowercase before calling the parent constructor
62
+ super(...items.map((item) => item.toLowerCase()));
63
+ }
64
+ }
65
+ exports.LowerCaseStringArray = LowerCaseStringArray;
66
+ class AlphaRouter {
67
+ constructor({ chainId, provider, multicall2Provider,
68
+ // v4SubgraphProvider,
69
+ // v4PoolProvider,
70
+ v3PoolProvider, onChainQuoteProvider, v2PoolProvider, v2QuoteProvider, v2SubgraphProvider, tokenProvider, blockedTokenListProvider, v3SubgraphProvider, gasPriceProvider,
71
+ // v4GasModelFactory,
72
+ v3GasModelFactory, v2GasModelFactory, mixedRouteGasModelFactory, swapRouterProvider, tokenValidatorProvider, arbitrumGasDataProvider, simulator, routeCachingProvider, tokenPropertiesProvider, portionProvider, v2Supported,
73
+ // v4Supported,
74
+ universalRouterVersion, }) {
75
+ this.chainId = chainId;
76
+ this.provider = provider;
77
+ this.multicall2Provider =
78
+ multicall2Provider !== null && multicall2Provider !== void 0 ? multicall2Provider : new providers_2.UniswapMulticallProvider(chainId, provider, 375000);
79
+ // this.v4PoolProvider =
80
+ // v4PoolProvider ??
81
+ // new CachingV4PoolProvider(
82
+ // this.chainId,
83
+ // new V4PoolProvider(ID_TO_CHAIN_ID(chainId), this.multicall2Provider),
84
+ // new NodeJSCache(new NodeCache({ stdTTL: 360, useClones: false }))
85
+ // );
86
+ this.v3PoolProvider =
87
+ v3PoolProvider !== null && v3PoolProvider !== void 0 ? v3PoolProvider : new providers_2.CachingV3PoolProvider(this.chainId, new pool_provider_2.V3PoolProvider((0, chains_1.ID_TO_CHAIN_ID)(chainId), this.multicall2Provider), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 360, useClones: false })));
88
+ this.simulator = simulator;
89
+ this.routeCachingProvider = routeCachingProvider;
90
+ if (onChainQuoteProvider) {
91
+ this.onChainQuoteProvider = onChainQuoteProvider;
92
+ }
93
+ else {
94
+ // Only Chiliz and Spicy are supported - use default config
95
+ this.onChainQuoteProvider = new providers_2.OnChainQuoteProvider(chainId, provider, this.multicall2Provider, onchainQuoteProviderConfigs_1.DEFAULT_RETRY_OPTIONS, (_) => onchainQuoteProviderConfigs_1.DEFAULT_BATCH_PARAMS, onchainQuoteProviderConfigs_1.DEFAULT_GAS_ERROR_FAILURE_OVERRIDES, onchainQuoteProviderConfigs_1.DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES, onchainQuoteProviderConfigs_1.DEFAULT_BLOCK_NUMBER_CONFIGS);
96
+ }
97
+ if (tokenValidatorProvider) {
98
+ this.tokenValidatorProvider = tokenValidatorProvider;
99
+ // } else if (this.chainId === ChainId.MAINNET) { // MAINNET removed
100
+ }
101
+ else if (false) {
102
+ this.tokenValidatorProvider = new token_validator_provider_1.TokenValidatorProvider(this.chainId, this.multicall2Provider, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 30000, useClones: false })));
103
+ }
104
+ if (tokenPropertiesProvider) {
105
+ this.tokenPropertiesProvider = tokenPropertiesProvider;
106
+ }
107
+ else {
108
+ this.tokenPropertiesProvider = new providers_2.TokenPropertiesProvider(this.chainId, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 86400, useClones: false })), new token_fee_fetcher_1.OnChainTokenFeeFetcher(this.chainId, provider));
109
+ }
110
+ this.v2PoolProvider =
111
+ v2PoolProvider !== null && v2PoolProvider !== void 0 ? v2PoolProvider : new providers_2.CachingV2PoolProvider(chainId, new pool_provider_1.V2PoolProvider(chainId, this.multicall2Provider, this.tokenPropertiesProvider), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 60, useClones: false })));
112
+ this.v2QuoteProvider = v2QuoteProvider !== null && v2QuoteProvider !== void 0 ? v2QuoteProvider : new providers_2.V2QuoteProvider();
113
+ this.blockedTokenListProvider =
114
+ blockedTokenListProvider !== null && blockedTokenListProvider !== void 0 ? blockedTokenListProvider : new caching_token_list_provider_1.CachingTokenListProvider(chainId, unsupported_tokens_1.UNSUPPORTED_TOKENS, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 3600, useClones: false })));
115
+ this.tokenProvider =
116
+ tokenProvider !== null && tokenProvider !== void 0 ? tokenProvider : new providers_2.CachingTokenProviderWithFallback(chainId, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 3600, useClones: false })), new caching_token_list_provider_1.CachingTokenListProvider(chainId, default_token_list_1.default, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 3600, useClones: false }))), new token_provider_1.TokenProvider(chainId, this.multicall2Provider));
117
+ this.portionProvider = portionProvider !== null && portionProvider !== void 0 ? portionProvider : new portion_provider_1.PortionProvider();
118
+ const chainName = (0, chains_1.ID_TO_NETWORK_NAME)(chainId);
119
+ // ipfs urls in the following format: `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/${protocol}/${chainName}.json`;
120
+ if (v2SubgraphProvider) {
121
+ this.v2SubgraphProvider = v2SubgraphProvider;
122
+ }
123
+ else {
124
+ this.v2SubgraphProvider = new providers_2.V2SubgraphProviderWithFallBacks([
125
+ new providers_2.CachingV2SubgraphProvider(chainId, new providers_2.URISubgraphProvider(chainId, `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v2/${chainName}.json`, undefined, 0), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 300, useClones: false }))),
126
+ new providers_2.StaticV2SubgraphProvider(chainId),
127
+ ]);
128
+ }
129
+ if (v3SubgraphProvider) {
130
+ this.v3SubgraphProvider = v3SubgraphProvider;
131
+ }
132
+ else {
133
+ this.v3SubgraphProvider = new providers_2.V3SubgraphProviderWithFallBacks([
134
+ new providers_2.CachingV3SubgraphProvider(chainId, new providers_2.URISubgraphProvider(chainId, `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v3/${chainName}.json`, undefined, 0), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 300, useClones: false }))),
135
+ new providers_2.StaticV3SubgraphProvider(chainId, this.v3PoolProvider),
136
+ ]);
137
+ }
138
+ // if (v4SubgraphProvider) {
139
+ // this.v4SubgraphProvider = v4SubgraphProvider;
140
+ // } else {
141
+ // this.v4SubgraphProvider = new V4SubgraphProviderWithFallBacks([
142
+ // new CachingV4SubgraphProvider(
143
+ // chainId,
144
+ // new URISubgraphProvider(
145
+ // chainId,
146
+ // `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v4/${chainName}.json`,
147
+ // undefined,
148
+ // 0
149
+ // ),
150
+ // new NodeJSCache(new NodeCache({ stdTTL: 300, useClones: false }))
151
+ // ),
152
+ // new StaticV4SubgraphProvider(chainId, this.v4PoolProvider),
153
+ // ]);
154
+ // }
155
+ let gasPriceProviderInstance;
156
+ if (providers_1.JsonRpcProvider.isProvider(this.provider)) {
157
+ gasPriceProviderInstance = new providers_2.OnChainGasPriceProvider(chainId, new providers_2.EIP1559GasPriceProvider(this.provider), new providers_2.LegacyGasPriceProvider(this.provider));
158
+ }
159
+ else {
160
+ gasPriceProviderInstance = new providers_2.ETHGasStationInfoProvider(config_1.ETH_GAS_STATION_API_URL);
161
+ }
162
+ this.gasPriceProvider =
163
+ gasPriceProvider !== null && gasPriceProvider !== void 0 ? gasPriceProvider : new providers_2.CachingGasStationProvider(chainId, gasPriceProviderInstance, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 7, useClones: false })));
164
+ // this.v4GasModelFactory =
165
+ // v4GasModelFactory ?? new V4HeuristicGasModelFactory(this.provider);
166
+ this.v3GasModelFactory =
167
+ v3GasModelFactory !== null && v3GasModelFactory !== void 0 ? v3GasModelFactory : new v3_heuristic_gas_model_1.V3HeuristicGasModelFactory(this.provider);
168
+ this.v2GasModelFactory =
169
+ v2GasModelFactory !== null && v2GasModelFactory !== void 0 ? v2GasModelFactory : new v2_heuristic_gas_model_1.V2HeuristicGasModelFactory(this.provider);
170
+ this.mixedRouteGasModelFactory =
171
+ mixedRouteGasModelFactory !== null && mixedRouteGasModelFactory !== void 0 ? mixedRouteGasModelFactory : new mixed_route_heuristic_gas_model_1.MixedRouteHeuristicGasModelFactory();
172
+ this.swapRouterProvider =
173
+ swapRouterProvider !== null && swapRouterProvider !== void 0 ? swapRouterProvider : new providers_2.SwapRouterProvider(this.multicall2Provider, this.chainId);
174
+ if (
175
+ // chainId === ChainId.ARBITRUM_ONE || // ARBITRUM chains removed
176
+ // chainId === ChainId.ARBITRUM_GOERLI
177
+ false) {
178
+ this.l2GasDataProvider =
179
+ arbitrumGasDataProvider !== null && arbitrumGasDataProvider !== void 0 ? arbitrumGasDataProvider : new gas_data_provider_1.ArbitrumGasDataProvider(chainId, this.provider);
180
+ }
181
+ // Initialize the Quoters.
182
+ // Quoters are an abstraction encapsulating the business logic of fetching routes and quotes.
183
+ this.v2Quoter = new quoters_1.V2Quoter(this.v2SubgraphProvider, this.v2PoolProvider, this.v2QuoteProvider, this.v2GasModelFactory, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider, this.l2GasDataProvider);
184
+ this.v3Quoter = new quoters_1.V3Quoter(this.v3SubgraphProvider, this.v3PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
185
+ // this.v4Quoter = new V4Quoter(
186
+ // this.v4SubgraphProvider,
187
+ // this.v4PoolProvider,
188
+ // this.onChainQuoteProvider,
189
+ // this.tokenProvider,
190
+ // this.chainId,
191
+ // this.blockedTokenListProvider,
192
+ // this.tokenValidatorProvider
193
+ // );
194
+ this.mixedQuoter = new quoters_1.MixedQuoter(
195
+ // this.v4SubgraphProvider,
196
+ // this.v4PoolProvider,
197
+ this.v3SubgraphProvider, this.v3PoolProvider, this.v2SubgraphProvider, this.v2PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
198
+ this.v2Supported = v2Supported !== null && v2Supported !== void 0 ? v2Supported : chains_1.V2_SUPPORTED;
199
+ // this.v4Supported = v4Supported ?? V4_SUPPORTED;
200
+ this.universalRouterVersion =
201
+ universalRouterVersion !== null && universalRouterVersion !== void 0 ? universalRouterVersion : universal_router_sdk_1.UniversalRouterVersion.V1_2;
202
+ }
203
+ async routeToRatio(token0Balance, token1Balance, position, swapAndAddConfig, swapAndAddOptions, routingConfig = (0, config_1.DEFAULT_ROUTING_CONFIG_BY_CHAIN)(this.chainId)) {
204
+ if (token1Balance.currency.wrapped.sortsBefore(token0Balance.currency.wrapped)) {
205
+ [token0Balance, token1Balance] = [token1Balance, token0Balance];
206
+ }
207
+ let preSwapOptimalRatio = this.calculateOptimalRatio(position, position.pool.sqrtRatioX96, true);
208
+ // set up parameters according to which token will be swapped
209
+ let zeroForOne;
210
+ if (position.pool.tickCurrent > position.tickUpper) {
211
+ zeroForOne = true;
212
+ }
213
+ else if (position.pool.tickCurrent < position.tickLower) {
214
+ zeroForOne = false;
215
+ }
216
+ else {
217
+ zeroForOne = new sdk_core_1.Fraction(token0Balance.quotient, token1Balance.quotient).greaterThan(preSwapOptimalRatio);
218
+ if (!zeroForOne)
219
+ preSwapOptimalRatio = preSwapOptimalRatio.invert();
220
+ }
221
+ const [inputBalance, outputBalance] = zeroForOne
222
+ ? [token0Balance, token1Balance]
223
+ : [token1Balance, token0Balance];
224
+ let optimalRatio = preSwapOptimalRatio;
225
+ let postSwapTargetPool = position.pool;
226
+ let exchangeRate = zeroForOne
227
+ ? position.pool.token0Price
228
+ : position.pool.token1Price;
229
+ let swap = null;
230
+ let ratioAchieved = false;
231
+ let n = 0;
232
+ // iterate until we find a swap with a sufficient ratio or return null
233
+ while (!ratioAchieved) {
234
+ n++;
235
+ if (n > swapAndAddConfig.maxIterations) {
236
+ log_1.log.info('max iterations exceeded');
237
+ return {
238
+ status: router_1.SwapToRatioStatus.NO_ROUTE_FOUND,
239
+ error: 'max iterations exceeded',
240
+ };
241
+ }
242
+ const amountToSwap = (0, calculate_ratio_amount_in_1.calculateRatioAmountIn)(optimalRatio, exchangeRate, inputBalance, outputBalance);
243
+ if (amountToSwap.equalTo(0)) {
244
+ log_1.log.info(`no swap needed: amountToSwap = 0`);
245
+ return {
246
+ status: router_1.SwapToRatioStatus.NO_SWAP_NEEDED,
247
+ };
248
+ }
249
+ swap = await this.route(amountToSwap, outputBalance.currency, sdk_core_1.TradeType.EXACT_INPUT, undefined, Object.assign(Object.assign(Object.assign({}, (0, config_1.DEFAULT_ROUTING_CONFIG_BY_CHAIN)(this.chainId)), routingConfig), {
250
+ /// @dev We do not want to query for mixedRoutes for routeToRatio as they are not supported
251
+ /// [Protocol.V3, Protocol.V2] will make sure we only query for V3 and V2
252
+ protocols: [router_sdk_1.Protocol.V3, router_sdk_1.Protocol.V2] }));
253
+ if (!swap) {
254
+ log_1.log.info('no route found from this.route()');
255
+ return {
256
+ status: router_1.SwapToRatioStatus.NO_ROUTE_FOUND,
257
+ error: 'no route found',
258
+ };
259
+ }
260
+ const inputBalanceUpdated = inputBalance.subtract(swap.trade.inputAmount);
261
+ const outputBalanceUpdated = outputBalance.add(swap.trade.outputAmount);
262
+ const newRatio = inputBalanceUpdated.divide(outputBalanceUpdated);
263
+ let targetPoolPriceUpdate;
264
+ swap.route.forEach((route) => {
265
+ if (route.protocol === router_sdk_1.Protocol.V3) {
266
+ const v3Route = route;
267
+ v3Route.route.pools.forEach((pool, i) => {
268
+ if (pool.token0.equals(position.pool.token0) &&
269
+ pool.token1.equals(position.pool.token1) &&
270
+ pool.fee === position.pool.fee) {
271
+ targetPoolPriceUpdate = jsbi_1.default.BigInt(v3Route.sqrtPriceX96AfterList[i].toString());
272
+ optimalRatio = this.calculateOptimalRatio(position, jsbi_1.default.BigInt(targetPoolPriceUpdate.toString()), zeroForOne);
273
+ }
274
+ });
275
+ }
276
+ });
277
+ if (!targetPoolPriceUpdate) {
278
+ optimalRatio = preSwapOptimalRatio;
279
+ }
280
+ ratioAchieved =
281
+ newRatio.equalTo(optimalRatio) ||
282
+ this.absoluteValue(newRatio.asFraction.divide(optimalRatio).subtract(1)).lessThan(swapAndAddConfig.ratioErrorTolerance);
283
+ if (ratioAchieved && targetPoolPriceUpdate) {
284
+ postSwapTargetPool = new v3_sdk_1.Pool(position.pool.token0, position.pool.token1, position.pool.fee, targetPoolPriceUpdate, position.pool.liquidity, v3_sdk_1.TickMath.getTickAtSqrtRatio(targetPoolPriceUpdate), position.pool.tickDataProvider);
285
+ }
286
+ exchangeRate = swap.trade.outputAmount.divide(swap.trade.inputAmount);
287
+ log_1.log.info({
288
+ exchangeRate: exchangeRate.asFraction.toFixed(18),
289
+ optimalRatio: optimalRatio.asFraction.toFixed(18),
290
+ newRatio: newRatio.asFraction.toFixed(18),
291
+ inputBalanceUpdated: inputBalanceUpdated.asFraction.toFixed(18),
292
+ outputBalanceUpdated: outputBalanceUpdated.asFraction.toFixed(18),
293
+ ratioErrorTolerance: swapAndAddConfig.ratioErrorTolerance.toFixed(18),
294
+ iterationN: n.toString(),
295
+ }, 'QuoteToRatio Iteration Parameters');
296
+ if (exchangeRate.equalTo(0)) {
297
+ log_1.log.info('exchangeRate to 0');
298
+ return {
299
+ status: router_1.SwapToRatioStatus.NO_ROUTE_FOUND,
300
+ error: 'insufficient liquidity to swap to optimal ratio',
301
+ };
302
+ }
303
+ }
304
+ if (!swap) {
305
+ return {
306
+ status: router_1.SwapToRatioStatus.NO_ROUTE_FOUND,
307
+ error: 'no route found',
308
+ };
309
+ }
310
+ let methodParameters;
311
+ if (swapAndAddOptions) {
312
+ methodParameters = await this.buildSwapAndAddMethodParameters(swap.trade, swapAndAddOptions, {
313
+ initialBalanceTokenIn: inputBalance,
314
+ initialBalanceTokenOut: outputBalance,
315
+ preLiquidityPosition: position,
316
+ });
317
+ }
318
+ return {
319
+ status: router_1.SwapToRatioStatus.SUCCESS,
320
+ result: Object.assign(Object.assign({}, swap), { methodParameters, optimalRatio, postSwapTargetPool }),
321
+ };
322
+ }
323
+ /**
324
+ * @inheritdoc IRouter
325
+ */
326
+ async route(amount, quoteCurrency, tradeType, swapConfig, partialRoutingConfig = {}) {
327
+ var _a, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
328
+ const originalAmount = amount;
329
+ const { currencyIn, currencyOut } = this.determineCurrencyInOutFromTradeType(tradeType, amount, quoteCurrency);
330
+ const tokenIn = currencyIn.wrapped;
331
+ const tokenOut = currencyOut.wrapped;
332
+ const tokenOutProperties = await this.tokenPropertiesProvider.getTokensProperties([currencyOut], partialRoutingConfig);
333
+ const feeTakenOnTransfer = (_c = (_a = tokenOutProperties[(0, util_1.getAddressLowerCase)(currencyOut)]) === null || _a === void 0 ? void 0 : _a.tokenFeeResult) === null || _c === void 0 ? void 0 : _c.feeTakenOnTransfer;
334
+ const externalTransferFailed = (_e = (_d = tokenOutProperties[(0, util_1.getAddressLowerCase)(currencyOut)]) === null || _d === void 0 ? void 0 : _d.tokenFeeResult) === null || _e === void 0 ? void 0 : _e.externalTransferFailed;
335
+ // We want to log the fee on transfer output tokens that we are taking fee or not
336
+ // Ideally the trade size (normalized in USD) would be ideal to log here, but we don't have spot price of output tokens here.
337
+ // We have to make sure token out is FOT with either buy/sell fee bps > 0
338
+ if (((_h = (_g = (_f = tokenOutProperties[(0, util_1.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)) ||
339
+ ((_l = (_k = (_j = tokenOutProperties[(0, util_1.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))) {
340
+ if (feeTakenOnTransfer || externalTransferFailed) {
341
+ // also to be extra safe, in case of FOT with feeTakenOnTransfer or externalTransferFailed,
342
+ // we nullify the fee and flat fee to avoid any potential issues.
343
+ // although neither web nor wallet should use the calldata returned from routing/SOR
344
+ if ((swapConfig === null || swapConfig === void 0 ? void 0 : swapConfig.type) === router_1.SwapType.UNIVERSAL_ROUTER) {
345
+ swapConfig.fee = undefined;
346
+ swapConfig.flatFee = undefined;
347
+ }
348
+ metric_1.metric.putMetric('TokenOutFeeOnTransferNotTakingFee', 1, metric_1.MetricLoggerUnit.Count);
349
+ }
350
+ else {
351
+ metric_1.metric.putMetric('TokenOutFeeOnTransferTakingFee', 1, metric_1.MetricLoggerUnit.Count);
352
+ }
353
+ }
354
+ if (tradeType === sdk_core_1.TradeType.EXACT_OUTPUT) {
355
+ const portionAmount = this.portionProvider.getPortionAmount(amount, tradeType, feeTakenOnTransfer, externalTransferFailed, swapConfig);
356
+ if (portionAmount && portionAmount.greaterThan(router_sdk_1.ZERO)) {
357
+ // In case of exact out swap, before we route, we need to make sure that the
358
+ // token out amount accounts for flat portion, and token in amount after the best swap route contains the token in equivalent of portion.
359
+ // 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.
360
+ // This is because instead of the swapper being responsible for the portion,
361
+ // the pool instead gets responsible for the portion.
362
+ // The addition below avoids that situation.
363
+ amount = amount.add(portionAmount);
364
+ }
365
+ }
366
+ metric_1.metric.setProperty('chainId', this.chainId);
367
+ metric_1.metric.setProperty('pair', `${currencyIn.symbol}/${currencyOut.symbol}`);
368
+ metric_1.metric.setProperty('tokenIn', (0, util_1.getAddress)(currencyIn));
369
+ metric_1.metric.setProperty('tokenOut', (0, util_1.getAddress)(currencyOut));
370
+ metric_1.metric.setProperty('tradeType', tradeType === sdk_core_1.TradeType.EXACT_INPUT ? 'ExactIn' : 'ExactOut');
371
+ metric_1.metric.putMetric(`QuoteRequestedForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
372
+ // Get a block number to specify in all our calls. Ensures data we fetch from chain is
373
+ // from the same block.
374
+ const blockNumber = (_m = partialRoutingConfig.blockNumber) !== null && _m !== void 0 ? _m : this.getBlockNumberPromise();
375
+ const routingConfig = lodash_1.default.merge({
376
+ // These settings could be changed by the partialRoutingConfig
377
+ useCachedRoutes: true,
378
+ writeToCachedRoutes: true,
379
+ optimisticCachedRoutes: false,
380
+ }, (0, config_1.DEFAULT_ROUTING_CONFIG_BY_CHAIN)(this.chainId), partialRoutingConfig, { blockNumber });
381
+ if (routingConfig.debugRouting) {
382
+ log_1.log.warn(`Finalized routing config is ${JSON.stringify(routingConfig)}`);
383
+ }
384
+ const gasPriceWei = await this.getGasPriceWei(await blockNumber, await partialRoutingConfig.blockNumber);
385
+ const quoteToken = quoteCurrency.wrapped;
386
+ // const gasTokenAccessor = await this.tokenProvider.getTokens([routingConfig.gasToken!]);
387
+ const gasToken = routingConfig.gasToken
388
+ ? (await this.tokenProvider.getTokens([routingConfig.gasToken])).getTokenByAddress(routingConfig.gasToken)
389
+ : undefined;
390
+ const providerConfig = Object.assign(Object.assign({}, routingConfig), { blockNumber, additionalGasOverhead: (0, gas_costs_1.NATIVE_OVERHEAD)(this.chainId, amount.currency, quoteCurrency), gasToken,
391
+ externalTransferFailed,
392
+ feeTakenOnTransfer });
393
+ const { v2GasModel: v2GasModel, v3GasModel: v3GasModel,
394
+ // v4GasModel: v4GasModel,
395
+ mixedRouteGasModel: mixedRouteGasModel, } = await this.getGasModels(gasPriceWei, amount.currency.wrapped, quoteToken, providerConfig);
396
+ // Create a Set to sanitize the protocols input, a Set of undefined becomes an empty set,
397
+ // Then create an Array from the values of that Set.
398
+ const protocols = Array.from(new Set(routingConfig.protocols).values());
399
+ 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, quoteToken, tradeType, protocols)));
400
+ // Fetch CachedRoutes
401
+ let cachedRoutes;
402
+ if (routingConfig.useCachedRoutes && cacheMode !== providers_2.CacheMode.Darkmode) {
403
+ cachedRoutes = await ((_q = this.routeCachingProvider) === null || _q === void 0 ? void 0 : _q.getCachedRoute(this.chainId, amount, quoteToken, tradeType, protocols, await blockNumber, routingConfig.optimisticCachedRoutes));
404
+ }
405
+ if ((0, util_1.shouldWipeoutCachedRoutes)(cachedRoutes, routingConfig)) {
406
+ cachedRoutes = undefined;
407
+ }
408
+ metric_1.metric.putMetric(routingConfig.useCachedRoutes
409
+ ? 'GetQuoteUsingCachedRoutes'
410
+ : 'GetQuoteNotUsingCachedRoutes', 1, metric_1.MetricLoggerUnit.Count);
411
+ if (cacheMode &&
412
+ routingConfig.useCachedRoutes &&
413
+ cacheMode !== providers_2.CacheMode.Darkmode &&
414
+ !cachedRoutes) {
415
+ metric_1.metric.putMetric(`GetCachedRoute_miss_${cacheMode}`, 1, metric_1.MetricLoggerUnit.Count);
416
+ log_1.log.info({
417
+ tokenIn: tokenIn.symbol,
418
+ tokenInAddress: tokenIn.address,
419
+ tokenOut: tokenOut.symbol,
420
+ tokenOutAddress: tokenOut.address,
421
+ cacheMode,
422
+ amount: amount.toExact(),
423
+ chainId: this.chainId,
424
+ tradeType: this.tradeTypeStr(tradeType),
425
+ }, `GetCachedRoute miss ${cacheMode} for ${this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType)}`);
426
+ }
427
+ else if (cachedRoutes && routingConfig.useCachedRoutes) {
428
+ metric_1.metric.putMetric(`GetCachedRoute_hit_${cacheMode}`, 1, metric_1.MetricLoggerUnit.Count);
429
+ log_1.log.info({
430
+ tokenIn: tokenIn.symbol,
431
+ tokenInAddress: tokenIn.address,
432
+ tokenOut: tokenOut.symbol,
433
+ tokenOutAddress: tokenOut.address,
434
+ cacheMode,
435
+ amount: amount.toExact(),
436
+ chainId: this.chainId,
437
+ tradeType: this.tradeTypeStr(tradeType),
438
+ }, `GetCachedRoute hit ${cacheMode} for ${this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType)}`);
439
+ }
440
+ let swapRouteFromCachePromise = Promise.resolve(null);
441
+ if (cachedRoutes) {
442
+ swapRouteFromCachePromise = this.getSwapRouteFromCache(tokenIn, tokenOut, cachedRoutes, await blockNumber, amount, quoteToken, tradeType, routingConfig, v3GasModel,
443
+ // v4GasModel,
444
+ mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig);
445
+ }
446
+ let swapRouteFromChainPromise = Promise.resolve(null);
447
+ if (!cachedRoutes || cacheMode !== providers_2.CacheMode.Livemode) {
448
+ swapRouteFromChainPromise = this.getSwapRouteFromChain(amount, tokenIn, tokenOut, protocols, quoteToken, tradeType, routingConfig, v3GasModel,
449
+ // v4GasModel,
450
+ mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig);
451
+ }
452
+ const [swapRouteFromCache, swapRouteFromChain] = await Promise.all([
453
+ swapRouteFromCachePromise,
454
+ swapRouteFromChainPromise,
455
+ ]);
456
+ let swapRouteRaw;
457
+ let hitsCachedRoute = false;
458
+ if (cacheMode === providers_2.CacheMode.Livemode && swapRouteFromCache) {
459
+ log_1.log.info(`CacheMode is ${cacheMode}, and we are using swapRoute from cache`);
460
+ hitsCachedRoute = true;
461
+ swapRouteRaw = swapRouteFromCache;
462
+ }
463
+ else {
464
+ log_1.log.info(`CacheMode is ${cacheMode}, and we are using materialized swapRoute`);
465
+ swapRouteRaw = swapRouteFromChain;
466
+ }
467
+ if (cacheMode === providers_2.CacheMode.Tapcompare &&
468
+ swapRouteFromCache &&
469
+ swapRouteFromChain) {
470
+ const quoteDiff = swapRouteFromChain.quote.subtract(swapRouteFromCache.quote);
471
+ const quoteGasAdjustedDiff = swapRouteFromChain.quoteGasAdjusted.subtract(swapRouteFromCache.quoteGasAdjusted);
472
+ const gasUsedDiff = swapRouteFromChain.estimatedGasUsed.sub(swapRouteFromCache.estimatedGasUsed);
473
+ // Only log if quoteDiff is different from 0, or if quoteGasAdjustedDiff and gasUsedDiff are both different from 0
474
+ if (!quoteDiff.equalTo(0) ||
475
+ !(quoteGasAdjustedDiff.equalTo(0) || gasUsedDiff.eq(0))) {
476
+ try {
477
+ // Calculates the percentage of the difference with respect to the quoteFromChain (not from cache)
478
+ const misquotePercent = quoteGasAdjustedDiff
479
+ .divide(swapRouteFromChain.quoteGasAdjusted)
480
+ .multiply(100);
481
+ metric_1.metric.putMetric(`TapcompareCachedRoute_quoteGasAdjustedDiffPercent`, Number(misquotePercent.toExact()), metric_1.MetricLoggerUnit.Percent);
482
+ log_1.log.warn({
483
+ quoteFromChain: swapRouteFromChain.quote.toExact(),
484
+ quoteFromCache: swapRouteFromCache.quote.toExact(),
485
+ quoteDiff: quoteDiff.toExact(),
486
+ quoteGasAdjustedFromChain: swapRouteFromChain.quoteGasAdjusted.toExact(),
487
+ quoteGasAdjustedFromCache: swapRouteFromCache.quoteGasAdjusted.toExact(),
488
+ quoteGasAdjustedDiff: quoteGasAdjustedDiff.toExact(),
489
+ gasUsedFromChain: swapRouteFromChain.estimatedGasUsed.toString(),
490
+ gasUsedFromCache: swapRouteFromCache.estimatedGasUsed.toString(),
491
+ gasUsedDiff: gasUsedDiff.toString(),
492
+ routesFromChain: swapRouteFromChain.routes.toString(),
493
+ routesFromCache: swapRouteFromCache.routes.toString(),
494
+ amount: amount.toExact(),
495
+ originalAmount: cachedRoutes === null || cachedRoutes === void 0 ? void 0 : cachedRoutes.originalAmount,
496
+ pair: this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType),
497
+ blockNumber,
498
+ }, `Comparing quotes between Chain and Cache for ${this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType)}`);
499
+ }
500
+ catch (error) {
501
+ // This is in response to the 'division by zero' error
502
+ // during https://uniswapteam.slack.com/archives/C059TGEC57W/p1723997015399579
503
+ if (error instanceof RangeError &&
504
+ error.message.includes('Division by zero')) {
505
+ log_1.log.error({
506
+ quoteGasAdjustedDiff: quoteGasAdjustedDiff.toExact(),
507
+ swapRouteFromChainQuoteGasAdjusted: swapRouteFromChain.quoteGasAdjusted.toExact(),
508
+ }, 'Error calculating misquote percent');
509
+ metric_1.metric.putMetric(`TapcompareCachedRoute_quoteGasAdjustedDiffPercent_divzero`, 1, metric_1.MetricLoggerUnit.Count);
510
+ }
511
+ // Log but don't throw here - this is only for logging.
512
+ }
513
+ }
514
+ }
515
+ if (!swapRouteRaw) {
516
+ return null;
517
+ }
518
+ const { quote, quoteGasAdjusted, estimatedGasUsed, routes: routeAmounts, estimatedGasUsedQuoteToken, estimatedGasUsedUSD, estimatedGasUsedGasToken, } = swapRouteRaw;
519
+ if (this.routeCachingProvider &&
520
+ routingConfig.writeToCachedRoutes &&
521
+ cacheMode !== providers_2.CacheMode.Darkmode &&
522
+ swapRouteFromChain) {
523
+ // Generate the object to be cached
524
+ const routesToCache = providers_2.CachedRoutes.fromRoutesWithValidQuotes(swapRouteFromChain.routes, this.chainId, tokenIn, tokenOut, protocols.sort(), await blockNumber, tradeType, amount.toExact());
525
+ if (routesToCache) {
526
+ // Attempt to insert the entry in cache. This is fire and forget promise.
527
+ // The catch method will prevent any exception from blocking the normal code execution.
528
+ this.routeCachingProvider
529
+ .setCachedRoute(routesToCache, amount)
530
+ .then((success) => {
531
+ const status = success ? 'success' : 'rejected';
532
+ metric_1.metric.putMetric(`SetCachedRoute_${status}`, 1, metric_1.MetricLoggerUnit.Count);
533
+ })
534
+ .catch((reason) => {
535
+ log_1.log.error({
536
+ reason: reason,
537
+ tokenPair: this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType),
538
+ }, `SetCachedRoute failure`);
539
+ metric_1.metric.putMetric(`SetCachedRoute_failure`, 1, metric_1.MetricLoggerUnit.Count);
540
+ });
541
+ }
542
+ else {
543
+ metric_1.metric.putMetric(`SetCachedRoute_unnecessary`, 1, metric_1.MetricLoggerUnit.Count);
544
+ }
545
+ }
546
+ metric_1.metric.putMetric(`QuoteFoundForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
547
+ // Build Trade object that represents the optimal swap.
548
+ const trade = (0, methodParameters_1.buildTrade)(currencyIn, currencyOut, tradeType, routeAmounts);
549
+ let methodParameters;
550
+ // If user provided recipient, deadline etc. we also generate the calldata required to execute
551
+ // the swap and return it too.
552
+ if (swapConfig) {
553
+ methodParameters = (0, methodParameters_1.buildSwapMethodParameters)(trade, swapConfig, this.chainId);
554
+ }
555
+ const tokenOutAmount = tradeType === sdk_core_1.TradeType.EXACT_OUTPUT
556
+ ? originalAmount // we need to pass in originalAmount instead of amount, because amount already added portionAmount in case of exact out swap
557
+ : quote;
558
+ const portionAmount = this.portionProvider.getPortionAmount(tokenOutAmount, tradeType, feeTakenOnTransfer, externalTransferFailed, swapConfig);
559
+ 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
560
+ portionAmount);
561
+ // we need to correct quote and quote gas adjusted for exact output when portion is part of the exact out swap
562
+ const correctedQuote = this.portionProvider.getQuote(tradeType, quote, portionQuoteAmount);
563
+ const correctedQuoteGasAdjusted = this.portionProvider.getQuoteGasAdjusted(tradeType, quoteGasAdjusted, portionQuoteAmount);
564
+ const quoteGasAndPortionAdjusted = this.portionProvider.getQuoteGasAndPortionAdjusted(tradeType, quoteGasAdjusted, portionAmount);
565
+ const swapRoute = {
566
+ quote: correctedQuote,
567
+ quoteGasAdjusted: correctedQuoteGasAdjusted,
568
+ estimatedGasUsed,
569
+ estimatedGasUsedQuoteToken,
570
+ estimatedGasUsedUSD,
571
+ estimatedGasUsedGasToken,
572
+ gasPriceWei,
573
+ route: routeAmounts,
574
+ trade,
575
+ methodParameters,
576
+ blockNumber: bignumber_1.BigNumber.from(await blockNumber),
577
+ hitsCachedRoute: hitsCachedRoute,
578
+ portionAmount: portionAmount,
579
+ quoteGasAndPortionAdjusted: quoteGasAndPortionAdjusted,
580
+ };
581
+ if (swapConfig &&
582
+ swapConfig.simulate &&
583
+ methodParameters &&
584
+ methodParameters.calldata) {
585
+ if (!this.simulator) {
586
+ throw new Error('Simulator not initialized!');
587
+ }
588
+ log_1.log.info(JSON.stringify({ swapConfig, methodParameters, providerConfig }, null, 2), `Starting simulation`);
589
+ const fromAddress = swapConfig.simulate.fromAddress;
590
+ const beforeSimulate = Date.now();
591
+ const swapRouteWithSimulation = await this.simulator.simulate(fromAddress, swapConfig, swapRoute, amount,
592
+ // Quote will be in WETH even if quoteCurrency is ETH
593
+ // So we init a new CurrencyAmount object here
594
+ amounts_1.CurrencyAmount.fromRawAmount(quoteCurrency, quote.quotient.toString()), providerConfig);
595
+ metric_1.metric.putMetric('SimulateTransaction', Date.now() - beforeSimulate, metric_1.MetricLoggerUnit.Milliseconds);
596
+ return swapRouteWithSimulation;
597
+ }
598
+ return swapRoute;
599
+ }
600
+ async getSwapRouteFromCache(tokenIn, tokenOut, cachedRoutes, blockNumber, amount, quoteToken, tradeType, routingConfig, v3GasModel,
601
+ // v4GasModel: IGasModel<V4RouteWithValidQuote>,
602
+ mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig) {
603
+ var _a, _c, _d, _e, _f, _g;
604
+ const tokenPairProperties = await this.tokenPropertiesProvider.getTokensProperties([tokenIn, tokenOut], providerConfig);
605
+ const sellTokenIsFot = (_d = (_c = (_a = tokenPairProperties[tokenIn.address.toLowerCase()]) === 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);
606
+ const buyTokenIsFot = (_g = (_f = (_e = tokenPairProperties[tokenOut.address.toLowerCase()]) === 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);
607
+ const fotInDirectSwap = sellTokenIsFot || buyTokenIsFot;
608
+ log_1.log.info({
609
+ protocols: cachedRoutes.protocolsCovered,
610
+ tradeType: cachedRoutes.tradeType,
611
+ cachedBlockNumber: cachedRoutes.blockNumber,
612
+ quoteBlockNumber: blockNumber,
613
+ }, 'Routing across CachedRoute');
614
+ const quotePromises = [];
615
+ // const v4Routes = cachedRoutes.routes.filter(
616
+ // (route) => route.protocol === Protocol.V4
617
+ // );
618
+ const v3Routes = cachedRoutes.routes.filter((route) => route.protocol === router_sdk_1.Protocol.V3);
619
+ const v2Routes = cachedRoutes.routes.filter((route) => route.protocol === router_sdk_1.Protocol.V2);
620
+ const mixedRoutes = cachedRoutes.routes.filter((route) => route.protocol === router_sdk_1.Protocol.MIXED);
621
+ let percents;
622
+ let amounts;
623
+ if (cachedRoutes.routes.length > 1) {
624
+ // If we have more than 1 route, we will quote the different percents for it, following the regular process
625
+ [percents, amounts] = this.getAmountDistribution(amount, routingConfig);
626
+ }
627
+ else if (cachedRoutes.routes.length == 1) {
628
+ [percents, amounts] = [[100], [amount]];
629
+ }
630
+ else {
631
+ // In this case this means that there's no route, so we return null
632
+ return Promise.resolve(null);
633
+ }
634
+ // if (v4Routes.length > 0) {
635
+ // const v4RoutesFromCache: V4Route[] = v4Routes.map(
636
+ // (cachedRoute) => cachedRoute.route as V4Route
637
+ // );
638
+ // metric.putMetric(
639
+ // 'SwapRouteFromCache_V4_GetQuotes_Request',
640
+ // 1,
641
+ // MetricLoggerUnit.Count
642
+ // );
643
+ // const beforeGetQuotes = Date.now();
644
+ // quotePromises.push(
645
+ // this.v4Quoter
646
+ // .getQuotes(
647
+ // v4RoutesFromCache,
648
+ // amounts,
649
+ // percents,
650
+ // quoteToken,
651
+ // tradeType,
652
+ // routingConfig,
653
+ // undefined,
654
+ // v4GasModel
655
+ // )
656
+ // .then((result) => {
657
+ // metric.putMetric(
658
+ // `SwapRouteFromCache_V4_GetQuotes_Load`,
659
+ // Date.now() - beforeGetQuotes,
660
+ // MetricLoggerUnit.Milliseconds
661
+ // );
662
+ // return result;
663
+ // })
664
+ // );
665
+ // }
666
+ if (!fotInDirectSwap) {
667
+ if (v3Routes.length > 0) {
668
+ const v3RoutesFromCache = v3Routes.map((cachedRoute) => cachedRoute.route);
669
+ metric_1.metric.putMetric('SwapRouteFromCache_V3_GetQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
670
+ const beforeGetQuotes = Date.now();
671
+ quotePromises.push(this.v3Quoter
672
+ .getQuotes(v3RoutesFromCache, amounts, percents, quoteToken, tradeType, routingConfig, undefined, v3GasModel)
673
+ .then((result) => {
674
+ metric_1.metric.putMetric(`SwapRouteFromCache_V3_GetQuotes_Load`, Date.now() - beforeGetQuotes, metric_1.MetricLoggerUnit.Milliseconds);
675
+ return result;
676
+ }));
677
+ }
678
+ }
679
+ if (v2Routes.length > 0) {
680
+ const v2RoutesFromCache = v2Routes.map((cachedRoute) => cachedRoute.route);
681
+ metric_1.metric.putMetric('SwapRouteFromCache_V2_GetQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
682
+ const beforeGetQuotes = Date.now();
683
+ quotePromises.push(this.v2Quoter
684
+ .refreshRoutesThenGetQuotes(cachedRoutes.currencyIn.wrapped, cachedRoutes.currencyOut.wrapped, v2RoutesFromCache, amounts, percents, quoteToken, tradeType, routingConfig, gasPriceWei)
685
+ .then((result) => {
686
+ metric_1.metric.putMetric(`SwapRouteFromCache_V2_GetQuotes_Load`, Date.now() - beforeGetQuotes, metric_1.MetricLoggerUnit.Milliseconds);
687
+ return result;
688
+ }));
689
+ }
690
+ if (!fotInDirectSwap) {
691
+ if (mixedRoutes.length > 0) {
692
+ const mixedRoutesFromCache = mixedRoutes.map((cachedRoute) => cachedRoute.route);
693
+ metric_1.metric.putMetric('SwapRouteFromCache_Mixed_GetQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
694
+ const beforeGetQuotes = Date.now();
695
+ quotePromises.push(this.mixedQuoter
696
+ .getQuotes(mixedRoutesFromCache, amounts, percents, quoteToken, tradeType, routingConfig, undefined, mixedRouteGasModel)
697
+ .then((result) => {
698
+ metric_1.metric.putMetric(`SwapRouteFromCache_Mixed_GetQuotes_Load`, Date.now() - beforeGetQuotes, metric_1.MetricLoggerUnit.Milliseconds);
699
+ return result;
700
+ }));
701
+ }
702
+ }
703
+ const getQuotesResults = await Promise.all(quotePromises);
704
+ const allRoutesWithValidQuotes = lodash_1.default.flatMap(getQuotesResults, (quoteResult) => quoteResult.routesWithValidQuotes);
705
+ return (0, best_swap_route_1.getBestSwapRoute)(amount, percents, allRoutesWithValidQuotes, tradeType, this.chainId, routingConfig, this.portionProvider, v2GasModel, v3GasModel,
706
+ // v4GasModel,
707
+ swapConfig, providerConfig);
708
+ }
709
+ async getSwapRouteFromChain(amount, tokenIn, tokenOut, protocols, quoteToken, tradeType, routingConfig, v3GasModel,
710
+ // v4GasModel: IGasModel<V4RouteWithValidQuote>,
711
+ mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig) {
712
+ var _a, _c, _d, _e, _f, _g, _h;
713
+ const tokenPairProperties = await this.tokenPropertiesProvider.getTokensProperties([tokenIn, tokenOut], providerConfig);
714
+ const sellTokenIsFot = (_d = (_c = (_a = tokenPairProperties[tokenIn.address.toLowerCase()]) === 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);
715
+ const buyTokenIsFot = (_g = (_f = (_e = tokenPairProperties[tokenOut.address.toLowerCase()]) === 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);
716
+ const fotInDirectSwap = sellTokenIsFot || buyTokenIsFot;
717
+ // Generate our distribution of amounts, i.e. fractions of the input amount.
718
+ // We will get quotes for fractions of the input amount for different routes, then
719
+ // combine to generate split routes.
720
+ const [percents, amounts] = this.getAmountDistribution(amount, routingConfig);
721
+ const noProtocolsSpecified = protocols.length === 0;
722
+ // const v4ProtocolSpecified = protocols.includes(Protocol.V4);
723
+ const v3ProtocolSpecified = protocols.includes(router_sdk_1.Protocol.V3);
724
+ const v2ProtocolSpecified = protocols.includes(router_sdk_1.Protocol.V2);
725
+ const v2SupportedInChain = (_h = this.v2Supported) === null || _h === void 0 ? void 0 : _h.includes(this.chainId);
726
+ // const v4SupportedInChain = this.v4Supported?.includes(this.chainId);
727
+ const shouldQueryMixedProtocol = protocols.includes(router_sdk_1.Protocol.MIXED) ||
728
+ (noProtocolsSpecified && v2SupportedInChain); /* && v4SupportedInChain */
729
+ const mixedProtocolAllowed = [
730
+ // ChainId.MAINNET,
731
+ // ChainId.SEPOLIA,
732
+ // ChainId.GOERLI,
733
+ sdk_core_1.ChainId.CHILIZ,
734
+ sdk_core_1.ChainId.SPICY,
735
+ ].includes(this.chainId) && tradeType === sdk_core_1.TradeType.EXACT_INPUT;
736
+ const beforeGetCandidates = Date.now();
737
+ // let v4CandidatePoolsPromise: Promise<V4CandidatePools | undefined> =
738
+ // Promise.resolve(undefined);
739
+ // we are explicitly requiring people to specify v4 for now
740
+ // if (
741
+ // v4SupportedInChain &&
742
+ // (v4ProtocolSpecified ||
743
+ // noProtocolsSpecified ||
744
+ // (shouldQueryMixedProtocol && mixedProtocolAllowed))
745
+ // ) {
746
+ // // if (v4ProtocolSpecified || noProtocolsSpecified) {
747
+ // v4CandidatePoolsPromise = getV4CandidatePools({
748
+ // currencyIn: tokenIn,
749
+ // currencyOut: tokenOut,
750
+ // tokenProvider: this.tokenProvider,
751
+ // blockedTokenListProvider: this.blockedTokenListProvider,
752
+ // poolProvider: this.v4PoolProvider,
753
+ // routeType: tradeType,
754
+ // subgraphProvider: this.v4SubgraphProvider,
755
+ // routingConfig,
756
+ // chainId: this.chainId,
757
+ // }).then((candidatePools) => {
758
+ // metric.putMetric(
759
+ // 'GetV4CandidatePools',
760
+ // Date.now() - beforeGetCandidates,
761
+ // MetricLoggerUnit.Milliseconds
762
+ // );
763
+ // return candidatePools;
764
+ // });
765
+ // }
766
+ let v3CandidatePoolsPromise = Promise.resolve(undefined);
767
+ if (!fotInDirectSwap) {
768
+ if (v3ProtocolSpecified ||
769
+ noProtocolsSpecified ||
770
+ (shouldQueryMixedProtocol && mixedProtocolAllowed)) {
771
+ v3CandidatePoolsPromise = (0, get_candidate_pools_1.getV3CandidatePools)({
772
+ tokenIn,
773
+ tokenOut,
774
+ tokenProvider: this.tokenProvider,
775
+ blockedTokenListProvider: this.blockedTokenListProvider,
776
+ poolProvider: this.v3PoolProvider,
777
+ routeType: tradeType,
778
+ subgraphProvider: this.v3SubgraphProvider,
779
+ routingConfig,
780
+ chainId: this.chainId,
781
+ }).then((candidatePools) => {
782
+ metric_1.metric.putMetric('GetV3CandidatePools', Date.now() - beforeGetCandidates, metric_1.MetricLoggerUnit.Milliseconds);
783
+ return candidatePools;
784
+ });
785
+ }
786
+ }
787
+ let v2CandidatePoolsPromise = Promise.resolve(undefined);
788
+ if ((v2SupportedInChain && (v2ProtocolSpecified || noProtocolsSpecified)) ||
789
+ (shouldQueryMixedProtocol && mixedProtocolAllowed)) {
790
+ // Fetch all the pools that we will consider routing via. There are thousands
791
+ // of pools, so we filter them to a set of candidate pools that we expect will
792
+ // result in good prices.
793
+ v2CandidatePoolsPromise = (0, get_candidate_pools_1.getV2CandidatePools)({
794
+ tokenIn,
795
+ tokenOut,
796
+ tokenProvider: this.tokenProvider,
797
+ blockedTokenListProvider: this.blockedTokenListProvider,
798
+ poolProvider: this.v2PoolProvider,
799
+ routeType: tradeType,
800
+ subgraphProvider: this.v2SubgraphProvider,
801
+ routingConfig,
802
+ chainId: this.chainId,
803
+ }).then((candidatePools) => {
804
+ metric_1.metric.putMetric('GetV2CandidatePools', Date.now() - beforeGetCandidates, metric_1.MetricLoggerUnit.Milliseconds);
805
+ return candidatePools;
806
+ });
807
+ }
808
+ const quotePromises = [];
809
+ // for v4, for now we explicitly require people to specify
810
+ // if (v4SupportedInChain && v4ProtocolSpecified) {
811
+ // log.info({ protocols, tradeType }, 'Routing across V4');
812
+ // metric.putMetric(
813
+ // 'SwapRouteFromChain_V4_GetRoutesThenQuotes_Request',
814
+ // 1,
815
+ // MetricLoggerUnit.Count
816
+ // );
817
+ // const beforeGetRoutesThenQuotes = Date.now();
818
+ // quotePromises.push(
819
+ // v4CandidatePoolsPromise.then((v4CandidatePools) =>
820
+ // this.v4Quoter
821
+ // .getRoutesThenQuotes(
822
+ // tokenIn,
823
+ // tokenOut,
824
+ // amount,
825
+ // amounts,
826
+ // percents,
827
+ // quoteToken,
828
+ // v4CandidatePools!,
829
+ // tradeType,
830
+ // routingConfig,
831
+ // v3GasModel
832
+ // )
833
+ // .then((result) => {
834
+ // metric.putMetric(
835
+ // `SwapRouteFromChain_V4_GetRoutesThenQuotes_Load`,
836
+ // Date.now() - beforeGetRoutesThenQuotes,
837
+ // MetricLoggerUnit.Milliseconds
838
+ // );
839
+ // return result;
840
+ // })
841
+ // )
842
+ // );
843
+ // }
844
+ if (!fotInDirectSwap) {
845
+ // Maybe Quote V3 - if V3 is specified, or no protocol is specified
846
+ if (v3ProtocolSpecified || noProtocolsSpecified) {
847
+ log_1.log.info({ protocols, tradeType }, 'Routing across V3');
848
+ metric_1.metric.putMetric('SwapRouteFromChain_V3_GetRoutesThenQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
849
+ const beforeGetRoutesThenQuotes = Date.now();
850
+ quotePromises.push(v3CandidatePoolsPromise.then((v3CandidatePools) => this.v3Quoter
851
+ .getRoutesThenQuotes(tokenIn, tokenOut, amount, amounts, percents, quoteToken, v3CandidatePools, tradeType, routingConfig, v3GasModel)
852
+ .then((result) => {
853
+ metric_1.metric.putMetric(`SwapRouteFromChain_V3_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, metric_1.MetricLoggerUnit.Milliseconds);
854
+ return result;
855
+ })));
856
+ }
857
+ }
858
+ // Maybe Quote V2 - if V2 is specified, or no protocol is specified AND v2 is supported in this chain
859
+ if (v2SupportedInChain && (v2ProtocolSpecified || noProtocolsSpecified)) {
860
+ log_1.log.info({ protocols, tradeType }, 'Routing across V2');
861
+ metric_1.metric.putMetric('SwapRouteFromChain_V2_GetRoutesThenQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
862
+ const beforeGetRoutesThenQuotes = Date.now();
863
+ quotePromises.push(v2CandidatePoolsPromise.then((v2CandidatePools) => this.v2Quoter
864
+ .getRoutesThenQuotes(tokenIn, tokenOut, amount, amounts, percents, quoteToken, v2CandidatePools, tradeType, routingConfig, v2GasModel, gasPriceWei)
865
+ .then((result) => {
866
+ metric_1.metric.putMetric(`SwapRouteFromChain_V2_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, metric_1.MetricLoggerUnit.Milliseconds);
867
+ return result;
868
+ })));
869
+ }
870
+ if (!fotInDirectSwap) {
871
+ // Maybe Quote mixed routes
872
+ // if MixedProtocol is specified or no protocol is specified and v2 is supported AND tradeType is ExactIn
873
+ // AND is Mainnet or Gorli
874
+ if (shouldQueryMixedProtocol && mixedProtocolAllowed) {
875
+ log_1.log.info({ protocols, tradeType }, 'Routing across MixedRoutes');
876
+ metric_1.metric.putMetric('SwapRouteFromChain_Mixed_GetRoutesThenQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
877
+ const beforeGetRoutesThenQuotes = Date.now();
878
+ quotePromises.push(Promise.all([
879
+ // v4CandidatePoolsPromise,
880
+ v3CandidatePoolsPromise,
881
+ v2CandidatePoolsPromise,
882
+ ]).then(async ([v3CandidatePools, v2CandidatePools]) => {
883
+ const crossLiquidityPools = await (0, get_candidate_pools_1.getMixedCrossLiquidityCandidatePools)({
884
+ tokenIn,
885
+ tokenOut,
886
+ blockNumber: routingConfig.blockNumber,
887
+ v2SubgraphProvider: this.v2SubgraphProvider,
888
+ v3SubgraphProvider: this.v3SubgraphProvider,
889
+ v2Candidates: v2CandidatePools,
890
+ v3Candidates: v3CandidatePools,
891
+ // v4Candidates: undefined,
892
+ });
893
+ return this.mixedQuoter
894
+ .getRoutesThenQuotes(tokenIn, tokenOut, amount, amounts, percents, quoteToken, [
895
+ // v4CandidatePools!,
896
+ v3CandidatePools,
897
+ v2CandidatePools,
898
+ crossLiquidityPools,
899
+ ], tradeType, routingConfig, mixedRouteGasModel)
900
+ .then((result) => {
901
+ metric_1.metric.putMetric(`SwapRouteFromChain_Mixed_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, metric_1.MetricLoggerUnit.Milliseconds);
902
+ return result;
903
+ });
904
+ }));
905
+ }
906
+ }
907
+ const getQuotesResults = await Promise.all(quotePromises);
908
+ const allRoutesWithValidQuotes = [];
909
+ const allCandidatePools = [];
910
+ getQuotesResults.forEach((getQuoteResult) => {
911
+ if (!getQuoteResult) {
912
+ return;
913
+ }
914
+ allRoutesWithValidQuotes.push(...getQuoteResult.routesWithValidQuotes);
915
+ if (getQuoteResult.candidatePools) {
916
+ allCandidatePools.push(getQuoteResult.candidatePools);
917
+ }
918
+ });
919
+ if (allRoutesWithValidQuotes.length === 0) {
920
+ log_1.log.info({ allRoutesWithValidQuotes }, 'Received no valid quotes');
921
+ return null;
922
+ }
923
+ // Given all the quotes for all the amounts for all the routes, find the best combination.
924
+ const bestSwapRoute = await (0, best_swap_route_1.getBestSwapRoute)(amount, percents, allRoutesWithValidQuotes, tradeType, this.chainId, routingConfig, this.portionProvider, v2GasModel, v3GasModel,
925
+ // v4GasModel,
926
+ swapConfig, providerConfig);
927
+ if (bestSwapRoute) {
928
+ this.emitPoolSelectionMetrics(bestSwapRoute, allCandidatePools);
929
+ }
930
+ return bestSwapRoute;
931
+ }
932
+ tradeTypeStr(tradeType) {
933
+ return tradeType === sdk_core_1.TradeType.EXACT_INPUT ? 'ExactIn' : 'ExactOut';
934
+ }
935
+ tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType) {
936
+ return `${tokenIn.symbol}/${tokenOut.symbol}/${this.tradeTypeStr(tradeType)}/${this.chainId}`;
937
+ }
938
+ determineCurrencyInOutFromTradeType(tradeType, amount, quoteCurrency) {
939
+ if (tradeType === sdk_core_1.TradeType.EXACT_INPUT) {
940
+ return {
941
+ currencyIn: amount.currency,
942
+ currencyOut: quoteCurrency,
943
+ };
944
+ }
945
+ else {
946
+ return {
947
+ currencyIn: quoteCurrency,
948
+ currencyOut: amount.currency,
949
+ };
950
+ }
951
+ }
952
+ async getGasPriceWei(latestBlockNumber, requestBlockNumber) {
953
+ // Track how long it takes to resolve this async call.
954
+ const beforeGasTimestamp = Date.now();
955
+ // Get an estimate of the gas price to use when estimating gas cost of different routes.
956
+ const { gasPriceWei } = await this.gasPriceProvider.getGasPrice(latestBlockNumber, requestBlockNumber);
957
+ metric_1.metric.putMetric('GasPriceLoad', Date.now() - beforeGasTimestamp, metric_1.MetricLoggerUnit.Milliseconds);
958
+ return gasPriceWei;
959
+ }
960
+ async getGasModels(gasPriceWei, amountToken, quoteToken, providerConfig) {
961
+ var _a;
962
+ const beforeGasModel = Date.now();
963
+ const usdPoolPromise = (0, gas_factory_helpers_1.getHighestLiquidityV3USDPool)(this.chainId, this.v3PoolProvider, providerConfig);
964
+ const nativeCurrency = util_1.WRAPPED_NATIVE_CURRENCY[this.chainId];
965
+ const nativeAndQuoteTokenV3PoolPromise = !quoteToken.equals(nativeCurrency)
966
+ ? (0, gas_factory_helpers_1.getHighestLiquidityV3NativePool)(quoteToken, this.v3PoolProvider, providerConfig)
967
+ : Promise.resolve(null);
968
+ const nativeAndAmountTokenV3PoolPromise = !amountToken.equals(nativeCurrency)
969
+ ? (0, gas_factory_helpers_1.getHighestLiquidityV3NativePool)(amountToken, this.v3PoolProvider, providerConfig)
970
+ : Promise.resolve(null);
971
+ // If a specific gas token is specified in the provider config
972
+ // fetch the highest liq V3 pool with it and the native currency
973
+ const nativeAndSpecifiedGasTokenV3PoolPromise = (providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken) &&
974
+ !(providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken.equals(nativeCurrency))
975
+ ? (0, gas_factory_helpers_1.getHighestLiquidityV3NativePool)(providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken, this.v3PoolProvider, providerConfig)
976
+ : Promise.resolve(null);
977
+ const [usdPool, nativeAndQuoteTokenV3Pool, nativeAndAmountTokenV3Pool, nativeAndSpecifiedGasTokenV3Pool,] = await Promise.all([
978
+ usdPoolPromise,
979
+ nativeAndQuoteTokenV3PoolPromise,
980
+ nativeAndAmountTokenV3PoolPromise,
981
+ nativeAndSpecifiedGasTokenV3PoolPromise,
982
+ ]);
983
+ const pools = {
984
+ usdPool: usdPool,
985
+ nativeAndQuoteTokenV3Pool: nativeAndQuoteTokenV3Pool,
986
+ nativeAndAmountTokenV3Pool: nativeAndAmountTokenV3Pool,
987
+ nativeAndSpecifiedGasTokenV3Pool: nativeAndSpecifiedGasTokenV3Pool,
988
+ };
989
+ const v2GasModelPromise = ((_a = this.v2Supported) === null || _a === void 0 ? void 0 : _a.includes(this.chainId))
990
+ ? this.v2GasModelFactory
991
+ .buildGasModel({
992
+ chainId: this.chainId,
993
+ gasPriceWei,
994
+ poolProvider: this.v2PoolProvider,
995
+ token: quoteToken,
996
+ l2GasDataProvider: this.l2GasDataProvider,
997
+ providerConfig: providerConfig,
998
+ })
999
+ .catch((_) => undefined) // If v2 model throws uncaught exception, we return undefined v2 gas model, so there's a chance v3 route can go through
1000
+ : Promise.resolve(undefined);
1001
+ const v3GasModelPromise = this.v3GasModelFactory.buildGasModel({
1002
+ chainId: this.chainId,
1003
+ gasPriceWei,
1004
+ pools,
1005
+ amountToken,
1006
+ quoteToken,
1007
+ v2poolProvider: this.v2PoolProvider,
1008
+ l2GasDataProvider: this.l2GasDataProvider,
1009
+ providerConfig: providerConfig,
1010
+ });
1011
+ // const v4GasModelPromise = this.v4GasModelFactory.buildGasModel({
1012
+ // chainId: this.chainId,
1013
+ // gasPriceWei,
1014
+ // pools,
1015
+ // amountToken,
1016
+ // quoteToken,
1017
+ // v2poolProvider: this.v2PoolProvider,
1018
+ // l2GasDataProvider: this.l2GasDataProvider,
1019
+ // providerConfig: providerConfig,
1020
+ // });
1021
+ const mixedRouteGasModelPromise = this.mixedRouteGasModelFactory.buildGasModel({
1022
+ chainId: this.chainId,
1023
+ gasPriceWei,
1024
+ pools,
1025
+ amountToken,
1026
+ quoteToken,
1027
+ v2poolProvider: this.v2PoolProvider,
1028
+ providerConfig: providerConfig,
1029
+ });
1030
+ const [v2GasModel, v3GasModel /* , V4GasModel */, mixedRouteGasModel] = await Promise.all([
1031
+ v2GasModelPromise,
1032
+ v3GasModelPromise,
1033
+ // v4GasModelPromise,
1034
+ mixedRouteGasModelPromise,
1035
+ ]);
1036
+ metric_1.metric.putMetric('GasModelCreation', Date.now() - beforeGasModel, metric_1.MetricLoggerUnit.Milliseconds);
1037
+ return {
1038
+ v2GasModel: v2GasModel,
1039
+ v3GasModel: v3GasModel,
1040
+ // v4GasModel: V4GasModel,
1041
+ mixedRouteGasModel: mixedRouteGasModel,
1042
+ };
1043
+ }
1044
+ // Note multiplications here can result in a loss of precision in the amounts (e.g. taking 50% of 101)
1045
+ // This is reconcilled at the end of the algorithm by adding any lost precision to one of
1046
+ // the splits in the route.
1047
+ getAmountDistribution(amount, routingConfig) {
1048
+ const { distributionPercent } = routingConfig;
1049
+ const percents = [];
1050
+ const amounts = [];
1051
+ for (let i = 1; i <= 100 / distributionPercent; i++) {
1052
+ percents.push(i * distributionPercent);
1053
+ amounts.push(amount.multiply(new sdk_core_1.Fraction(i * distributionPercent, 100)));
1054
+ }
1055
+ return [percents, amounts];
1056
+ }
1057
+ async buildSwapAndAddMethodParameters(trade, swapAndAddOptions, swapAndAddParameters) {
1058
+ const { swapOptions: { recipient, slippageTolerance, deadline, inputTokenPermit }, addLiquidityOptions: addLiquidityConfig, } = swapAndAddOptions;
1059
+ const preLiquidityPosition = swapAndAddParameters.preLiquidityPosition;
1060
+ const finalBalanceTokenIn = swapAndAddParameters.initialBalanceTokenIn.subtract(trade.inputAmount);
1061
+ const finalBalanceTokenOut = swapAndAddParameters.initialBalanceTokenOut.add(trade.outputAmount);
1062
+ const approvalTypes = await this.swapRouterProvider.getApprovalType(finalBalanceTokenIn, finalBalanceTokenOut);
1063
+ const zeroForOne = finalBalanceTokenIn.currency.wrapped.sortsBefore(finalBalanceTokenOut.currency.wrapped);
1064
+ return Object.assign(Object.assign({}, router_sdk_1.SwapRouter.swapAndAddCallParameters(trade, {
1065
+ recipient,
1066
+ slippageTolerance,
1067
+ deadlineOrPreviousBlockhash: deadline,
1068
+ inputTokenPermit,
1069
+ }, v3_sdk_1.Position.fromAmounts({
1070
+ pool: preLiquidityPosition.pool,
1071
+ tickLower: preLiquidityPosition.tickLower,
1072
+ tickUpper: preLiquidityPosition.tickUpper,
1073
+ amount0: zeroForOne
1074
+ ? finalBalanceTokenIn.quotient.toString()
1075
+ : finalBalanceTokenOut.quotient.toString(),
1076
+ amount1: zeroForOne
1077
+ ? finalBalanceTokenOut.quotient.toString()
1078
+ : finalBalanceTokenIn.quotient.toString(),
1079
+ useFullPrecision: false,
1080
+ }), addLiquidityConfig, approvalTypes.approvalTokenIn, approvalTypes.approvalTokenOut)), { to: (0, util_1.SWAP_ROUTER_02_ADDRESSES)(this.chainId) });
1081
+ }
1082
+ emitPoolSelectionMetrics(swapRouteRaw, allPoolsBySelection) {
1083
+ const poolAddressesUsed = new Set();
1084
+ const { routes: routeAmounts } = swapRouteRaw;
1085
+ (0, lodash_1.default)(routeAmounts)
1086
+ .flatMap((routeAmount) => {
1087
+ const { poolIdentifiers: poolAddresses } = routeAmount;
1088
+ return poolAddresses;
1089
+ })
1090
+ .forEach((address) => {
1091
+ poolAddressesUsed.add(address.toLowerCase());
1092
+ });
1093
+ for (const poolsBySelection of allPoolsBySelection) {
1094
+ const { protocol } = poolsBySelection;
1095
+ lodash_1.default.forIn(poolsBySelection.selections, (pools, topNSelection) => {
1096
+ const topNUsed = lodash_1.default.findLastIndex(pools, (pool) => poolAddressesUsed.has(pool.id.toLowerCase())) + 1;
1097
+ metric_1.metric.putMetric(lodash_1.default.capitalize(`${protocol}${topNSelection}`), topNUsed, metric_1.MetricLoggerUnit.Count);
1098
+ });
1099
+ }
1100
+ let hasV3Route = false;
1101
+ let hasV2Route = false;
1102
+ let hasMixedRoute = false;
1103
+ for (const routeAmount of routeAmounts) {
1104
+ if (routeAmount.protocol === router_sdk_1.Protocol.V3) {
1105
+ hasV3Route = true;
1106
+ }
1107
+ if (routeAmount.protocol === router_sdk_1.Protocol.V2) {
1108
+ hasV2Route = true;
1109
+ }
1110
+ if (routeAmount.protocol === router_sdk_1.Protocol.MIXED) {
1111
+ hasMixedRoute = true;
1112
+ }
1113
+ }
1114
+ if (hasMixedRoute && (hasV3Route || hasV2Route)) {
1115
+ if (hasV3Route && hasV2Route) {
1116
+ metric_1.metric.putMetric(`MixedAndV3AndV2SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1117
+ metric_1.metric.putMetric(`MixedAndV3AndV2SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1118
+ }
1119
+ else if (hasV3Route) {
1120
+ metric_1.metric.putMetric(`MixedAndV3SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1121
+ metric_1.metric.putMetric(`MixedAndV3SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1122
+ }
1123
+ else if (hasV2Route) {
1124
+ metric_1.metric.putMetric(`MixedAndV2SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1125
+ metric_1.metric.putMetric(`MixedAndV2SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1126
+ }
1127
+ }
1128
+ else if (hasV3Route && hasV2Route) {
1129
+ metric_1.metric.putMetric(`V3AndV2SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1130
+ metric_1.metric.putMetric(`V3AndV2SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1131
+ }
1132
+ else if (hasMixedRoute) {
1133
+ if (routeAmounts.length > 1) {
1134
+ metric_1.metric.putMetric(`MixedSplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1135
+ metric_1.metric.putMetric(`MixedSplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1136
+ }
1137
+ else {
1138
+ metric_1.metric.putMetric(`MixedRoute`, 1, metric_1.MetricLoggerUnit.Count);
1139
+ metric_1.metric.putMetric(`MixedRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1140
+ }
1141
+ }
1142
+ else if (hasV3Route) {
1143
+ if (routeAmounts.length > 1) {
1144
+ metric_1.metric.putMetric(`V3SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1145
+ metric_1.metric.putMetric(`V3SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1146
+ }
1147
+ else {
1148
+ metric_1.metric.putMetric(`V3Route`, 1, metric_1.MetricLoggerUnit.Count);
1149
+ metric_1.metric.putMetric(`V3RouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1150
+ }
1151
+ }
1152
+ else if (hasV2Route) {
1153
+ if (routeAmounts.length > 1) {
1154
+ metric_1.metric.putMetric(`V2SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1155
+ metric_1.metric.putMetric(`V2SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1156
+ }
1157
+ else {
1158
+ metric_1.metric.putMetric(`V2Route`, 1, metric_1.MetricLoggerUnit.Count);
1159
+ metric_1.metric.putMetric(`V2RouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1160
+ }
1161
+ }
1162
+ }
1163
+ calculateOptimalRatio(position, sqrtRatioX96, zeroForOne) {
1164
+ const upperSqrtRatioX96 = v3_sdk_1.TickMath.getSqrtRatioAtTick(position.tickUpper);
1165
+ const lowerSqrtRatioX96 = v3_sdk_1.TickMath.getSqrtRatioAtTick(position.tickLower);
1166
+ // returns Fraction(0, 1) for any out of range position regardless of zeroForOne. Implication: function
1167
+ // cannot be used to determine the trading direction of out of range positions.
1168
+ if (jsbi_1.default.greaterThan(sqrtRatioX96, upperSqrtRatioX96) ||
1169
+ jsbi_1.default.lessThan(sqrtRatioX96, lowerSqrtRatioX96)) {
1170
+ return new sdk_core_1.Fraction(0, 1);
1171
+ }
1172
+ const precision = jsbi_1.default.BigInt('1' + '0'.repeat(18));
1173
+ let optimalRatio = new sdk_core_1.Fraction(v3_sdk_1.SqrtPriceMath.getAmount0Delta(sqrtRatioX96, upperSqrtRatioX96, precision, true), v3_sdk_1.SqrtPriceMath.getAmount1Delta(sqrtRatioX96, lowerSqrtRatioX96, precision, true));
1174
+ if (!zeroForOne)
1175
+ optimalRatio = optimalRatio.invert();
1176
+ return optimalRatio;
1177
+ }
1178
+ async userHasSufficientBalance(fromAddress, tradeType, amount, quote) {
1179
+ try {
1180
+ const neededBalance = tradeType === sdk_core_1.TradeType.EXACT_INPUT ? amount : quote;
1181
+ let balance;
1182
+ if (neededBalance.currency.isNative) {
1183
+ balance = await this.provider.getBalance(fromAddress);
1184
+ }
1185
+ else {
1186
+ const tokenContract = Erc20__factory_1.Erc20__factory.connect(neededBalance.currency.address, this.provider);
1187
+ balance = await tokenContract.balanceOf(fromAddress);
1188
+ }
1189
+ return balance.gte(bignumber_1.BigNumber.from(neededBalance.quotient.toString()));
1190
+ }
1191
+ catch (e) {
1192
+ log_1.log.error(e, 'Error while checking user balance');
1193
+ return false;
1194
+ }
1195
+ }
1196
+ absoluteValue(fraction) {
1197
+ const numeratorAbs = jsbi_1.default.lessThan(fraction.numerator, jsbi_1.default.BigInt(0))
1198
+ ? jsbi_1.default.unaryMinus(fraction.numerator)
1199
+ : fraction.numerator;
1200
+ const denominatorAbs = jsbi_1.default.lessThan(fraction.denominator, jsbi_1.default.BigInt(0))
1201
+ ? jsbi_1.default.unaryMinus(fraction.denominator)
1202
+ : fraction.denominator;
1203
+ return new sdk_core_1.Fraction(numeratorAbs, denominatorAbs);
1204
+ }
1205
+ getBlockNumberPromise() {
1206
+ return (0, async_retry_1.default)(async (_b, attempt) => {
1207
+ if (attempt > 1) {
1208
+ log_1.log.info(`Get block number attempt ${attempt}`);
1209
+ }
1210
+ return this.provider.getBlockNumber();
1211
+ }, {
1212
+ retries: 2,
1213
+ minTimeout: 100,
1214
+ maxTimeout: 1000,
1215
+ });
1216
+ }
1217
+ }
1218
+ exports.AlphaRouter = AlphaRouter;
1219
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxwaGEtcm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3JvdXRlcnMvYWxwaGEtcm91dGVyL2FscGhhLXJvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx3REFBcUQ7QUFDckQsd0RBQXlFO0FBQ3pFLDBEQUE4RTtBQUM5RSxzREFNaUM7QUFDakMsOEVBQTZFO0FBQzdFLGtEQUFnRjtBQUNoRixxRkFBNkQ7QUFFN0QsOERBQWdDO0FBQ2hDLGdEQUF3QjtBQUN4QixvREFBdUI7QUFDdkIsNERBQW1DO0FBRW5DLCtDQWtDeUI7QUFDekIsNkZBR3FEO0FBS3JELHVFQUcwQztBQUUxQyx5RUFBMkU7QUFDM0UsbUVBQStFO0FBQy9FLHVGQUdrRDtBQUNsRCxvRUFHMEM7QUFDMUMsNEVBSThDO0FBQzlDLG9FQUcwQztBQUUxQyxvRkFBb0Y7QUFDcEYsV0FBVztBQUNYLHFCQUFxQjtBQUNyQixvQkFBb0I7QUFDcEIsNkNBQTZDO0FBQzdDLCtFQUE0RTtBQUM1RSxxQ0FPb0I7QUFDcEIsZ0RBQW9EO0FBQ3BELDhDQUkyQjtBQUMzQix3RUFHd0M7QUFDeEMsd0NBQXFDO0FBQ3JDLGtFQUdxQztBQUNyQyw4Q0FBNkQ7QUFDN0Qsd0ZBTWdEO0FBQ2hELHNFQUFtRTtBQUNuRSxzQ0FlbUI7QUFFbkIscUNBR2tCO0FBT2xCLGlFQUE4RTtBQUM5RSxxRkFBK0U7QUFDL0UseUVBU3lDO0FBQ3pDLHNEQUF5RDtBQVN6RCw2R0FBNkc7QUFDN0csbUZBQW9GO0FBQ3BGLG1GQUFvRjtBQUNwRix1RkFBdUY7QUFDdkYsdUNBQTZFO0FBMkk3RSxNQUFhLG1CQUF1QixTQUFRLEdBQWM7SUFDL0MsR0FBRyxDQUFDLEdBQVcsRUFBRSxLQUFRO1FBQ2hDLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDN0MsQ0FBQztDQUNGO0FBSkQsa0RB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