@synthra-swap/smart-order-router 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/LICENSE +674 -0
  3. package/README.md +262 -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 +9 -0
  7. package/build/main/providers/cache-node.js +19 -0
  8. package/build/main/providers/cache.d.ts +13 -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 +26 -0
  15. package/build/main/providers/caching/route/model/cached-route.js +30 -0
  16. package/build/main/providers/caching/route/model/cached-routes.d.ts +66 -0
  17. package/build/main/providers/caching/route/model/cached-routes.js +77 -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 +90 -0
  21. package/build/main/providers/caching/route/route-caching-provider.js +70 -0
  22. package/build/main/providers/caching-gas-provider.d.ts +23 -0
  23. package/build/main/providers/caching-gas-provider.js +37 -0
  24. package/build/main/providers/caching-token-list-provider.d.ts +40 -0
  25. package/build/main/providers/caching-token-list-provider.js +122 -0
  26. package/build/main/providers/caching-token-provider.d.ts +25 -0
  27. package/build/main/providers/caching-token-provider.js +191 -0
  28. package/build/main/providers/eip-1559-gas-price-provider.d.ts +31 -0
  29. package/build/main/providers/eip-1559-gas-price-provider.js +66 -0
  30. package/build/main/providers/eth-estimate-gas-provider.d.ts +20 -0
  31. package/build/main/providers/eth-estimate-gas-provider.js +84 -0
  32. package/build/main/providers/eth-gas-station-info-gas-price-provider.d.ts +19 -0
  33. package/build/main/providers/eth-gas-station-info-gas-price-provider.js +37 -0
  34. package/build/main/providers/gas-price-provider.d.ts +10 -0
  35. package/build/main/providers/gas-price-provider.js +10 -0
  36. package/build/main/providers/index.d.ts +37 -0
  37. package/build/main/providers/index.js +54 -0
  38. package/build/main/providers/legacy-gas-price-provider.d.ts +7 -0
  39. package/build/main/providers/legacy-gas-price-provider.js +20 -0
  40. package/build/main/providers/multicall-provider.d.ts +82 -0
  41. package/build/main/providers/multicall-provider.js +15 -0
  42. package/build/main/providers/multicall-uniswap-provider.d.ts +37 -0
  43. package/build/main/providers/multicall-uniswap-provider.js +163 -0
  44. package/build/main/providers/on-chain-gas-price-provider.d.ts +19 -0
  45. package/build/main/providers/on-chain-gas-price-provider.js +34 -0
  46. package/build/main/providers/on-chain-quote-provider.d.ts +221 -0
  47. package/build/main/providers/on-chain-quote-provider.js +523 -0
  48. package/build/main/providers/provider.d.ts +10 -0
  49. package/build/main/providers/provider.js +3 -0
  50. package/build/main/providers/simulation-provider.d.ts +43 -0
  51. package/build/main/providers/simulation-provider.js +130 -0
  52. package/build/main/providers/static-gas-price-provider.d.ts +7 -0
  53. package/build/main/providers/static-gas-price-provider.js +13 -0
  54. package/build/main/providers/swap-router-provider.d.ts +30 -0
  55. package/build/main/providers/swap-router-provider.js +42 -0
  56. package/build/main/providers/tenderly-simulation-provider.d.ts +46 -0
  57. package/build/main/providers/tenderly-simulation-provider.js +266 -0
  58. package/build/main/providers/token-provider.d.ts +102 -0
  59. package/build/main/providers/token-provider.js +299 -0
  60. package/build/main/providers/token-validator-provider.d.ts +42 -0
  61. package/build/main/providers/token-validator-provider.js +95 -0
  62. package/build/main/providers/uri-subgraph-provider.d.ts +20 -0
  63. package/build/main/providers/uri-subgraph-provider.js +65 -0
  64. package/build/main/providers/v2/caching-pool-provider.d.ts +34 -0
  65. package/build/main/providers/v2/caching-pool-provider.js +88 -0
  66. package/build/main/providers/v2/caching-subgraph-provider.d.ts +23 -0
  67. package/build/main/providers/v2/caching-subgraph-provider.js +34 -0
  68. package/build/main/providers/v2/pool-provider.d.ts +59 -0
  69. package/build/main/providers/v2/pool-provider.js +120 -0
  70. package/build/main/providers/v2/quote-provider.d.ts +33 -0
  71. package/build/main/providers/v2/quote-provider.js +91 -0
  72. package/build/main/providers/v2/static-subgraph-provider.d.ts +20 -0
  73. package/build/main/providers/v2/static-subgraph-provider.js +98 -0
  74. package/build/main/providers/v2/subgraph-provider-with-fallback.d.ts +19 -0
  75. package/build/main/providers/v2/subgraph-provider-with-fallback.js +35 -0
  76. package/build/main/providers/v2/subgraph-provider.d.ts +33 -0
  77. package/build/main/providers/v2/subgraph-provider.js +134 -0
  78. package/build/main/providers/v2/uri-subgraph-provider.d.ts +4 -0
  79. package/build/main/providers/v2/uri-subgraph-provider.js +8 -0
  80. package/build/main/providers/v3/caching-pool-provider.d.ts +33 -0
  81. package/build/main/providers/v3/caching-pool-provider.js +80 -0
  82. package/build/main/providers/v3/caching-subgraph-provider.d.ts +23 -0
  83. package/build/main/providers/v3/caching-subgraph-provider.js +34 -0
  84. package/build/main/providers/v3/gas-data-provider.d.ts +57 -0
  85. package/build/main/providers/v3/gas-data-provider.js +67 -0
  86. package/build/main/providers/v3/pool-provider.d.ts +60 -0
  87. package/build/main/providers/v3/pool-provider.js +123 -0
  88. package/build/main/providers/v3/static-subgraph-provider.d.ts +22 -0
  89. package/build/main/providers/v3/static-subgraph-provider.js +171 -0
  90. package/build/main/providers/v3/subgraph-provider-with-fallback.d.ts +15 -0
  91. package/build/main/providers/v3/subgraph-provider-with-fallback.js +31 -0
  92. package/build/main/providers/v3/subgraph-provider.d.ts +36 -0
  93. package/build/main/providers/v3/subgraph-provider.js +146 -0
  94. package/build/main/providers/v3/uri-subgraph-provider.d.ts +4 -0
  95. package/build/main/providers/v3/uri-subgraph-provider.js +8 -0
  96. package/build/main/routers/alpha-router/alpha-router.d.ts +267 -0
  97. package/build/main/routers/alpha-router/alpha-router.js +848 -0
  98. package/build/main/routers/alpha-router/config.d.ts +4 -0
  99. package/build/main/routers/alpha-router/config.js +93 -0
  100. package/build/main/routers/alpha-router/entities/index.d.ts +1 -0
  101. package/build/main/routers/alpha-router/entities/index.js +18 -0
  102. package/build/main/routers/alpha-router/entities/route-with-valid-quote.d.ts +163 -0
  103. package/build/main/routers/alpha-router/entities/route-with-valid-quote.js +143 -0
  104. package/build/main/routers/alpha-router/functions/best-swap-route.d.ts +19 -0
  105. package/build/main/routers/alpha-router/functions/best-swap-route.js +364 -0
  106. package/build/main/routers/alpha-router/functions/calculate-ratio-amount-in.d.ts +3 -0
  107. package/build/main/routers/alpha-router/functions/calculate-ratio-amount-in.js +18 -0
  108. package/build/main/routers/alpha-router/functions/compute-all-routes.d.ts +8 -0
  109. package/build/main/routers/alpha-router/functions/compute-all-routes.js +72 -0
  110. package/build/main/routers/alpha-router/functions/get-candidate-pools.d.ts +78 -0
  111. package/build/main/routers/alpha-router/functions/get-candidate-pools.js +749 -0
  112. package/build/main/routers/alpha-router/gas-models/gas-model.d.ts +90 -0
  113. package/build/main/routers/alpha-router/gas-models/gas-model.js +60 -0
  114. package/build/main/routers/alpha-router/gas-models/index.d.ts +2 -0
  115. package/build/main/routers/alpha-router/gas-models/index.js +19 -0
  116. package/build/main/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.d.ts +25 -0
  117. package/build/main/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.js +175 -0
  118. package/build/main/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.d.ts +29 -0
  119. package/build/main/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.js +167 -0
  120. package/build/main/routers/alpha-router/gas-models/v3/gas-costs.d.ts +10 -0
  121. package/build/main/routers/alpha-router/gas-models/v3/gas-costs.js +124 -0
  122. package/build/main/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.d.ts +31 -0
  123. package/build/main/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.js +300 -0
  124. package/build/main/routers/alpha-router/index.d.ts +4 -0
  125. package/build/main/routers/alpha-router/index.js +21 -0
  126. package/build/main/routers/alpha-router/quoters/base-quoter.d.ts +68 -0
  127. package/build/main/routers/alpha-router/quoters/base-quoter.js +60 -0
  128. package/build/main/routers/alpha-router/quoters/index.d.ts +5 -0
  129. package/build/main/routers/alpha-router/quoters/index.js +22 -0
  130. package/build/main/routers/alpha-router/quoters/mixed-quoter.d.ts +20 -0
  131. package/build/main/routers/alpha-router/quoters/mixed-quoter.js +130 -0
  132. package/build/main/routers/alpha-router/quoters/model/index.d.ts +1 -0
  133. package/build/main/routers/alpha-router/quoters/model/index.js +18 -0
  134. package/build/main/routers/alpha-router/quoters/model/results/get-quotes-result.d.ts +6 -0
  135. package/build/main/routers/alpha-router/quoters/model/results/get-quotes-result.js +3 -0
  136. package/build/main/routers/alpha-router/quoters/model/results/get-routes-result.d.ts +6 -0
  137. package/build/main/routers/alpha-router/quoters/model/results/get-routes-result.js +3 -0
  138. package/build/main/routers/alpha-router/quoters/model/results/index.d.ts +2 -0
  139. package/build/main/routers/alpha-router/quoters/model/results/index.js +19 -0
  140. package/build/main/routers/alpha-router/quoters/v2-quoter.d.ts +21 -0
  141. package/build/main/routers/alpha-router/quoters/v2-quoter.js +122 -0
  142. package/build/main/routers/alpha-router/quoters/v3-quoter.d.ts +19 -0
  143. package/build/main/routers/alpha-router/quoters/v3-quoter.js +125 -0
  144. package/build/main/routers/index.d.ts +4 -0
  145. package/build/main/routers/index.js +21 -0
  146. package/build/main/routers/legacy-router/bases.d.ts +160 -0
  147. package/build/main/routers/legacy-router/bases.js +77 -0
  148. package/build/main/routers/legacy-router/index.d.ts +1 -0
  149. package/build/main/routers/legacy-router/index.js +18 -0
  150. package/build/main/routers/legacy-router/legacy-router.d.ts +42 -0
  151. package/build/main/routers/legacy-router/legacy-router.js +289 -0
  152. package/build/main/routers/router.d.ts +165 -0
  153. package/build/main/routers/router.js +52 -0
  154. package/build/main/tsconfig.tsbuildinfo +1 -0
  155. package/build/main/types/other/commons.d.ts +16 -0
  156. package/build/main/types/other/commons.js +6 -0
  157. package/build/main/types/other/factories/Erc20__factory.d.ts +45 -0
  158. package/build/main/types/other/factories/Erc20__factory.js +240 -0
  159. package/build/main/types/other/factories/GasDataArbitrum__factory.d.ts +18 -0
  160. package/build/main/types/other/factories/GasDataArbitrum__factory.js +58 -0
  161. package/build/main/types/other/factories/GasPriceOracle__factory.d.ts +46 -0
  162. package/build/main/types/other/factories/GasPriceOracle__factory.js +316 -0
  163. package/build/main/types/other/factories/IMixedRouteQuoterV1__factory.d.ts +41 -0
  164. package/build/main/types/other/factories/IMixedRouteQuoterV1__factory.js +156 -0
  165. package/build/main/types/other/factories/ITokenValidator__factory.d.ts +22 -0
  166. package/build/main/types/other/factories/ITokenValidator__factory.js +78 -0
  167. package/build/main/types/other/factories/Permit2__factory.d.ts +87 -0
  168. package/build/main/types/other/factories/Permit2__factory.js +936 -0
  169. package/build/main/types/other/factories/SwapRouter02__factory.d.ts +67 -0
  170. package/build/main/types/other/factories/SwapRouter02__factory.js +1098 -0
  171. package/build/main/types/v2/commons.d.ts +16 -0
  172. package/build/main/types/v2/commons.js +6 -0
  173. package/build/main/types/v2/factories/IUniswapV2Pair__factory.d.ts +35 -0
  174. package/build/main/types/v2/factories/IUniswapV2Pair__factory.js +671 -0
  175. package/build/main/types/v3/commons.d.ts +16 -0
  176. package/build/main/types/v3/commons.js +6 -0
  177. package/build/main/types/v3/factories/IERC20Metadata__factory.d.ts +35 -0
  178. package/build/main/types/v3/factories/IERC20Metadata__factory.js +242 -0
  179. package/build/main/types/v3/factories/IQuoterV2__factory.d.ts +41 -0
  180. package/build/main/types/v3/factories/IQuoterV2__factory.js +220 -0
  181. package/build/main/types/v3/factories/IUniswapV3PoolState__factory.d.ts +22 -0
  182. package/build/main/types/v3/factories/IUniswapV3PoolState__factory.js +266 -0
  183. package/build/main/types/v3/factories/UniswapInterfaceMulticall__factory.d.ts +61 -0
  184. package/build/main/types/v3/factories/UniswapInterfaceMulticall__factory.js +127 -0
  185. package/build/main/util/addresses.d.ts +25 -0
  186. package/build/main/util/addresses.js +55 -0
  187. package/build/main/util/amounts.d.ts +8 -0
  188. package/build/main/util/amounts.js +51 -0
  189. package/build/main/util/callData.d.ts +1 -0
  190. package/build/main/util/callData.js +6 -0
  191. package/build/main/util/chains.d.ts +55 -0
  192. package/build/main/util/chains.js +505 -0
  193. package/build/main/util/gas-factory-helpers.d.ts +25 -0
  194. package/build/main/util/gas-factory-helpers.js +305 -0
  195. package/build/main/util/index.d.ts +7 -0
  196. package/build/main/util/index.js +24 -0
  197. package/build/main/util/log.d.ts +3 -0
  198. package/build/main/util/log.js +97 -0
  199. package/build/main/util/methodParameters.d.ts +5 -0
  200. package/build/main/util/methodParameters.js +108 -0
  201. package/build/main/util/metric.d.ts +48 -0
  202. package/build/main/util/metric.js +59 -0
  203. package/build/main/util/protocols.d.ts +2 -0
  204. package/build/main/util/protocols.js +18 -0
  205. package/build/main/util/routes.d.ts +8 -0
  206. package/build/main/util/routes.js +60 -0
  207. package/build/main/util/unsupported-tokens.d.ts +37 -0
  208. package/build/main/util/unsupported-tokens.js +1119 -0
  209. package/build/module/index.d.ts +3 -0
  210. package/build/module/index.js +4 -0
  211. package/build/module/providers/cache-node.d.ts +9 -0
  212. package/build/module/providers/cache-node.js +15 -0
  213. package/build/module/providers/cache.d.ts +13 -0
  214. package/build/module/providers/cache.js +2 -0
  215. package/build/module/providers/caching/route/index.d.ts +2 -0
  216. package/build/module/providers/caching/route/index.js +3 -0
  217. package/build/module/providers/caching/route/model/cache-mode.d.ts +16 -0
  218. package/build/module/providers/caching/route/model/cache-mode.js +18 -0
  219. package/build/module/providers/caching/route/model/cached-route.d.ts +26 -0
  220. package/build/module/providers/caching/route/model/cached-route.js +26 -0
  221. package/build/module/providers/caching/route/model/cached-routes.d.ts +66 -0
  222. package/build/module/providers/caching/route/model/cached-routes.js +70 -0
  223. package/build/module/providers/caching/route/model/index.d.ts +3 -0
  224. package/build/module/providers/caching/route/model/index.js +4 -0
  225. package/build/module/providers/caching/route/route-caching-provider.d.ts +90 -0
  226. package/build/module/providers/caching/route/route-caching-provider.js +66 -0
  227. package/build/module/providers/caching-gas-provider.d.ts +23 -0
  228. package/build/module/providers/caching-gas-provider.js +33 -0
  229. package/build/module/providers/caching-token-list-provider.d.ts +40 -0
  230. package/build/module/providers/caching-token-list-provider.js +115 -0
  231. package/build/module/providers/caching-token-provider.d.ts +25 -0
  232. package/build/module/providers/caching-token-provider.js +184 -0
  233. package/build/module/providers/eip-1559-gas-price-provider.d.ts +31 -0
  234. package/build/module/providers/eip-1559-gas-price-provider.js +59 -0
  235. package/build/module/providers/eth-estimate-gas-provider.d.ts +20 -0
  236. package/build/module/providers/eth-estimate-gas-provider.js +92 -0
  237. package/build/module/providers/eth-gas-station-info-gas-price-provider.d.ts +19 -0
  238. package/build/module/providers/eth-gas-station-info-gas-price-provider.js +30 -0
  239. package/build/module/providers/gas-price-provider.d.ts +10 -0
  240. package/build/module/providers/gas-price-provider.js +6 -0
  241. package/build/module/providers/index.d.ts +37 -0
  242. package/build/module/providers/index.js +38 -0
  243. package/build/module/providers/legacy-gas-price-provider.d.ts +7 -0
  244. package/build/module/providers/legacy-gas-price-provider.js +16 -0
  245. package/build/module/providers/multicall-provider.d.ts +82 -0
  246. package/build/module/providers/multicall-provider.js +11 -0
  247. package/build/module/providers/multicall-uniswap-provider.d.ts +37 -0
  248. package/build/module/providers/multicall-uniswap-provider.js +156 -0
  249. package/build/module/providers/on-chain-gas-price-provider.d.ts +19 -0
  250. package/build/module/providers/on-chain-gas-price-provider.js +30 -0
  251. package/build/module/providers/on-chain-quote-provider.d.ts +221 -0
  252. package/build/module/providers/on-chain-quote-provider.js +517 -0
  253. package/build/module/providers/provider.d.ts +10 -0
  254. package/build/module/providers/provider.js +2 -0
  255. package/build/module/providers/simulation-provider.d.ts +43 -0
  256. package/build/module/providers/simulation-provider.js +132 -0
  257. package/build/module/providers/static-gas-price-provider.d.ts +7 -0
  258. package/build/module/providers/static-gas-price-provider.js +9 -0
  259. package/build/module/providers/swap-router-provider.d.ts +30 -0
  260. package/build/module/providers/swap-router-provider.js +38 -0
  261. package/build/module/providers/tenderly-simulation-provider.d.ts +46 -0
  262. package/build/module/providers/tenderly-simulation-provider.js +261 -0
  263. package/build/module/providers/token-provider.d.ts +102 -0
  264. package/build/module/providers/token-provider.js +287 -0
  265. package/build/module/providers/token-validator-provider.d.ts +42 -0
  266. package/build/module/providers/token-validator-provider.js +88 -0
  267. package/build/module/providers/uri-subgraph-provider.d.ts +20 -0
  268. package/build/module/providers/uri-subgraph-provider.js +58 -0
  269. package/build/module/providers/v2/caching-pool-provider.d.ts +34 -0
  270. package/build/module/providers/v2/caching-pool-provider.js +81 -0
  271. package/build/module/providers/v2/caching-subgraph-provider.d.ts +23 -0
  272. package/build/module/providers/v2/caching-subgraph-provider.js +30 -0
  273. package/build/module/providers/v2/pool-provider.d.ts +59 -0
  274. package/build/module/providers/v2/pool-provider.js +113 -0
  275. package/build/module/providers/v2/quote-provider.d.ts +33 -0
  276. package/build/module/providers/v2/quote-provider.js +87 -0
  277. package/build/module/providers/v2/static-subgraph-provider.d.ts +20 -0
  278. package/build/module/providers/v2/static-subgraph-provider.js +91 -0
  279. package/build/module/providers/v2/subgraph-provider-with-fallback.d.ts +19 -0
  280. package/build/module/providers/v2/subgraph-provider-with-fallback.js +31 -0
  281. package/build/module/providers/v2/subgraph-provider.d.ts +33 -0
  282. package/build/module/providers/v2/subgraph-provider.js +135 -0
  283. package/build/module/providers/v2/uri-subgraph-provider.d.ts +4 -0
  284. package/build/module/providers/v2/uri-subgraph-provider.js +4 -0
  285. package/build/module/providers/v3/caching-pool-provider.d.ts +33 -0
  286. package/build/module/providers/v3/caching-pool-provider.js +73 -0
  287. package/build/module/providers/v3/caching-subgraph-provider.d.ts +23 -0
  288. package/build/module/providers/v3/caching-subgraph-provider.js +30 -0
  289. package/build/module/providers/v3/gas-data-provider.d.ts +57 -0
  290. package/build/module/providers/v3/gas-data-provider.js +62 -0
  291. package/build/module/providers/v3/pool-provider.d.ts +60 -0
  292. package/build/module/providers/v3/pool-provider.js +116 -0
  293. package/build/module/providers/v3/static-subgraph-provider.d.ts +22 -0
  294. package/build/module/providers/v3/static-subgraph-provider.js +164 -0
  295. package/build/module/providers/v3/subgraph-provider-with-fallback.d.ts +15 -0
  296. package/build/module/providers/v3/subgraph-provider-with-fallback.js +27 -0
  297. package/build/module/providers/v3/subgraph-provider.d.ts +36 -0
  298. package/build/module/providers/v3/subgraph-provider.js +133 -0
  299. package/build/module/providers/v3/uri-subgraph-provider.d.ts +4 -0
  300. package/build/module/providers/v3/uri-subgraph-provider.js +4 -0
  301. package/build/module/routers/alpha-router/alpha-router.d.ts +267 -0
  302. package/build/module/routers/alpha-router/alpha-router.js +846 -0
  303. package/build/module/routers/alpha-router/config.d.ts +4 -0
  304. package/build/module/routers/alpha-router/config.js +89 -0
  305. package/build/module/routers/alpha-router/entities/index.d.ts +1 -0
  306. package/build/module/routers/alpha-router/entities/index.js +2 -0
  307. package/build/module/routers/alpha-router/entities/route-with-valid-quote.d.ts +163 -0
  308. package/build/module/routers/alpha-router/entities/route-with-valid-quote.js +134 -0
  309. package/build/module/routers/alpha-router/functions/best-swap-route.d.ts +19 -0
  310. package/build/module/routers/alpha-router/functions/best-swap-route.js +356 -0
  311. package/build/module/routers/alpha-router/functions/calculate-ratio-amount-in.d.ts +3 -0
  312. package/build/module/routers/alpha-router/functions/calculate-ratio-amount-in.js +14 -0
  313. package/build/module/routers/alpha-router/functions/compute-all-routes.d.ts +8 -0
  314. package/build/module/routers/alpha-router/functions/compute-all-routes.js +65 -0
  315. package/build/module/routers/alpha-router/functions/get-candidate-pools.d.ts +78 -0
  316. package/build/module/routers/alpha-router/functions/get-candidate-pools.js +760 -0
  317. package/build/module/routers/alpha-router/gas-models/gas-model.d.ts +90 -0
  318. package/build/module/routers/alpha-router/gas-models/gas-model.js +55 -0
  319. package/build/module/routers/alpha-router/gas-models/index.d.ts +2 -0
  320. package/build/module/routers/alpha-router/gas-models/index.js +3 -0
  321. package/build/module/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.d.ts +25 -0
  322. package/build/module/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.js +168 -0
  323. package/build/module/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.d.ts +29 -0
  324. package/build/module/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.js +160 -0
  325. package/build/module/routers/alpha-router/gas-models/v3/gas-costs.d.ts +10 -0
  326. package/build/module/routers/alpha-router/gas-models/v3/gas-costs.js +116 -0
  327. package/build/module/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.d.ts +31 -0
  328. package/build/module/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.js +293 -0
  329. package/build/module/routers/alpha-router/index.d.ts +4 -0
  330. package/build/module/routers/alpha-router/index.js +5 -0
  331. package/build/module/routers/alpha-router/quoters/base-quoter.d.ts +68 -0
  332. package/build/module/routers/alpha-router/quoters/base-quoter.js +53 -0
  333. package/build/module/routers/alpha-router/quoters/index.d.ts +5 -0
  334. package/build/module/routers/alpha-router/quoters/index.js +6 -0
  335. package/build/module/routers/alpha-router/quoters/mixed-quoter.d.ts +20 -0
  336. package/build/module/routers/alpha-router/quoters/mixed-quoter.js +123 -0
  337. package/build/module/routers/alpha-router/quoters/model/index.d.ts +1 -0
  338. package/build/module/routers/alpha-router/quoters/model/index.js +2 -0
  339. package/build/module/routers/alpha-router/quoters/model/results/get-quotes-result.d.ts +6 -0
  340. package/build/module/routers/alpha-router/quoters/model/results/get-quotes-result.js +2 -0
  341. package/build/module/routers/alpha-router/quoters/model/results/get-routes-result.d.ts +6 -0
  342. package/build/module/routers/alpha-router/quoters/model/results/get-routes-result.js +2 -0
  343. package/build/module/routers/alpha-router/quoters/model/results/index.d.ts +2 -0
  344. package/build/module/routers/alpha-router/quoters/model/results/index.js +3 -0
  345. package/build/module/routers/alpha-router/quoters/v2-quoter.d.ts +21 -0
  346. package/build/module/routers/alpha-router/quoters/v2-quoter.js +115 -0
  347. package/build/module/routers/alpha-router/quoters/v3-quoter.d.ts +19 -0
  348. package/build/module/routers/alpha-router/quoters/v3-quoter.js +118 -0
  349. package/build/module/routers/index.d.ts +4 -0
  350. package/build/module/routers/index.js +5 -0
  351. package/build/module/routers/legacy-router/bases.d.ts +160 -0
  352. package/build/module/routers/legacy-router/bases.js +83 -0
  353. package/build/module/routers/legacy-router/index.d.ts +1 -0
  354. package/build/module/routers/legacy-router/index.js +2 -0
  355. package/build/module/routers/legacy-router/legacy-router.d.ts +42 -0
  356. package/build/module/routers/legacy-router/legacy-router.js +290 -0
  357. package/build/module/routers/router.d.ts +165 -0
  358. package/build/module/routers/router.js +44 -0
  359. package/build/module/tsconfig.module.tsbuildinfo +1 -0
  360. package/build/module/types/other/commons.d.ts +16 -0
  361. package/build/module/types/other/commons.js +5 -0
  362. package/build/module/types/other/factories/Erc20__factory.d.ts +45 -0
  363. package/build/module/types/other/factories/Erc20__factory.js +236 -0
  364. package/build/module/types/other/factories/GasDataArbitrum__factory.d.ts +18 -0
  365. package/build/module/types/other/factories/GasDataArbitrum__factory.js +54 -0
  366. package/build/module/types/other/factories/GasPriceOracle__factory.d.ts +46 -0
  367. package/build/module/types/other/factories/GasPriceOracle__factory.js +312 -0
  368. package/build/module/types/other/factories/IMixedRouteQuoterV1__factory.d.ts +41 -0
  369. package/build/module/types/other/factories/IMixedRouteQuoterV1__factory.js +152 -0
  370. package/build/module/types/other/factories/ITokenValidator__factory.d.ts +22 -0
  371. package/build/module/types/other/factories/ITokenValidator__factory.js +74 -0
  372. package/build/module/types/other/factories/Permit2__factory.d.ts +87 -0
  373. package/build/module/types/other/factories/Permit2__factory.js +932 -0
  374. package/build/module/types/other/factories/SwapRouter02__factory.d.ts +67 -0
  375. package/build/module/types/other/factories/SwapRouter02__factory.js +1094 -0
  376. package/build/module/types/v2/commons.d.ts +16 -0
  377. package/build/module/types/v2/commons.js +5 -0
  378. package/build/module/types/v2/factories/IUniswapV2Pair__factory.d.ts +35 -0
  379. package/build/module/types/v2/factories/IUniswapV2Pair__factory.js +667 -0
  380. package/build/module/types/v3/commons.d.ts +16 -0
  381. package/build/module/types/v3/commons.js +5 -0
  382. package/build/module/types/v3/factories/IERC20Metadata__factory.d.ts +35 -0
  383. package/build/module/types/v3/factories/IERC20Metadata__factory.js +238 -0
  384. package/build/module/types/v3/factories/IQuoterV2__factory.d.ts +41 -0
  385. package/build/module/types/v3/factories/IQuoterV2__factory.js +216 -0
  386. package/build/module/types/v3/factories/IUniswapV3PoolState__factory.d.ts +22 -0
  387. package/build/module/types/v3/factories/IUniswapV3PoolState__factory.js +262 -0
  388. package/build/module/types/v3/factories/UniswapInterfaceMulticall__factory.d.ts +61 -0
  389. package/build/module/types/v3/factories/UniswapInterfaceMulticall__factory.js +123 -0
  390. package/build/module/util/addresses.d.ts +25 -0
  391. package/build/module/util/addresses.js +89 -0
  392. package/build/module/util/amounts.d.ts +8 -0
  393. package/build/module/util/amounts.js +41 -0
  394. package/build/module/util/callData.d.ts +1 -0
  395. package/build/module/util/callData.js +3 -0
  396. package/build/module/util/chains.d.ts +55 -0
  397. package/build/module/util/chains.js +496 -0
  398. package/build/module/util/gas-factory-helpers.d.ts +25 -0
  399. package/build/module/util/gas-factory-helpers.js +288 -0
  400. package/build/module/util/index.d.ts +7 -0
  401. package/build/module/util/index.js +8 -0
  402. package/build/module/util/log.d.ts +3 -0
  403. package/build/module/util/log.js +93 -0
  404. package/build/module/util/methodParameters.d.ts +5 -0
  405. package/build/module/util/methodParameters.js +106 -0
  406. package/build/module/util/metric.d.ts +48 -0
  407. package/build/module/util/metric.js +53 -0
  408. package/build/module/util/protocols.d.ts +2 -0
  409. package/build/module/util/protocols.js +14 -0
  410. package/build/module/util/routes.d.ts +8 -0
  411. package/build/module/util/routes.js +50 -0
  412. package/build/module/util/unsupported-tokens.d.ts +37 -0
  413. package/build/module/util/unsupported-tokens.js +1116 -0
  414. package/package.json +119 -0
@@ -0,0 +1,846 @@
1
+ import { BigNumber } from '@ethersproject/bignumber';
2
+ import { JsonRpcProvider } from '@ethersproject/providers';
3
+ import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list';
4
+ import { Protocol, SwapRouter } from '@uniswap/router-sdk';
5
+ import { Pool, Position, SqrtPriceMath, TickMath } from '@uniswap/v3-sdk';
6
+ import { ChainId, Fraction, TradeType, } from '@synthra-swap/sdk-core';
7
+ import retry from 'async-retry';
8
+ import JSBI from 'jsbi';
9
+ import _ from 'lodash';
10
+ import NodeCache from 'node-cache';
11
+ import { CachedRoutes, CacheMode, CachingGasStationProvider, CachingTokenProviderWithFallback, CachingV2PoolProvider, CachingV2SubgraphProvider, CachingV3PoolProvider, CachingV3SubgraphProvider, EIP1559GasPriceProvider, ETHGasStationInfoProvider, LegacyGasPriceProvider, NodeJSCache, OnChainGasPriceProvider, OnChainQuoteProvider, StaticV2SubgraphProvider, StaticV3SubgraphProvider, SwapRouterProvider, UniswapMulticallProvider, URISubgraphProvider, V2QuoteProvider, V2SubgraphProviderWithFallBacks, V3SubgraphProviderWithFallBacks, } from '../../providers';
12
+ import { CachingTokenListProvider, } from '../../providers/caching-token-list-provider';
13
+ import { TokenProvider } from '../../providers/token-provider';
14
+ import { TokenValidatorProvider, } from '../../providers/token-validator-provider';
15
+ import { V2PoolProvider, } from '../../providers/v2/pool-provider';
16
+ import { ArbitrumGasDataProvider, OptimismGasDataProvider, } from '../../providers/v3/gas-data-provider';
17
+ import { V3PoolProvider, } from '../../providers/v3/pool-provider';
18
+ import { Erc20__factory } from '../../types/other/factories/Erc20__factory';
19
+ import { SWAP_ROUTER_02_ADDRESSES, WRAPPED_NATIVE_CURRENCY } from '../../util';
20
+ import { CurrencyAmount } from '../../util/amounts';
21
+ import { ID_TO_CHAIN_ID, ID_TO_NETWORK_NAME, V2_SUPPORTED, } from '../../util/chains';
22
+ import { getHighestLiquidityV3NativePool, getHighestLiquidityV3USDPool, } from '../../util/gas-factory-helpers';
23
+ import { log } from '../../util/log';
24
+ import { buildSwapMethodParameters, buildTrade, } from '../../util/methodParameters';
25
+ import { metric, MetricLoggerUnit } from '../../util/metric';
26
+ import { UNSUPPORTED_TOKENS } from '../../util/unsupported-tokens';
27
+ import { SwapToRatioStatus, } from '../router';
28
+ import { DEFAULT_ROUTING_CONFIG_BY_CHAIN, ETH_GAS_STATION_API_URL, } from './config';
29
+ import { getBestSwapRoute } from './functions/best-swap-route';
30
+ import { calculateRatioAmountIn } from './functions/calculate-ratio-amount-in';
31
+ import { MixedRouteHeuristicGasModelFactory } from './gas-models/mixedRoute/mixed-route-heuristic-gas-model';
32
+ import { V2HeuristicGasModelFactory } from './gas-models/v2/v2-heuristic-gas-model';
33
+ import { V3HeuristicGasModelFactory } from './gas-models/v3/v3-heuristic-gas-model';
34
+ import { MixedQuoter, V2Quoter, V3Quoter } from './quoters';
35
+ export class MapWithLowerCaseKey extends Map {
36
+ set(key, value) {
37
+ return super.set(key.toLowerCase(), value);
38
+ }
39
+ }
40
+ export class AlphaRouter {
41
+ constructor({ chainId, provider, multicall2Provider, v3PoolProvider, onChainQuoteProvider, v2PoolProvider, v2QuoteProvider, v2SubgraphProvider, tokenProvider, blockedTokenListProvider, v3SubgraphProvider, gasPriceProvider, v3GasModelFactory, v2GasModelFactory, mixedRouteGasModelFactory, swapRouterProvider, optimismGasDataProvider, tokenValidatorProvider, arbitrumGasDataProvider, simulator, routeCachingProvider, }) {
42
+ this.chainId = chainId;
43
+ this.provider = provider;
44
+ this.multicall2Provider =
45
+ multicall2Provider !== null && multicall2Provider !== void 0 ? multicall2Provider : new UniswapMulticallProvider(chainId, provider, 375000);
46
+ this.v3PoolProvider =
47
+ v3PoolProvider !== null && v3PoolProvider !== void 0 ? v3PoolProvider : new CachingV3PoolProvider(this.chainId, new V3PoolProvider(ID_TO_CHAIN_ID(chainId), this.multicall2Provider), new NodeJSCache(new NodeCache({ stdTTL: 360, useClones: false })));
48
+ this.simulator = simulator;
49
+ this.routeCachingProvider = routeCachingProvider;
50
+ if (onChainQuoteProvider) {
51
+ this.onChainQuoteProvider = onChainQuoteProvider;
52
+ }
53
+ else {
54
+ switch (chainId) {
55
+ case ChainId.OPTIMISM:
56
+ case ChainId.OPTIMISM_GOERLI:
57
+ case ChainId.BASE:
58
+ case ChainId.BASE_GOERLI:
59
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, {
60
+ retries: 2,
61
+ minTimeout: 100,
62
+ maxTimeout: 1000,
63
+ }, {
64
+ multicallChunk: 110,
65
+ gasLimitPerCall: 1200000,
66
+ quoteMinSuccessRate: 0.1,
67
+ }, {
68
+ gasLimitOverride: 3000000,
69
+ multicallChunk: 45,
70
+ }, {
71
+ gasLimitOverride: 3000000,
72
+ multicallChunk: 45,
73
+ }, {
74
+ baseBlockOffset: -10,
75
+ rollback: {
76
+ enabled: true,
77
+ attemptsBeforeRollback: 1,
78
+ rollbackBlockOffset: -10,
79
+ },
80
+ });
81
+ break;
82
+ case ChainId.ARBITRUM_ONE:
83
+ case ChainId.ARBITRUM_GOERLI:
84
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, {
85
+ retries: 2,
86
+ minTimeout: 100,
87
+ maxTimeout: 1000,
88
+ }, {
89
+ multicallChunk: 10,
90
+ gasLimitPerCall: 12000000,
91
+ quoteMinSuccessRate: 0.1,
92
+ }, {
93
+ gasLimitOverride: 30000000,
94
+ multicallChunk: 6,
95
+ }, {
96
+ gasLimitOverride: 30000000,
97
+ multicallChunk: 6,
98
+ });
99
+ break;
100
+ case ChainId.CELO:
101
+ case ChainId.CELO_ALFAJORES:
102
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, {
103
+ retries: 2,
104
+ minTimeout: 100,
105
+ maxTimeout: 1000,
106
+ }, {
107
+ multicallChunk: 10,
108
+ gasLimitPerCall: 5000000,
109
+ quoteMinSuccessRate: 0.1,
110
+ }, {
111
+ gasLimitOverride: 5000000,
112
+ multicallChunk: 5,
113
+ }, {
114
+ gasLimitOverride: 6250000,
115
+ multicallChunk: 4,
116
+ });
117
+ break;
118
+ default:
119
+ this.onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, this.multicall2Provider, {
120
+ retries: 2,
121
+ minTimeout: 100,
122
+ maxTimeout: 1000,
123
+ }, {
124
+ multicallChunk: 210,
125
+ gasLimitPerCall: 705000,
126
+ quoteMinSuccessRate: 0.15,
127
+ }, {
128
+ gasLimitOverride: 2000000,
129
+ multicallChunk: 70,
130
+ });
131
+ break;
132
+ }
133
+ }
134
+ this.v2PoolProvider =
135
+ v2PoolProvider !== null && v2PoolProvider !== void 0 ? v2PoolProvider : new CachingV2PoolProvider(chainId, new V2PoolProvider(chainId, this.multicall2Provider), new NodeJSCache(new NodeCache({ stdTTL: 60, useClones: false })));
136
+ this.v2QuoteProvider = v2QuoteProvider !== null && v2QuoteProvider !== void 0 ? v2QuoteProvider : new V2QuoteProvider();
137
+ this.blockedTokenListProvider =
138
+ blockedTokenListProvider !== null && blockedTokenListProvider !== void 0 ? blockedTokenListProvider : new CachingTokenListProvider(chainId, UNSUPPORTED_TOKENS, new NodeJSCache(new NodeCache({ stdTTL: 3600, useClones: false })));
139
+ this.tokenProvider =
140
+ tokenProvider !== null && tokenProvider !== void 0 ? tokenProvider : new CachingTokenProviderWithFallback(chainId, new NodeJSCache(new NodeCache({ stdTTL: 3600, useClones: false })), new CachingTokenListProvider(chainId, DEFAULT_TOKEN_LIST, new NodeJSCache(new NodeCache({ stdTTL: 3600, useClones: false }))), new TokenProvider(chainId, this.multicall2Provider));
141
+ const chainName = ID_TO_NETWORK_NAME(chainId);
142
+ // ipfs urls in the following format: `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/${protocol}/${chainName}.json`;
143
+ if (v2SubgraphProvider) {
144
+ this.v2SubgraphProvider = v2SubgraphProvider;
145
+ }
146
+ else {
147
+ this.v2SubgraphProvider = new V2SubgraphProviderWithFallBacks([
148
+ new CachingV2SubgraphProvider(chainId, new URISubgraphProvider(chainId, `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v2/${chainName}.json`, undefined, 0), new NodeJSCache(new NodeCache({ stdTTL: 300, useClones: false }))),
149
+ new StaticV2SubgraphProvider(chainId),
150
+ ]);
151
+ }
152
+ if (v3SubgraphProvider) {
153
+ this.v3SubgraphProvider = v3SubgraphProvider;
154
+ }
155
+ else {
156
+ this.v3SubgraphProvider = new V3SubgraphProviderWithFallBacks([
157
+ new CachingV3SubgraphProvider(chainId, new URISubgraphProvider(chainId, `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v3/${chainName}.json`, undefined, 0), new NodeJSCache(new NodeCache({ stdTTL: 300, useClones: false }))),
158
+ new StaticV3SubgraphProvider(chainId, this.v3PoolProvider),
159
+ ]);
160
+ }
161
+ let gasPriceProviderInstance;
162
+ if (JsonRpcProvider.isProvider(this.provider)) {
163
+ gasPriceProviderInstance = new OnChainGasPriceProvider(chainId, new EIP1559GasPriceProvider(this.provider), new LegacyGasPriceProvider(this.provider));
164
+ }
165
+ else {
166
+ gasPriceProviderInstance = new ETHGasStationInfoProvider(ETH_GAS_STATION_API_URL);
167
+ }
168
+ this.gasPriceProvider =
169
+ gasPriceProvider !== null && gasPriceProvider !== void 0 ? gasPriceProvider : new CachingGasStationProvider(chainId, gasPriceProviderInstance, new NodeJSCache(new NodeCache({ stdTTL: 7, useClones: false })));
170
+ this.v3GasModelFactory =
171
+ v3GasModelFactory !== null && v3GasModelFactory !== void 0 ? v3GasModelFactory : new V3HeuristicGasModelFactory();
172
+ this.v2GasModelFactory =
173
+ v2GasModelFactory !== null && v2GasModelFactory !== void 0 ? v2GasModelFactory : new V2HeuristicGasModelFactory();
174
+ this.mixedRouteGasModelFactory =
175
+ mixedRouteGasModelFactory !== null && mixedRouteGasModelFactory !== void 0 ? mixedRouteGasModelFactory : new MixedRouteHeuristicGasModelFactory();
176
+ this.swapRouterProvider =
177
+ swapRouterProvider !== null && swapRouterProvider !== void 0 ? swapRouterProvider : new SwapRouterProvider(this.multicall2Provider, this.chainId);
178
+ if (chainId === ChainId.OPTIMISM || chainId === ChainId.BASE) {
179
+ this.l2GasDataProvider =
180
+ optimismGasDataProvider !== null && optimismGasDataProvider !== void 0 ? optimismGasDataProvider : new OptimismGasDataProvider(chainId, this.multicall2Provider);
181
+ }
182
+ if (chainId === ChainId.ARBITRUM_ONE ||
183
+ chainId === ChainId.ARBITRUM_GOERLI) {
184
+ this.l2GasDataProvider =
185
+ arbitrumGasDataProvider !== null && arbitrumGasDataProvider !== void 0 ? arbitrumGasDataProvider : new ArbitrumGasDataProvider(chainId, this.provider);
186
+ }
187
+ if (tokenValidatorProvider) {
188
+ this.tokenValidatorProvider = tokenValidatorProvider;
189
+ }
190
+ else if (this.chainId === ChainId.MAINNET) {
191
+ this.tokenValidatorProvider = new TokenValidatorProvider(this.chainId, this.multicall2Provider, new NodeJSCache(new NodeCache({ stdTTL: 30000, useClones: false })));
192
+ }
193
+ // Initialize the Quoters.
194
+ // Quoters are an abstraction encapsulating the business logic of fetching routes and quotes.
195
+ this.v2Quoter = new V2Quoter(this.v2SubgraphProvider, this.v2PoolProvider, this.v2QuoteProvider, this.v2GasModelFactory, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
196
+ this.v3Quoter = new V3Quoter(this.v3SubgraphProvider, this.v3PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
197
+ this.mixedQuoter = new MixedQuoter(this.v3SubgraphProvider, this.v3PoolProvider, this.v2SubgraphProvider, this.v2PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
198
+ }
199
+ async routeToRatio(token0Balance, token1Balance, position, swapAndAddConfig, swapAndAddOptions, routingConfig = DEFAULT_ROUTING_CONFIG_BY_CHAIN(this.chainId)) {
200
+ if (token1Balance.currency.wrapped.sortsBefore(token0Balance.currency.wrapped)) {
201
+ [token0Balance, token1Balance] = [token1Balance, token0Balance];
202
+ }
203
+ let preSwapOptimalRatio = this.calculateOptimalRatio(position, position.pool.sqrtRatioX96, true);
204
+ // set up parameters according to which token will be swapped
205
+ let zeroForOne;
206
+ if (position.pool.tickCurrent > position.tickUpper) {
207
+ zeroForOne = true;
208
+ }
209
+ else if (position.pool.tickCurrent < position.tickLower) {
210
+ zeroForOne = false;
211
+ }
212
+ else {
213
+ zeroForOne = new Fraction(token0Balance.quotient, token1Balance.quotient).greaterThan(preSwapOptimalRatio);
214
+ if (!zeroForOne)
215
+ preSwapOptimalRatio = preSwapOptimalRatio.invert();
216
+ }
217
+ const [inputBalance, outputBalance] = zeroForOne
218
+ ? [token0Balance, token1Balance]
219
+ : [token1Balance, token0Balance];
220
+ let optimalRatio = preSwapOptimalRatio;
221
+ let postSwapTargetPool = position.pool;
222
+ let exchangeRate = zeroForOne
223
+ ? position.pool.token0Price
224
+ : position.pool.token1Price;
225
+ let swap = null;
226
+ let ratioAchieved = false;
227
+ let n = 0;
228
+ // iterate until we find a swap with a sufficient ratio or return null
229
+ while (!ratioAchieved) {
230
+ n++;
231
+ if (n > swapAndAddConfig.maxIterations) {
232
+ log.info('max iterations exceeded');
233
+ return {
234
+ status: SwapToRatioStatus.NO_ROUTE_FOUND,
235
+ error: 'max iterations exceeded',
236
+ };
237
+ }
238
+ const amountToSwap = calculateRatioAmountIn(optimalRatio, exchangeRate, inputBalance, outputBalance);
239
+ if (amountToSwap.equalTo(0)) {
240
+ log.info(`no swap needed: amountToSwap = 0`);
241
+ return {
242
+ status: SwapToRatioStatus.NO_SWAP_NEEDED,
243
+ };
244
+ }
245
+ swap = await this.route(amountToSwap, outputBalance.currency, TradeType.EXACT_INPUT, undefined, {
246
+ ...DEFAULT_ROUTING_CONFIG_BY_CHAIN(this.chainId),
247
+ ...routingConfig,
248
+ /// @dev We do not want to query for mixedRoutes for routeToRatio as they are not supported
249
+ /// [Protocol.V3, Protocol.V2] will make sure we only query for V3 and V2
250
+ protocols: [Protocol.V3 /* Protocol.V2 */],
251
+ });
252
+ if (!swap) {
253
+ log.info('no route found from this.route()');
254
+ return {
255
+ status: SwapToRatioStatus.NO_ROUTE_FOUND,
256
+ error: 'no route found',
257
+ };
258
+ }
259
+ const inputBalanceUpdated = inputBalance.subtract(swap.trade.inputAmount);
260
+ const outputBalanceUpdated = outputBalance.add(swap.trade.outputAmount);
261
+ const newRatio = inputBalanceUpdated.divide(outputBalanceUpdated);
262
+ let targetPoolPriceUpdate;
263
+ swap.route.forEach((route) => {
264
+ if (route.protocol === Protocol.V3) {
265
+ const v3Route = route;
266
+ v3Route.route.pools.forEach((pool, i) => {
267
+ if (pool.token0.equals(position.pool.token0) &&
268
+ pool.token1.equals(position.pool.token1) &&
269
+ pool.fee === position.pool.fee) {
270
+ targetPoolPriceUpdate = JSBI.BigInt(v3Route.sqrtPriceX96AfterList[i].toString());
271
+ optimalRatio = this.calculateOptimalRatio(position, JSBI.BigInt(targetPoolPriceUpdate.toString()), zeroForOne);
272
+ }
273
+ });
274
+ }
275
+ });
276
+ if (!targetPoolPriceUpdate) {
277
+ optimalRatio = preSwapOptimalRatio;
278
+ }
279
+ ratioAchieved =
280
+ newRatio.equalTo(optimalRatio) ||
281
+ this.absoluteValue(newRatio.asFraction.divide(optimalRatio).subtract(1)).lessThan(swapAndAddConfig.ratioErrorTolerance);
282
+ if (ratioAchieved && targetPoolPriceUpdate) {
283
+ postSwapTargetPool = new Pool(position.pool.token0, position.pool.token1, position.pool.fee, targetPoolPriceUpdate, position.pool.liquidity, TickMath.getTickAtSqrtRatio(targetPoolPriceUpdate), position.pool.tickDataProvider);
284
+ }
285
+ exchangeRate = swap.trade.outputAmount.divide(swap.trade.inputAmount);
286
+ log.info({
287
+ exchangeRate: exchangeRate.asFraction.toFixed(18),
288
+ optimalRatio: optimalRatio.asFraction.toFixed(18),
289
+ newRatio: newRatio.asFraction.toFixed(18),
290
+ inputBalanceUpdated: inputBalanceUpdated.asFraction.toFixed(18),
291
+ outputBalanceUpdated: outputBalanceUpdated.asFraction.toFixed(18),
292
+ ratioErrorTolerance: swapAndAddConfig.ratioErrorTolerance.toFixed(18),
293
+ iterationN: n.toString(),
294
+ }, 'QuoteToRatio Iteration Parameters');
295
+ if (exchangeRate.equalTo(0)) {
296
+ log.info('exchangeRate to 0');
297
+ return {
298
+ status: SwapToRatioStatus.NO_ROUTE_FOUND,
299
+ error: 'insufficient liquidity to swap to optimal ratio',
300
+ };
301
+ }
302
+ }
303
+ if (!swap) {
304
+ return {
305
+ status: SwapToRatioStatus.NO_ROUTE_FOUND,
306
+ error: 'no route found',
307
+ };
308
+ }
309
+ let methodParameters;
310
+ if (swapAndAddOptions) {
311
+ methodParameters = await this.buildSwapAndAddMethodParameters(swap.trade, swapAndAddOptions, {
312
+ initialBalanceTokenIn: inputBalance,
313
+ initialBalanceTokenOut: outputBalance,
314
+ preLiquidityPosition: position,
315
+ });
316
+ }
317
+ return {
318
+ status: SwapToRatioStatus.SUCCESS,
319
+ result: { ...swap, methodParameters, optimalRatio, postSwapTargetPool },
320
+ };
321
+ }
322
+ /**
323
+ * @inheritdoc IRouter
324
+ */
325
+ async route(amount, quoteCurrency, tradeType, swapConfig, partialRoutingConfig = {}) {
326
+ var _a, _c, _d;
327
+ const { currencyIn, currencyOut } = this.determineCurrencyInOutFromTradeType(tradeType, amount, quoteCurrency);
328
+ const tokenIn = currencyIn.wrapped;
329
+ const tokenOut = currencyOut.wrapped;
330
+ metric.setProperty('chainId', this.chainId);
331
+ metric.setProperty('pair', `${tokenIn.symbol}/${tokenOut.symbol}`);
332
+ metric.setProperty('tokenIn', tokenIn.address);
333
+ metric.setProperty('tokenOut', tokenOut.address);
334
+ metric.setProperty('tradeType', tradeType === TradeType.EXACT_INPUT ? 'ExactIn' : 'ExactOut');
335
+ metric.putMetric(`QuoteRequestedForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
336
+ // Get a block number to specify in all our calls. Ensures data we fetch from chain is
337
+ // from the same block.
338
+ const blockNumber = (_a = partialRoutingConfig.blockNumber) !== null && _a !== void 0 ? _a : this.getBlockNumberPromise();
339
+ const routingConfig = _.merge({}, DEFAULT_ROUTING_CONFIG_BY_CHAIN(this.chainId), partialRoutingConfig, { blockNumber });
340
+ const gasPriceWei = await this.getGasPriceWei();
341
+ const quoteToken = quoteCurrency.wrapped;
342
+ const [v3GasModel, mixedRouteGasModel] = await this.getGasModels(gasPriceWei, amount.currency.wrapped, quoteToken, { blockNumber });
343
+ // Create a Set to sanitize the protocols input, a Set of undefined becomes an empty set,
344
+ // Then create an Array from the values of that Set.
345
+ const protocols = Array.from(new Set(routingConfig.protocols).values());
346
+ const cacheMode = await ((_c = this.routeCachingProvider) === null || _c === void 0 ? void 0 : _c.getCacheMode(this.chainId, amount, quoteToken, tradeType, protocols));
347
+ // Fetch CachedRoutes
348
+ let cachedRoutes;
349
+ if (cacheMode !== CacheMode.Darkmode) {
350
+ cachedRoutes = await ((_d = this.routeCachingProvider) === null || _d === void 0 ? void 0 : _d.getCachedRoute(this.chainId, amount, quoteToken, tradeType, protocols, await blockNumber));
351
+ }
352
+ if (cacheMode && cacheMode !== CacheMode.Darkmode && !cachedRoutes) {
353
+ metric.putMetric(`GetCachedRoute_miss_${cacheMode}`, 1, MetricLoggerUnit.Count);
354
+ log.info({
355
+ tokenIn: tokenIn.symbol,
356
+ tokenInAddress: tokenIn.address,
357
+ tokenOut: tokenOut.symbol,
358
+ tokenOutAddress: tokenOut.address,
359
+ cacheMode,
360
+ amount: amount.toExact(),
361
+ chainId: this.chainId,
362
+ tradeType: this.tradeTypeStr(tradeType),
363
+ }, `GetCachedRoute miss ${cacheMode} for ${this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType)}`);
364
+ }
365
+ else if (cachedRoutes) {
366
+ metric.putMetric(`GetCachedRoute_hit_${cacheMode}`, 1, MetricLoggerUnit.Count);
367
+ log.info({
368
+ tokenIn: tokenIn.symbol,
369
+ tokenInAddress: tokenIn.address,
370
+ tokenOut: tokenOut.symbol,
371
+ tokenOutAddress: tokenOut.address,
372
+ cacheMode,
373
+ amount: amount.toExact(),
374
+ chainId: this.chainId,
375
+ tradeType: this.tradeTypeStr(tradeType),
376
+ }, `GetCachedRoute hit ${cacheMode} for ${this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType)}`);
377
+ }
378
+ let swapRouteFromCachePromise = Promise.resolve(null);
379
+ if (cachedRoutes) {
380
+ swapRouteFromCachePromise = this.getSwapRouteFromCache(cachedRoutes, await blockNumber, amount, quoteToken, tradeType, routingConfig, v3GasModel, mixedRouteGasModel, gasPriceWei);
381
+ }
382
+ let swapRouteFromChainPromise = Promise.resolve(null);
383
+ if (!cachedRoutes || cacheMode !== CacheMode.Livemode) {
384
+ swapRouteFromChainPromise = this.getSwapRouteFromChain(amount, tokenIn, tokenOut, protocols, quoteToken, tradeType, routingConfig, v3GasModel, mixedRouteGasModel, gasPriceWei);
385
+ }
386
+ const [swapRouteFromCache, swapRouteFromChain] = await Promise.all([
387
+ swapRouteFromCachePromise,
388
+ swapRouteFromChainPromise,
389
+ ]);
390
+ let swapRouteRaw;
391
+ if (cacheMode === CacheMode.Livemode && swapRouteFromCache) {
392
+ log.info(`CacheMode is ${cacheMode}, and we are using swapRoute from cache`);
393
+ swapRouteRaw = swapRouteFromCache;
394
+ }
395
+ else {
396
+ log.info(`CacheMode is ${cacheMode}, and we are using materialized swapRoute`);
397
+ swapRouteRaw = swapRouteFromChain;
398
+ }
399
+ if (cacheMode === CacheMode.Tapcompare &&
400
+ swapRouteFromCache &&
401
+ swapRouteFromChain) {
402
+ const quoteDiff = swapRouteFromChain.quote.subtract(swapRouteFromCache.quote);
403
+ const quoteGasAdjustedDiff = swapRouteFromChain.quoteGasAdjusted.subtract(swapRouteFromCache.quoteGasAdjusted);
404
+ const gasUsedDiff = swapRouteFromChain.estimatedGasUsed.sub(swapRouteFromCache.estimatedGasUsed);
405
+ // Only log if quoteDiff is different from 0, or if quoteGasAdjustedDiff and gasUsedDiff are both different from 0
406
+ if (!quoteDiff.equalTo(0) ||
407
+ !(quoteGasAdjustedDiff.equalTo(0) || gasUsedDiff.eq(0))) {
408
+ // Calculates the percentage of the difference with respect to the quoteFromChain (not from cache)
409
+ const misquotePercent = quoteGasAdjustedDiff
410
+ .divide(swapRouteFromChain.quoteGasAdjusted)
411
+ .multiply(100);
412
+ metric.putMetric(`TapcompareCachedRoute_quoteGasAdjustedDiffPercent`, Number(misquotePercent.toExact()), MetricLoggerUnit.Percent);
413
+ log.warn({
414
+ quoteFromChain: swapRouteFromChain.quote.toExact(),
415
+ quoteFromCache: swapRouteFromCache.quote.toExact(),
416
+ quoteDiff: quoteDiff.toExact(),
417
+ quoteGasAdjustedFromChain: swapRouteFromChain.quoteGasAdjusted.toExact(),
418
+ quoteGasAdjustedFromCache: swapRouteFromCache.quoteGasAdjusted.toExact(),
419
+ quoteGasAdjustedDiff: quoteGasAdjustedDiff.toExact(),
420
+ gasUsedFromChain: swapRouteFromChain.estimatedGasUsed.toString(),
421
+ gasUsedFromCache: swapRouteFromCache.estimatedGasUsed.toString(),
422
+ gasUsedDiff: gasUsedDiff.toString(),
423
+ routesFromChain: swapRouteFromChain.routes.toString(),
424
+ routesFromCache: swapRouteFromCache.routes.toString(),
425
+ amount: amount.toExact(),
426
+ originalAmount: cachedRoutes === null || cachedRoutes === void 0 ? void 0 : cachedRoutes.originalAmount,
427
+ pair: this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType),
428
+ blockNumber,
429
+ }, `Comparing quotes between Chain and Cache for ${this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType)}`);
430
+ }
431
+ }
432
+ if (!swapRouteRaw) {
433
+ return null;
434
+ }
435
+ const { quote, quoteGasAdjusted, estimatedGasUsed, routes: routeAmounts, estimatedGasUsedQuoteToken, estimatedGasUsedUSD, } = swapRouteRaw;
436
+ if (this.routeCachingProvider &&
437
+ cacheMode !== CacheMode.Darkmode &&
438
+ swapRouteFromChain) {
439
+ // Generate the object to be cached
440
+ const routesToCache = CachedRoutes.fromRoutesWithValidQuotes(swapRouteFromChain.routes, this.chainId, tokenIn, tokenOut, protocols.sort(), // sort it for consistency in the order of the protocols.
441
+ await blockNumber, tradeType, amount.toExact());
442
+ if (routesToCache) {
443
+ // Attempt to insert the entry in cache. This is fire and forget promise.
444
+ // The catch method will prevent any exception from blocking the normal code execution.
445
+ this.routeCachingProvider
446
+ .setCachedRoute(routesToCache, amount)
447
+ .then((success) => {
448
+ const status = success ? 'success' : 'rejected';
449
+ metric.putMetric(`SetCachedRoute_${status}`, 1, MetricLoggerUnit.Count);
450
+ })
451
+ .catch((reason) => {
452
+ log.error({
453
+ reason: reason,
454
+ tokenPair: this.tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType),
455
+ }, `SetCachedRoute failure`);
456
+ metric.putMetric(`SetCachedRoute_failure`, 1, MetricLoggerUnit.Count);
457
+ });
458
+ }
459
+ }
460
+ metric.putMetric(`QuoteFoundForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
461
+ // Build Trade object that represents the optimal swap.
462
+ const trade = buildTrade(currencyIn, currencyOut, tradeType, routeAmounts);
463
+ let methodParameters;
464
+ // If user provided recipient, deadline etc. we also generate the calldata required to execute
465
+ // the swap and return it too.
466
+ if (swapConfig) {
467
+ methodParameters = buildSwapMethodParameters(trade, swapConfig, this.chainId);
468
+ }
469
+ const swapRoute = {
470
+ quote,
471
+ quoteGasAdjusted,
472
+ estimatedGasUsed,
473
+ estimatedGasUsedQuoteToken,
474
+ estimatedGasUsedUSD,
475
+ gasPriceWei,
476
+ route: routeAmounts,
477
+ trade,
478
+ methodParameters,
479
+ blockNumber: BigNumber.from(await blockNumber),
480
+ };
481
+ if (swapConfig &&
482
+ swapConfig.simulate &&
483
+ methodParameters &&
484
+ methodParameters.calldata) {
485
+ if (!this.simulator) {
486
+ throw new Error('Simulator not initialized!');
487
+ }
488
+ log.info({ swapConfig, methodParameters }, 'Starting simulation');
489
+ const fromAddress = swapConfig.simulate.fromAddress;
490
+ const beforeSimulate = Date.now();
491
+ const swapRouteWithSimulation = await this.simulator.simulate(fromAddress, swapConfig, swapRoute, amount,
492
+ // Quote will be in WETH even if quoteCurrency is ETH
493
+ // So we init a new CurrencyAmount object here
494
+ CurrencyAmount.fromRawAmount(quoteCurrency, quote.quotient.toString()), this.l2GasDataProvider
495
+ ? await this.l2GasDataProvider.getGasData()
496
+ : undefined, { blockNumber });
497
+ metric.putMetric('SimulateTransaction', Date.now() - beforeSimulate, MetricLoggerUnit.Milliseconds);
498
+ return swapRouteWithSimulation;
499
+ }
500
+ return swapRoute;
501
+ }
502
+ async getSwapRouteFromCache(cachedRoutes, blockNumber, amount, quoteToken, tradeType, routingConfig, v3GasModel, mixedRouteGasModel, gasPriceWei) {
503
+ log.info({
504
+ protocols: cachedRoutes.protocolsCovered,
505
+ tradeType: cachedRoutes.tradeType,
506
+ cachedBlockNumber: cachedRoutes.blockNumber,
507
+ quoteBlockNumber: blockNumber,
508
+ }, 'Routing across CachedRoute');
509
+ const quotePromises = [];
510
+ const v3Routes = cachedRoutes.routes.filter((route) => route.protocol === Protocol.V3);
511
+ const v2Routes = cachedRoutes.routes.filter((route) => route.protocol === Protocol.V2);
512
+ const mixedRoutes = cachedRoutes.routes.filter((route) => route.protocol === Protocol.MIXED);
513
+ let percents;
514
+ let amounts;
515
+ if (cachedRoutes.routes.length > 1) {
516
+ // If we have more than 1 route, we will quote the different percents for it, following the regular process
517
+ [percents, amounts] = this.getAmountDistribution(amount, routingConfig);
518
+ }
519
+ else if (cachedRoutes.routes.length == 1) {
520
+ [percents, amounts] = [[100], [amount]];
521
+ }
522
+ else {
523
+ // In this case this means that there's no route, so we return null
524
+ return Promise.resolve(null);
525
+ }
526
+ if (v3Routes.length > 0) {
527
+ const v3RoutesFromCache = v3Routes.map((cachedRoute) => cachedRoute.route);
528
+ quotePromises.push(this.v3Quoter.getQuotes(v3RoutesFromCache, amounts, percents, quoteToken, tradeType, routingConfig, undefined, v3GasModel));
529
+ }
530
+ if (v2Routes.length > 0) {
531
+ quotePromises.push(
532
+ // When we fetch the quotes in V2, we are not calling the `onChainProvider` like on v3Routes and mixedRoutes
533
+ // Instead we are using the reserves in the Pool object, so we need to re-load the current reserves.
534
+ this.v2Quoter.getRoutesThenQuotes(v2Routes[0].tokenIn, v2Routes[0].tokenOut, amounts, percents, quoteToken, tradeType, routingConfig, undefined, gasPriceWei));
535
+ }
536
+ if (mixedRoutes.length > 0) {
537
+ const mixedRoutesFromCache = mixedRoutes.map((cachedRoute) => cachedRoute.route);
538
+ quotePromises.push(this.mixedQuoter.getQuotes(mixedRoutesFromCache, amounts, percents, quoteToken, tradeType, routingConfig, undefined, mixedRouteGasModel));
539
+ }
540
+ const getQuotesResults = await Promise.all(quotePromises);
541
+ const allRoutesWithValidQuotes = _.flatMap(getQuotesResults, (quoteResult) => quoteResult.routesWithValidQuotes);
542
+ return getBestSwapRoute(amount, percents, allRoutesWithValidQuotes, tradeType, this.chainId, routingConfig, v3GasModel);
543
+ }
544
+ async getSwapRouteFromChain(amount, tokenIn, tokenOut, protocols, quoteToken, tradeType, routingConfig, v3GasModel, mixedRouteGasModel, gasPriceWei) {
545
+ // Generate our distribution of amounts, i.e. fractions of the input amount.
546
+ // We will get quotes for fractions of the input amount for different routes, then
547
+ // combine to generate split routes.
548
+ const [percents, amounts] = this.getAmountDistribution(amount, routingConfig);
549
+ const noProtocolsSpecified = protocols.length === 0;
550
+ const v3ProtocolSpecified = protocols.includes(Protocol.V3);
551
+ const v2ProtocolSpecified = protocols.includes(Protocol.V2);
552
+ const v2SupportedInChain = V2_SUPPORTED.includes(this.chainId);
553
+ const shouldQueryMixedProtocol = protocols.includes(Protocol.MIXED) ||
554
+ (noProtocolsSpecified && v2SupportedInChain);
555
+ const mixedProtocolAllowed = [ChainId.MAINNET, ChainId.GOERLI].includes(this.chainId) &&
556
+ tradeType === TradeType.EXACT_INPUT;
557
+ const quotePromises = [];
558
+ // Maybe Quote V3 - if V3 is specified, or no protocol is specified
559
+ if (v3ProtocolSpecified || noProtocolsSpecified) {
560
+ log.info({ protocols, tradeType }, 'Routing across V3');
561
+ quotePromises.push(this.v3Quoter.getRoutesThenQuotes(tokenIn, tokenOut, amounts, percents, quoteToken, tradeType, routingConfig, v3GasModel));
562
+ }
563
+ // Maybe Quote V2 - if V2 is specified, or no protocol is specified AND v2 is supported in this chain
564
+ if (v2SupportedInChain && (v2ProtocolSpecified || noProtocolsSpecified)) {
565
+ log.info({ protocols, tradeType }, 'Routing across V2');
566
+ quotePromises.push(this.v2Quoter.getRoutesThenQuotes(tokenIn, tokenOut, amounts, percents, quoteToken, tradeType, routingConfig, undefined, gasPriceWei));
567
+ }
568
+ // Maybe Quote mixed routes
569
+ // if MixedProtocol is specified or no protocol is specified and v2 is supported AND tradeType is ExactIn
570
+ // AND is Mainnet or Gorli
571
+ if (shouldQueryMixedProtocol && mixedProtocolAllowed) {
572
+ log.info({ protocols, tradeType }, 'Routing across MixedRoutes');
573
+ quotePromises.push(this.mixedQuoter.getRoutesThenQuotes(tokenIn, tokenOut, amounts, percents, quoteToken, tradeType, routingConfig, mixedRouteGasModel));
574
+ }
575
+ const getQuotesResults = await Promise.all(quotePromises);
576
+ const allRoutesWithValidQuotes = [];
577
+ const allCandidatePools = [];
578
+ getQuotesResults.forEach((getQuoteResult) => {
579
+ allRoutesWithValidQuotes.push(...getQuoteResult.routesWithValidQuotes);
580
+ if (getQuoteResult.candidatePools) {
581
+ allCandidatePools.push(getQuoteResult.candidatePools);
582
+ }
583
+ });
584
+ if (allRoutesWithValidQuotes.length === 0) {
585
+ log.info({ allRoutesWithValidQuotes }, 'Received no valid quotes');
586
+ return null;
587
+ }
588
+ // Given all the quotes for all the amounts for all the routes, find the best combination.
589
+ const bestSwapRoute = await getBestSwapRoute(amount, percents, allRoutesWithValidQuotes, tradeType, this.chainId, routingConfig, v3GasModel);
590
+ if (bestSwapRoute) {
591
+ this.emitPoolSelectionMetrics(bestSwapRoute, allCandidatePools);
592
+ }
593
+ return bestSwapRoute;
594
+ }
595
+ tradeTypeStr(tradeType) {
596
+ return tradeType === TradeType.EXACT_INPUT ? 'ExactIn' : 'ExactOut';
597
+ }
598
+ tokenPairSymbolTradeTypeChainId(tokenIn, tokenOut, tradeType) {
599
+ return `${tokenIn.symbol}/${tokenOut.symbol}/${this.tradeTypeStr(tradeType)}/${this.chainId}`;
600
+ }
601
+ determineCurrencyInOutFromTradeType(tradeType, amount, quoteCurrency) {
602
+ if (tradeType === TradeType.EXACT_INPUT) {
603
+ return {
604
+ currencyIn: amount.currency,
605
+ currencyOut: quoteCurrency,
606
+ };
607
+ }
608
+ else {
609
+ return {
610
+ currencyIn: quoteCurrency,
611
+ currencyOut: amount.currency,
612
+ };
613
+ }
614
+ }
615
+ async getGasPriceWei() {
616
+ // Track how long it takes to resolve this async call.
617
+ const beforeGasTimestamp = Date.now();
618
+ // Get an estimate of the gas price to use when estimating gas cost of different routes.
619
+ const { gasPriceWei } = await this.gasPriceProvider.getGasPrice();
620
+ metric.putMetric('GasPriceLoad', Date.now() - beforeGasTimestamp, MetricLoggerUnit.Milliseconds);
621
+ return gasPriceWei;
622
+ }
623
+ async getGasModels(gasPriceWei, amountToken, quoteToken, providerConfig) {
624
+ const beforeGasModel = Date.now();
625
+ const usdPoolPromise = getHighestLiquidityV3USDPool(this.chainId, this.v3PoolProvider, providerConfig);
626
+ const nativeCurrency = WRAPPED_NATIVE_CURRENCY[this.chainId];
627
+ const nativeQuoteTokenV3PoolPromise = !quoteToken.equals(nativeCurrency)
628
+ ? getHighestLiquidityV3NativePool(quoteToken, this.v3PoolProvider, providerConfig)
629
+ : Promise.resolve(null);
630
+ const nativeAmountTokenV3PoolPromise = !amountToken.equals(nativeCurrency)
631
+ ? getHighestLiquidityV3NativePool(amountToken, this.v3PoolProvider, providerConfig)
632
+ : Promise.resolve(null);
633
+ const [usdPool, nativeQuoteTokenV3Pool, nativeAmountTokenV3Pool] = await Promise.all([
634
+ usdPoolPromise,
635
+ nativeQuoteTokenV3PoolPromise,
636
+ nativeAmountTokenV3PoolPromise,
637
+ ]);
638
+ const pools = {
639
+ usdPool: usdPool,
640
+ nativeQuoteTokenV3Pool: nativeQuoteTokenV3Pool,
641
+ nativeAmountTokenV3Pool: nativeAmountTokenV3Pool,
642
+ };
643
+ const v3GasModelPromise = this.v3GasModelFactory.buildGasModel({
644
+ chainId: this.chainId,
645
+ gasPriceWei,
646
+ pools,
647
+ amountToken,
648
+ quoteToken,
649
+ v2poolProvider: this.v2PoolProvider,
650
+ l2GasDataProvider: this.l2GasDataProvider,
651
+ providerConfig: providerConfig,
652
+ });
653
+ const mixedRouteGasModelPromise = this.mixedRouteGasModelFactory.buildGasModel({
654
+ chainId: this.chainId,
655
+ gasPriceWei,
656
+ pools,
657
+ amountToken,
658
+ quoteToken,
659
+ v2poolProvider: this.v2PoolProvider,
660
+ providerConfig: providerConfig,
661
+ });
662
+ const [v3GasModel, mixedRouteGasModel] = await Promise.all([
663
+ v3GasModelPromise,
664
+ mixedRouteGasModelPromise,
665
+ ]);
666
+ metric.putMetric('GasModelCreation', Date.now() - beforeGasModel, MetricLoggerUnit.Milliseconds);
667
+ return [v3GasModel, mixedRouteGasModel];
668
+ }
669
+ // Note multiplications here can result in a loss of precision in the amounts (e.g. taking 50% of 101)
670
+ // This is reconcilled at the end of the algorithm by adding any lost precision to one of
671
+ // the splits in the route.
672
+ getAmountDistribution(amount, routingConfig) {
673
+ const { distributionPercent } = routingConfig;
674
+ const percents = [];
675
+ const amounts = [];
676
+ for (let i = 1; i <= 100 / distributionPercent; i++) {
677
+ percents.push(i * distributionPercent);
678
+ amounts.push(amount.multiply(new Fraction(i * distributionPercent, 100)));
679
+ }
680
+ return [percents, amounts];
681
+ }
682
+ async buildSwapAndAddMethodParameters(trade, swapAndAddOptions, swapAndAddParameters) {
683
+ const { swapOptions: { recipient, slippageTolerance, deadline, inputTokenPermit }, addLiquidityOptions: addLiquidityConfig, } = swapAndAddOptions;
684
+ const preLiquidityPosition = swapAndAddParameters.preLiquidityPosition;
685
+ const finalBalanceTokenIn = swapAndAddParameters.initialBalanceTokenIn.subtract(trade.inputAmount);
686
+ const finalBalanceTokenOut = swapAndAddParameters.initialBalanceTokenOut.add(trade.outputAmount);
687
+ const approvalTypes = await this.swapRouterProvider.getApprovalType(finalBalanceTokenIn, finalBalanceTokenOut);
688
+ const zeroForOne = finalBalanceTokenIn.currency.wrapped.sortsBefore(finalBalanceTokenOut.currency.wrapped);
689
+ return {
690
+ ...SwapRouter.swapAndAddCallParameters(trade, {
691
+ recipient,
692
+ slippageTolerance,
693
+ deadlineOrPreviousBlockhash: deadline,
694
+ inputTokenPermit,
695
+ }, Position.fromAmounts({
696
+ pool: preLiquidityPosition.pool,
697
+ tickLower: preLiquidityPosition.tickLower,
698
+ tickUpper: preLiquidityPosition.tickUpper,
699
+ amount0: zeroForOne
700
+ ? finalBalanceTokenIn.quotient.toString()
701
+ : finalBalanceTokenOut.quotient.toString(),
702
+ amount1: zeroForOne
703
+ ? finalBalanceTokenOut.quotient.toString()
704
+ : finalBalanceTokenIn.quotient.toString(),
705
+ useFullPrecision: false,
706
+ }), addLiquidityConfig, approvalTypes.approvalTokenIn, approvalTypes.approvalTokenOut),
707
+ to: SWAP_ROUTER_02_ADDRESSES(this.chainId),
708
+ };
709
+ }
710
+ emitPoolSelectionMetrics(swapRouteRaw, allPoolsBySelection) {
711
+ const poolAddressesUsed = new Set();
712
+ const { routes: routeAmounts } = swapRouteRaw;
713
+ _(routeAmounts)
714
+ .flatMap((routeAmount) => {
715
+ const { poolAddresses } = routeAmount;
716
+ return poolAddresses;
717
+ })
718
+ .forEach((address) => {
719
+ poolAddressesUsed.add(address.toLowerCase());
720
+ });
721
+ for (const poolsBySelection of allPoolsBySelection) {
722
+ const { protocol } = poolsBySelection;
723
+ _.forIn(poolsBySelection.selections, (pools, topNSelection) => {
724
+ const topNUsed = _.findLastIndex(pools, (pool) => poolAddressesUsed.has(pool.id.toLowerCase())) + 1;
725
+ metric.putMetric(_.capitalize(`${protocol}${topNSelection}`), topNUsed, MetricLoggerUnit.Count);
726
+ });
727
+ }
728
+ let hasV3Route = false;
729
+ let hasV2Route = false;
730
+ let hasMixedRoute = false;
731
+ for (const routeAmount of routeAmounts) {
732
+ if (routeAmount.protocol === Protocol.V3) {
733
+ hasV3Route = true;
734
+ }
735
+ if (routeAmount.protocol === Protocol.V2) {
736
+ hasV2Route = true;
737
+ }
738
+ if (routeAmount.protocol === Protocol.MIXED) {
739
+ hasMixedRoute = true;
740
+ }
741
+ }
742
+ if (hasMixedRoute && (hasV3Route || hasV2Route)) {
743
+ if (hasV3Route && hasV2Route) {
744
+ metric.putMetric(`MixedAndV3AndV2SplitRoute`, 1, MetricLoggerUnit.Count);
745
+ metric.putMetric(`MixedAndV3AndV2SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
746
+ }
747
+ else if (hasV3Route) {
748
+ metric.putMetric(`MixedAndV3SplitRoute`, 1, MetricLoggerUnit.Count);
749
+ metric.putMetric(`MixedAndV3SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
750
+ }
751
+ else if (hasV2Route) {
752
+ metric.putMetric(`MixedAndV2SplitRoute`, 1, MetricLoggerUnit.Count);
753
+ metric.putMetric(`MixedAndV2SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
754
+ }
755
+ }
756
+ else if (hasV3Route && hasV2Route) {
757
+ metric.putMetric(`V3AndV2SplitRoute`, 1, MetricLoggerUnit.Count);
758
+ metric.putMetric(`V3AndV2SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
759
+ }
760
+ else if (hasMixedRoute) {
761
+ if (routeAmounts.length > 1) {
762
+ metric.putMetric(`MixedSplitRoute`, 1, MetricLoggerUnit.Count);
763
+ metric.putMetric(`MixedSplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
764
+ }
765
+ else {
766
+ metric.putMetric(`MixedRoute`, 1, MetricLoggerUnit.Count);
767
+ metric.putMetric(`MixedRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
768
+ }
769
+ }
770
+ else if (hasV3Route) {
771
+ if (routeAmounts.length > 1) {
772
+ metric.putMetric(`V3SplitRoute`, 1, MetricLoggerUnit.Count);
773
+ metric.putMetric(`V3SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
774
+ }
775
+ else {
776
+ metric.putMetric(`V3Route`, 1, MetricLoggerUnit.Count);
777
+ metric.putMetric(`V3RouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
778
+ }
779
+ }
780
+ else if (hasV2Route) {
781
+ if (routeAmounts.length > 1) {
782
+ metric.putMetric(`V2SplitRoute`, 1, MetricLoggerUnit.Count);
783
+ metric.putMetric(`V2SplitRouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
784
+ }
785
+ else {
786
+ metric.putMetric(`V2Route`, 1, MetricLoggerUnit.Count);
787
+ metric.putMetric(`V2RouteForChain${this.chainId}`, 1, MetricLoggerUnit.Count);
788
+ }
789
+ }
790
+ }
791
+ calculateOptimalRatio(position, sqrtRatioX96, zeroForOne) {
792
+ const upperSqrtRatioX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);
793
+ const lowerSqrtRatioX96 = TickMath.getSqrtRatioAtTick(position.tickLower);
794
+ // returns Fraction(0, 1) for any out of range position regardless of zeroForOne. Implication: function
795
+ // cannot be used to determine the trading direction of out of range positions.
796
+ if (JSBI.greaterThan(sqrtRatioX96, upperSqrtRatioX96) ||
797
+ JSBI.lessThan(sqrtRatioX96, lowerSqrtRatioX96)) {
798
+ return new Fraction(0, 1);
799
+ }
800
+ const precision = JSBI.BigInt('1' + '0'.repeat(18));
801
+ let optimalRatio = new Fraction(SqrtPriceMath.getAmount0Delta(sqrtRatioX96, upperSqrtRatioX96, precision, true), SqrtPriceMath.getAmount1Delta(sqrtRatioX96, lowerSqrtRatioX96, precision, true));
802
+ if (!zeroForOne)
803
+ optimalRatio = optimalRatio.invert();
804
+ return optimalRatio;
805
+ }
806
+ async userHasSufficientBalance(fromAddress, tradeType, amount, quote) {
807
+ try {
808
+ const neededBalance = tradeType === TradeType.EXACT_INPUT ? amount : quote;
809
+ let balance;
810
+ if (neededBalance.currency.isNative) {
811
+ balance = await this.provider.getBalance(fromAddress);
812
+ }
813
+ else {
814
+ const tokenContract = Erc20__factory.connect(neededBalance.currency.address, this.provider);
815
+ balance = await tokenContract.balanceOf(fromAddress);
816
+ }
817
+ return balance.gte(BigNumber.from(neededBalance.quotient.toString()));
818
+ }
819
+ catch (e) {
820
+ log.error(e, 'Error while checking user balance');
821
+ return false;
822
+ }
823
+ }
824
+ absoluteValue(fraction) {
825
+ const numeratorAbs = JSBI.lessThan(fraction.numerator, JSBI.BigInt(0))
826
+ ? JSBI.unaryMinus(fraction.numerator)
827
+ : fraction.numerator;
828
+ const denominatorAbs = JSBI.lessThan(fraction.denominator, JSBI.BigInt(0))
829
+ ? JSBI.unaryMinus(fraction.denominator)
830
+ : fraction.denominator;
831
+ return new Fraction(numeratorAbs, denominatorAbs);
832
+ }
833
+ getBlockNumberPromise() {
834
+ return retry(async (_b, attempt) => {
835
+ if (attempt > 1) {
836
+ log.info(`Get block number attempt ${attempt}`);
837
+ }
838
+ return this.provider.getBlockNumber();
839
+ }, {
840
+ retries: 2,
841
+ minTimeout: 100,
842
+ maxTimeout: 1000,
843
+ });
844
+ }
845
+ }
846
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxwaGEtcm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3JvdXRlcnMvYWxwaGEtcm91dGVyL2FscGhhLXJvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFnQixlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN6RSxPQUFPLGtCQUFrQixNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFTLE1BQU0scUJBQXFCLENBQUM7QUFFbEUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzFFLE9BQU8sRUFDTCxPQUFPLEVBRVAsUUFBUSxFQUVSLFNBQVMsR0FDVixNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sS0FBSyxNQUFNLGFBQWEsQ0FBQztBQUNoQyxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBQ3ZCLE9BQU8sU0FBUyxNQUFNLFlBQVksQ0FBQztBQUVuQyxPQUFPLEVBQ0wsWUFBWSxFQUNaLFNBQVMsRUFDVCx5QkFBeUIsRUFDekIsZ0NBQWdDLEVBQ2hDLHFCQUFxQixFQUNyQix5QkFBeUIsRUFDekIscUJBQXFCLEVBQ3JCLHlCQUF5QixFQUN6Qix1QkFBdUIsRUFDdkIseUJBQXlCLEVBTXpCLHNCQUFzQixFQUN0QixXQUFXLEVBQ1gsdUJBQXVCLEVBQ3ZCLG9CQUFvQixFQUVwQix3QkFBd0IsRUFDeEIsd0JBQXdCLEVBQ3hCLGtCQUFrQixFQUNsQix3QkFBd0IsRUFDeEIsbUJBQW1CLEVBQ25CLGVBQWUsRUFDZiwrQkFBK0IsRUFDL0IsK0JBQStCLEdBQ2hDLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUNM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