@juiceswapxyz/smart-order-router 0.0.1-beta.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 (534) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/LICENSE +674 -0
  3. package/README.md +308 -0
  4. package/build/main/index.d.ts +3 -0
  5. package/build/main/index.js +20 -0
  6. package/build/main/providers/cache-node.d.ts +10 -0
  7. package/build/main/providers/cache-node.js +33 -0
  8. package/build/main/providers/cache.d.ts +14 -0
  9. package/build/main/providers/cache.js +3 -0
  10. package/build/main/providers/caching/route/index.d.ts +2 -0
  11. package/build/main/providers/caching/route/index.js +19 -0
  12. package/build/main/providers/caching/route/model/cache-mode.d.ts +16 -0
  13. package/build/main/providers/caching/route/model/cache-mode.js +21 -0
  14. package/build/main/providers/caching/route/model/cached-route.d.ts +29 -0
  15. package/build/main/providers/caching/route/model/cached-route.js +77 -0
  16. package/build/main/providers/caching/route/model/cached-routes.d.ts +67 -0
  17. package/build/main/providers/caching/route/model/cached-routes.js +81 -0
  18. package/build/main/providers/caching/route/model/index.d.ts +3 -0
  19. package/build/main/providers/caching/route/model/index.js +20 -0
  20. package/build/main/providers/caching/route/route-caching-provider.d.ts +111 -0
  21. package/build/main/providers/caching/route/route-caching-provider.js +86 -0
  22. package/build/main/providers/caching-gas-provider.d.ts +23 -0
  23. package/build/main/providers/caching-gas-provider.js +41 -0
  24. package/build/main/providers/caching-subgraph-provider.d.ts +33 -0
  25. package/build/main/providers/caching-subgraph-provider.js +163 -0
  26. package/build/main/providers/caching-token-list-provider.d.ts +52 -0
  27. package/build/main/providers/caching-token-list-provider.js +147 -0
  28. package/build/main/providers/caching-token-provider.d.ts +24 -0
  29. package/build/main/providers/caching-token-provider.js +234 -0
  30. package/build/main/providers/eip-1559-gas-price-provider.d.ts +31 -0
  31. package/build/main/providers/eip-1559-gas-price-provider.js +71 -0
  32. package/build/main/providers/eth-estimate-gas-provider.d.ts +21 -0
  33. package/build/main/providers/eth-estimate-gas-provider.js +91 -0
  34. package/build/main/providers/eth-gas-station-info-gas-price-provider.d.ts +19 -0
  35. package/build/main/providers/eth-gas-station-info-gas-price-provider.js +36 -0
  36. package/build/main/providers/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 +47 -0
  39. package/build/main/providers/index.js +64 -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 +37 -0
  48. package/build/main/providers/on-chain-quote-provider.d.ts +258 -0
  49. package/build/main/providers/on-chain-quote-provider.js +687 -0
  50. package/build/main/providers/pool-provider.d.ts +45 -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 +46 -0
  57. package/build/main/providers/simulation-provider.js +138 -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 +55 -0
  63. package/build/main/providers/subgraph-provider.js +261 -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/tenderly-simulation-provider.d.ts +69 -0
  67. package/build/main/providers/tenderly-simulation-provider.js +456 -0
  68. package/build/main/providers/token-fee-fetcher.d.ts +31 -0
  69. package/build/main/providers/token-fee-fetcher.js +114 -0
  70. package/build/main/providers/token-properties-provider.d.ts +31 -0
  71. package/build/main/providers/token-properties-provider.js +118 -0
  72. package/build/main/providers/token-provider.d.ts +138 -0
  73. package/build/main/providers/token-provider.js +386 -0
  74. package/build/main/providers/token-validator-provider.d.ts +42 -0
  75. package/build/main/providers/token-validator-provider.js +99 -0
  76. package/build/main/providers/uri-subgraph-provider.d.ts +20 -0
  77. package/build/main/providers/uri-subgraph-provider.js +65 -0
  78. package/build/main/providers/v2/caching-pool-provider.d.ts +33 -0
  79. package/build/main/providers/v2/caching-pool-provider.js +89 -0
  80. package/build/main/providers/v2/caching-subgraph-provider.d.ts +19 -0
  81. package/build/main/providers/v2/caching-subgraph-provider.js +24 -0
  82. package/build/main/providers/v2/pool-provider.d.ts +63 -0
  83. package/build/main/providers/v2/pool-provider.js +148 -0
  84. package/build/main/providers/v2/quote-provider.d.ts +34 -0
  85. package/build/main/providers/v2/quote-provider.js +90 -0
  86. package/build/main/providers/v2/static-subgraph-provider.d.ts +19 -0
  87. package/build/main/providers/v2/static-subgraph-provider.js +168 -0
  88. package/build/main/providers/v2/subgraph-provider-with-fallback.d.ts +16 -0
  89. package/build/main/providers/v2/subgraph-provider-with-fallback.js +23 -0
  90. package/build/main/providers/v2/subgraph-provider.d.ts +52 -0
  91. package/build/main/providers/v2/subgraph-provider.js +334 -0
  92. package/build/main/providers/v2/uri-subgraph-provider.d.ts +4 -0
  93. package/build/main/providers/v2/uri-subgraph-provider.js +8 -0
  94. package/build/main/providers/v3/caching-pool-provider.d.ts +32 -0
  95. package/build/main/providers/v3/caching-pool-provider.js +84 -0
  96. package/build/main/providers/v3/caching-subgraph-provider.d.ts +19 -0
  97. package/build/main/providers/v3/caching-subgraph-provider.js +24 -0
  98. package/build/main/providers/v3/gas-data-provider.d.ts +39 -0
  99. package/build/main/providers/v3/gas-data-provider.js +26 -0
  100. package/build/main/providers/v3/pool-provider.d.ts +77 -0
  101. package/build/main/providers/v3/pool-provider.js +108 -0
  102. package/build/main/providers/v3/static-subgraph-provider.d.ts +21 -0
  103. package/build/main/providers/v3/static-subgraph-provider.js +214 -0
  104. package/build/main/providers/v3/subgraph-provider-with-fallback.d.ts +12 -0
  105. package/build/main/providers/v3/subgraph-provider-with-fallback.js +19 -0
  106. package/build/main/providers/v3/subgraph-provider.d.ts +45 -0
  107. package/build/main/providers/v3/subgraph-provider.js +45 -0
  108. package/build/main/providers/v3/uri-subgraph-provider.d.ts +4 -0
  109. package/build/main/providers/v3/uri-subgraph-provider.js +8 -0
  110. package/build/main/providers/v4/caching-pool-provider.d.ts +24 -0
  111. package/build/main/providers/v4/caching-pool-provider.js +81 -0
  112. package/build/main/providers/v4/caching-subgraph-provider.d.ts +19 -0
  113. package/build/main/providers/v4/caching-subgraph-provider.js +24 -0
  114. package/build/main/providers/v4/euler-swap-hooks-subgraph-provider.d.ts +25 -0
  115. package/build/main/providers/v4/euler-swap-hooks-subgraph-provider.js +160 -0
  116. package/build/main/providers/v4/pool-provider.d.ts +59 -0
  117. package/build/main/providers/v4/pool-provider.js +115 -0
  118. package/build/main/providers/v4/static-subgraph-provider.d.ts +15 -0
  119. package/build/main/providers/v4/static-subgraph-provider.js +78 -0
  120. package/build/main/providers/v4/subgraph-provider-with-fallback.d.ts +5 -0
  121. package/build/main/providers/v4/subgraph-provider-with-fallback.js +12 -0
  122. package/build/main/providers/v4/subgraph-provider.d.ts +63 -0
  123. package/build/main/providers/v4/subgraph-provider.js +63 -0
  124. package/build/main/providers/v4/uri-subgraph-provider.d.ts +4 -0
  125. package/build/main/providers/v4/uri-subgraph-provider.js +8 -0
  126. package/build/main/routers/alpha-router/alpha-router.d.ts +469 -0
  127. package/build/main/routers/alpha-router/alpha-router.js +1677 -0
  128. package/build/main/routers/alpha-router/config.d.ts +4 -0
  129. package/build/main/routers/alpha-router/config.js +129 -0
  130. package/build/main/routers/alpha-router/entities/index.d.ts +1 -0
  131. package/build/main/routers/alpha-router/entities/index.js +18 -0
  132. package/build/main/routers/alpha-router/entities/route-with-valid-quote.d.ts +208 -0
  133. package/build/main/routers/alpha-router/entities/route-with-valid-quote.js +194 -0
  134. package/build/main/routers/alpha-router/functions/best-swap-route.d.ts +24 -0
  135. package/build/main/routers/alpha-router/functions/best-swap-route.js +538 -0
  136. package/build/main/routers/alpha-router/functions/calculate-ratio-amount-in.d.ts +3 -0
  137. package/build/main/routers/alpha-router/functions/calculate-ratio-amount-in.js +18 -0
  138. package/build/main/routers/alpha-router/functions/compute-all-routes.d.ts +12 -0
  139. package/build/main/routers/alpha-router/functions/compute-all-routes.js +133 -0
  140. package/build/main/routers/alpha-router/functions/get-candidate-pools.d.ts +126 -0
  141. package/build/main/routers/alpha-router/functions/get-candidate-pools.js +1526 -0
  142. package/build/main/routers/alpha-router/gas-models/gas-costs.d.ts +12 -0
  143. package/build/main/routers/alpha-router/gas-models/gas-costs.js +188 -0
  144. package/build/main/routers/alpha-router/gas-models/gas-model.d.ts +107 -0
  145. package/build/main/routers/alpha-router/gas-models/gas-model.js +117 -0
  146. package/build/main/routers/alpha-router/gas-models/index.d.ts +2 -0
  147. package/build/main/routers/alpha-router/gas-models/index.js +19 -0
  148. package/build/main/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.d.ts +24 -0
  149. package/build/main/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.js +161 -0
  150. package/build/main/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.d.ts +15 -0
  151. package/build/main/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.js +191 -0
  152. package/build/main/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.d.ts +31 -0
  153. package/build/main/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.js +169 -0
  154. package/build/main/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.d.ts +26 -0
  155. package/build/main/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.js +41 -0
  156. package/build/main/routers/alpha-router/gas-models/v4/v4-heuristic-gas-model.d.ts +15 -0
  157. package/build/main/routers/alpha-router/gas-models/v4/v4-heuristic-gas-model.js +40 -0
  158. package/build/main/routers/alpha-router/index.d.ts +4 -0
  159. package/build/main/routers/alpha-router/index.js +21 -0
  160. package/build/main/routers/alpha-router/quoters/base-quoter.d.ts +77 -0
  161. package/build/main/routers/alpha-router/quoters/base-quoter.js +76 -0
  162. package/build/main/routers/alpha-router/quoters/index.d.ts +5 -0
  163. package/build/main/routers/alpha-router/quoters/index.js +22 -0
  164. package/build/main/routers/alpha-router/quoters/mixed-quoter.d.ts +32 -0
  165. package/build/main/routers/alpha-router/quoters/mixed-quoter.js +154 -0
  166. package/build/main/routers/alpha-router/quoters/model/index.d.ts +1 -0
  167. package/build/main/routers/alpha-router/quoters/model/index.js +18 -0
  168. package/build/main/routers/alpha-router/quoters/model/results/get-quotes-result.d.ts +6 -0
  169. package/build/main/routers/alpha-router/quoters/model/results/get-quotes-result.js +3 -0
  170. package/build/main/routers/alpha-router/quoters/model/results/get-routes-result.d.ts +6 -0
  171. package/build/main/routers/alpha-router/quoters/model/results/get-routes-result.js +3 -0
  172. package/build/main/routers/alpha-router/quoters/model/results/index.d.ts +2 -0
  173. package/build/main/routers/alpha-router/quoters/model/results/index.js +19 -0
  174. package/build/main/routers/alpha-router/quoters/v2-quoter.d.ts +24 -0
  175. package/build/main/routers/alpha-router/quoters/v2-quoter.js +141 -0
  176. package/build/main/routers/alpha-router/quoters/v3-quoter.d.ts +19 -0
  177. package/build/main/routers/alpha-router/quoters/v3-quoter.js +125 -0
  178. package/build/main/routers/alpha-router/quoters/v4-quoter.d.ts +18 -0
  179. package/build/main/routers/alpha-router/quoters/v4-quoter.js +121 -0
  180. package/build/main/routers/index.d.ts +4 -0
  181. package/build/main/routers/index.js +21 -0
  182. package/build/main/routers/legacy-router/bases.d.ts +201 -0
  183. package/build/main/routers/legacy-router/bases.js +121 -0
  184. package/build/main/routers/legacy-router/index.d.ts +1 -0
  185. package/build/main/routers/legacy-router/index.js +18 -0
  186. package/build/main/routers/legacy-router/legacy-router.d.ts +41 -0
  187. package/build/main/routers/legacy-router/legacy-router.js +291 -0
  188. package/build/main/routers/router.d.ts +195 -0
  189. package/build/main/routers/router.js +92 -0
  190. package/build/main/tsconfig.tsbuildinfo +1 -0
  191. package/build/main/types/other/commons.d.ts +16 -0
  192. package/build/main/types/other/commons.js +6 -0
  193. package/build/main/types/other/factories/Erc20__factory.d.ts +45 -0
  194. package/build/main/types/other/factories/Erc20__factory.js +240 -0
  195. package/build/main/types/other/factories/GasDataArbitrum__factory.d.ts +18 -0
  196. package/build/main/types/other/factories/GasDataArbitrum__factory.js +58 -0
  197. package/build/main/types/other/factories/IMixedRouteQuoterV1__factory.d.ts +41 -0
  198. package/build/main/types/other/factories/IMixedRouteQuoterV1__factory.js +156 -0
  199. package/build/main/types/other/factories/ITokenValidator__factory.d.ts +22 -0
  200. package/build/main/types/other/factories/ITokenValidator__factory.js +78 -0
  201. package/build/main/types/other/factories/MixedRouteQuoterV2__factory.d.ts +86 -0
  202. package/build/main/types/other/factories/MixedRouteQuoterV2__factory.js +477 -0
  203. package/build/main/types/other/factories/Permit2__factory.d.ts +87 -0
  204. package/build/main/types/other/factories/Permit2__factory.js +936 -0
  205. package/build/main/types/other/factories/StateView__factory.d.ts +32 -0
  206. package/build/main/types/other/factories/StateView__factory.js +383 -0
  207. package/build/main/types/other/factories/SwapRouter02__factory.d.ts +67 -0
  208. package/build/main/types/other/factories/SwapRouter02__factory.js +1098 -0
  209. package/build/main/types/other/factories/TokenFeeDetector__factory.d.ts +47 -0
  210. package/build/main/types/other/factories/TokenFeeDetector__factory.js +243 -0
  211. package/build/main/types/other/factories/V4Quoter__factory.d.ts +37 -0
  212. package/build/main/types/other/factories/V4Quoter__factory.js +312 -0
  213. package/build/main/types/v2/commons.d.ts +16 -0
  214. package/build/main/types/v2/commons.js +6 -0
  215. package/build/main/types/v2/factories/IUniswapV2Pair__factory.d.ts +35 -0
  216. package/build/main/types/v2/factories/IUniswapV2Pair__factory.js +671 -0
  217. package/build/main/types/v3/commons.d.ts +16 -0
  218. package/build/main/types/v3/commons.js +6 -0
  219. package/build/main/types/v3/factories/IERC20Metadata__factory.d.ts +35 -0
  220. package/build/main/types/v3/factories/IERC20Metadata__factory.js +242 -0
  221. package/build/main/types/v3/factories/IQuoterV2__factory.d.ts +41 -0
  222. package/build/main/types/v3/factories/IQuoterV2__factory.js +220 -0
  223. package/build/main/types/v3/factories/IUniswapV3PoolState__factory.d.ts +22 -0
  224. package/build/main/types/v3/factories/IUniswapV3PoolState__factory.js +266 -0
  225. package/build/main/types/v3/factories/UniswapInterfaceMulticall__factory.d.ts +61 -0
  226. package/build/main/types/v3/factories/UniswapInterfaceMulticall__factory.js +127 -0
  227. package/build/main/util/addresses.d.ts +32 -0
  228. package/build/main/util/addresses.js +112 -0
  229. package/build/main/util/amounts.d.ts +10 -0
  230. package/build/main/util/amounts.js +94 -0
  231. package/build/main/util/callData.d.ts +1 -0
  232. package/build/main/util/callData.js +6 -0
  233. package/build/main/util/chains.d.ts +69 -0
  234. package/build/main/util/chains.js +694 -0
  235. package/build/main/util/defaultBlocksToLive.d.ts +4 -0
  236. package/build/main/util/defaultBlocksToLive.js +53 -0
  237. package/build/main/util/gas-factory-helpers.d.ts +34 -0
  238. package/build/main/util/gas-factory-helpers.js +439 -0
  239. package/build/main/util/hooksOptions.d.ts +5 -0
  240. package/build/main/util/hooksOptions.js +10 -0
  241. package/build/main/util/index.d.ts +10 -0
  242. package/build/main/util/index.js +27 -0
  243. package/build/main/util/intent.d.ts +6 -0
  244. package/build/main/util/intent.js +13 -0
  245. package/build/main/util/l2FeeChains.d.ts +2 -0
  246. package/build/main/util/l2FeeChains.js +18 -0
  247. package/build/main/util/log.d.ts +3 -0
  248. package/build/main/util/log.js +97 -0
  249. package/build/main/util/methodParameters.d.ts +5 -0
  250. package/build/main/util/methodParameters.js +147 -0
  251. package/build/main/util/metric.d.ts +48 -0
  252. package/build/main/util/metric.js +59 -0
  253. package/build/main/util/mixedRouteFilterOutV4Pools.d.ts +3 -0
  254. package/build/main/util/mixedRouteFilterOutV4Pools.js +17 -0
  255. package/build/main/util/onchainQuoteProviderConfigs.d.ts +42 -0
  256. package/build/main/util/onchainQuoteProviderConfigs.js +72 -0
  257. package/build/main/util/pool.d.ts +5 -0
  258. package/build/main/util/pool.js +42 -0
  259. package/build/main/util/protocols.d.ts +2 -0
  260. package/build/main/util/protocols.js +20 -0
  261. package/build/main/util/routes.d.ts +11 -0
  262. package/build/main/util/routes.js +148 -0
  263. package/build/main/util/serializeRouteIds.d.ts +2 -0
  264. package/build/main/util/serializeRouteIds.js +12 -0
  265. package/build/main/util/tenderlySimulationErrorBreakDown.d.ts +3 -0
  266. package/build/main/util/tenderlySimulationErrorBreakDown.js +33 -0
  267. package/build/main/util/unsupported-tokens.d.ts +37 -0
  268. package/build/main/util/unsupported-tokens.js +1119 -0
  269. package/build/module/index.d.ts +3 -0
  270. package/build/module/index.js +4 -0
  271. package/build/module/providers/cache-node.d.ts +10 -0
  272. package/build/module/providers/cache-node.js +29 -0
  273. package/build/module/providers/cache.d.ts +14 -0
  274. package/build/module/providers/cache.js +2 -0
  275. package/build/module/providers/caching/route/index.d.ts +2 -0
  276. package/build/module/providers/caching/route/index.js +3 -0
  277. package/build/module/providers/caching/route/model/cache-mode.d.ts +16 -0
  278. package/build/module/providers/caching/route/model/cache-mode.js +18 -0
  279. package/build/module/providers/caching/route/model/cached-route.d.ts +29 -0
  280. package/build/module/providers/caching/route/model/cached-route.js +73 -0
  281. package/build/module/providers/caching/route/model/cached-routes.d.ts +67 -0
  282. package/build/module/providers/caching/route/model/cached-routes.js +74 -0
  283. package/build/module/providers/caching/route/model/index.d.ts +3 -0
  284. package/build/module/providers/caching/route/model/index.js +4 -0
  285. package/build/module/providers/caching/route/route-caching-provider.d.ts +111 -0
  286. package/build/module/providers/caching/route/route-caching-provider.js +82 -0
  287. package/build/module/providers/caching-gas-provider.d.ts +23 -0
  288. package/build/module/providers/caching-gas-provider.js +37 -0
  289. package/build/module/providers/caching-subgraph-provider.d.ts +33 -0
  290. package/build/module/providers/caching-subgraph-provider.js +159 -0
  291. package/build/module/providers/caching-token-list-provider.d.ts +52 -0
  292. package/build/module/providers/caching-token-list-provider.js +140 -0
  293. package/build/module/providers/caching-token-provider.d.ts +24 -0
  294. package/build/module/providers/caching-token-provider.js +227 -0
  295. package/build/module/providers/eip-1559-gas-price-provider.d.ts +31 -0
  296. package/build/module/providers/eip-1559-gas-price-provider.js +64 -0
  297. package/build/module/providers/eth-estimate-gas-provider.d.ts +21 -0
  298. package/build/module/providers/eth-estimate-gas-provider.js +99 -0
  299. package/build/module/providers/eth-gas-station-info-gas-price-provider.d.ts +19 -0
  300. package/build/module/providers/eth-gas-station-info-gas-price-provider.js +29 -0
  301. package/build/module/providers/gas-price-provider.d.ts +10 -0
  302. package/build/module/providers/gas-price-provider.js +6 -0
  303. package/build/module/providers/index.d.ts +47 -0
  304. package/build/module/providers/index.js +48 -0
  305. package/build/module/providers/legacy-gas-price-provider.d.ts +7 -0
  306. package/build/module/providers/legacy-gas-price-provider.js +14 -0
  307. package/build/module/providers/multicall-provider.d.ts +83 -0
  308. package/build/module/providers/multicall-provider.js +11 -0
  309. package/build/module/providers/multicall-uniswap-provider.d.ts +37 -0
  310. package/build/module/providers/multicall-uniswap-provider.js +157 -0
  311. package/build/module/providers/on-chain-gas-price-provider.d.ts +19 -0
  312. package/build/module/providers/on-chain-gas-price-provider.js +33 -0
  313. package/build/module/providers/on-chain-quote-provider.d.ts +258 -0
  314. package/build/module/providers/on-chain-quote-provider.js +681 -0
  315. package/build/module/providers/pool-provider.d.ts +45 -0
  316. package/build/module/providers/pool-provider.js +66 -0
  317. package/build/module/providers/portion-provider.d.ts +86 -0
  318. package/build/module/providers/portion-provider.js +114 -0
  319. package/build/module/providers/provider.d.ts +38 -0
  320. package/build/module/providers/provider.js +2 -0
  321. package/build/module/providers/simulation-provider.d.ts +46 -0
  322. package/build/module/providers/simulation-provider.js +140 -0
  323. package/build/module/providers/static-gas-price-provider.d.ts +7 -0
  324. package/build/module/providers/static-gas-price-provider.js +9 -0
  325. package/build/module/providers/subgraph-provider-with-fallback.d.ts +11 -0
  326. package/build/module/providers/subgraph-provider-with-fallback.js +21 -0
  327. package/build/module/providers/subgraph-provider.d.ts +55 -0
  328. package/build/module/providers/subgraph-provider.js +258 -0
  329. package/build/module/providers/swap-router-provider.d.ts +30 -0
  330. package/build/module/providers/swap-router-provider.js +38 -0
  331. package/build/module/providers/tenderly-simulation-provider.d.ts +69 -0
  332. package/build/module/providers/tenderly-simulation-provider.js +454 -0
  333. package/build/module/providers/token-fee-fetcher.d.ts +31 -0
  334. package/build/module/providers/token-fee-fetcher.js +110 -0
  335. package/build/module/providers/token-properties-provider.d.ts +31 -0
  336. package/build/module/providers/token-properties-provider.js +114 -0
  337. package/build/module/providers/token-provider.d.ts +138 -0
  338. package/build/module/providers/token-provider.js +373 -0
  339. package/build/module/providers/token-validator-provider.d.ts +42 -0
  340. package/build/module/providers/token-validator-provider.js +92 -0
  341. package/build/module/providers/uri-subgraph-provider.d.ts +20 -0
  342. package/build/module/providers/uri-subgraph-provider.js +58 -0
  343. package/build/module/providers/v2/caching-pool-provider.d.ts +33 -0
  344. package/build/module/providers/v2/caching-pool-provider.js +85 -0
  345. package/build/module/providers/v2/caching-subgraph-provider.d.ts +19 -0
  346. package/build/module/providers/v2/caching-subgraph-provider.js +20 -0
  347. package/build/module/providers/v2/pool-provider.d.ts +63 -0
  348. package/build/module/providers/v2/pool-provider.js +141 -0
  349. package/build/module/providers/v2/quote-provider.d.ts +34 -0
  350. package/build/module/providers/v2/quote-provider.js +86 -0
  351. package/build/module/providers/v2/static-subgraph-provider.d.ts +19 -0
  352. package/build/module/providers/v2/static-subgraph-provider.js +161 -0
  353. package/build/module/providers/v2/subgraph-provider-with-fallback.d.ts +16 -0
  354. package/build/module/providers/v2/subgraph-provider-with-fallback.js +19 -0
  355. package/build/module/providers/v2/subgraph-provider.d.ts +52 -0
  356. package/build/module/providers/v2/subgraph-provider.js +331 -0
  357. package/build/module/providers/v2/uri-subgraph-provider.d.ts +4 -0
  358. package/build/module/providers/v2/uri-subgraph-provider.js +4 -0
  359. package/build/module/providers/v3/caching-pool-provider.d.ts +32 -0
  360. package/build/module/providers/v3/caching-pool-provider.js +77 -0
  361. package/build/module/providers/v3/caching-subgraph-provider.d.ts +19 -0
  362. package/build/module/providers/v3/caching-subgraph-provider.js +20 -0
  363. package/build/module/providers/v3/gas-data-provider.d.ts +39 -0
  364. package/build/module/providers/v3/gas-data-provider.js +22 -0
  365. package/build/module/providers/v3/pool-provider.d.ts +77 -0
  366. package/build/module/providers/v3/pool-provider.js +101 -0
  367. package/build/module/providers/v3/static-subgraph-provider.d.ts +21 -0
  368. package/build/module/providers/v3/static-subgraph-provider.js +207 -0
  369. package/build/module/providers/v3/subgraph-provider-with-fallback.d.ts +12 -0
  370. package/build/module/providers/v3/subgraph-provider-with-fallback.js +15 -0
  371. package/build/module/providers/v3/subgraph-provider.d.ts +45 -0
  372. package/build/module/providers/v3/subgraph-provider.js +41 -0
  373. package/build/module/providers/v3/uri-subgraph-provider.d.ts +4 -0
  374. package/build/module/providers/v3/uri-subgraph-provider.js +4 -0
  375. package/build/module/providers/v4/caching-pool-provider.d.ts +24 -0
  376. package/build/module/providers/v4/caching-pool-provider.js +74 -0
  377. package/build/module/providers/v4/caching-subgraph-provider.d.ts +19 -0
  378. package/build/module/providers/v4/caching-subgraph-provider.js +20 -0
  379. package/build/module/providers/v4/euler-swap-hooks-subgraph-provider.d.ts +25 -0
  380. package/build/module/providers/v4/euler-swap-hooks-subgraph-provider.js +153 -0
  381. package/build/module/providers/v4/pool-provider.d.ts +59 -0
  382. package/build/module/providers/v4/pool-provider.js +106 -0
  383. package/build/module/providers/v4/static-subgraph-provider.d.ts +15 -0
  384. package/build/module/providers/v4/static-subgraph-provider.js +71 -0
  385. package/build/module/providers/v4/subgraph-provider-with-fallback.d.ts +5 -0
  386. package/build/module/providers/v4/subgraph-provider-with-fallback.js +8 -0
  387. package/build/module/providers/v4/subgraph-provider.d.ts +63 -0
  388. package/build/module/providers/v4/subgraph-provider.js +59 -0
  389. package/build/module/providers/v4/uri-subgraph-provider.d.ts +4 -0
  390. package/build/module/providers/v4/uri-subgraph-provider.js +4 -0
  391. package/build/module/routers/alpha-router/alpha-router.d.ts +469 -0
  392. package/build/module/routers/alpha-router/alpha-router.js +1679 -0
  393. package/build/module/routers/alpha-router/config.d.ts +4 -0
  394. package/build/module/routers/alpha-router/config.js +125 -0
  395. package/build/module/routers/alpha-router/entities/index.d.ts +1 -0
  396. package/build/module/routers/alpha-router/entities/index.js +2 -0
  397. package/build/module/routers/alpha-router/entities/route-with-valid-quote.d.ts +208 -0
  398. package/build/module/routers/alpha-router/entities/route-with-valid-quote.js +184 -0
  399. package/build/module/routers/alpha-router/functions/best-swap-route.d.ts +24 -0
  400. package/build/module/routers/alpha-router/functions/best-swap-route.js +528 -0
  401. package/build/module/routers/alpha-router/functions/calculate-ratio-amount-in.d.ts +3 -0
  402. package/build/module/routers/alpha-router/functions/calculate-ratio-amount-in.js +14 -0
  403. package/build/module/routers/alpha-router/functions/compute-all-routes.d.ts +12 -0
  404. package/build/module/routers/alpha-router/functions/compute-all-routes.js +125 -0
  405. package/build/module/routers/alpha-router/functions/get-candidate-pools.d.ts +126 -0
  406. package/build/module/routers/alpha-router/functions/get-candidate-pools.js +1515 -0
  407. package/build/module/routers/alpha-router/gas-models/gas-costs.d.ts +12 -0
  408. package/build/module/routers/alpha-router/gas-models/gas-costs.js +177 -0
  409. package/build/module/routers/alpha-router/gas-models/gas-model.d.ts +107 -0
  410. package/build/module/routers/alpha-router/gas-models/gas-model.js +111 -0
  411. package/build/module/routers/alpha-router/gas-models/index.d.ts +2 -0
  412. package/build/module/routers/alpha-router/gas-models/index.js +3 -0
  413. package/build/module/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.d.ts +24 -0
  414. package/build/module/routers/alpha-router/gas-models/mixedRoute/mixed-route-heuristic-gas-model.js +154 -0
  415. package/build/module/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.d.ts +15 -0
  416. package/build/module/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.js +187 -0
  417. package/build/module/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.d.ts +31 -0
  418. package/build/module/routers/alpha-router/gas-models/v2/v2-heuristic-gas-model.js +162 -0
  419. package/build/module/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.d.ts +26 -0
  420. package/build/module/routers/alpha-router/gas-models/v3/v3-heuristic-gas-model.js +37 -0
  421. package/build/module/routers/alpha-router/gas-models/v4/v4-heuristic-gas-model.d.ts +15 -0
  422. package/build/module/routers/alpha-router/gas-models/v4/v4-heuristic-gas-model.js +36 -0
  423. package/build/module/routers/alpha-router/index.d.ts +4 -0
  424. package/build/module/routers/alpha-router/index.js +5 -0
  425. package/build/module/routers/alpha-router/quoters/base-quoter.d.ts +77 -0
  426. package/build/module/routers/alpha-router/quoters/base-quoter.js +69 -0
  427. package/build/module/routers/alpha-router/quoters/index.d.ts +5 -0
  428. package/build/module/routers/alpha-router/quoters/index.js +6 -0
  429. package/build/module/routers/alpha-router/quoters/mixed-quoter.d.ts +32 -0
  430. package/build/module/routers/alpha-router/quoters/mixed-quoter.js +147 -0
  431. package/build/module/routers/alpha-router/quoters/model/index.d.ts +1 -0
  432. package/build/module/routers/alpha-router/quoters/model/index.js +2 -0
  433. package/build/module/routers/alpha-router/quoters/model/results/get-quotes-result.d.ts +6 -0
  434. package/build/module/routers/alpha-router/quoters/model/results/get-quotes-result.js +2 -0
  435. package/build/module/routers/alpha-router/quoters/model/results/get-routes-result.d.ts +6 -0
  436. package/build/module/routers/alpha-router/quoters/model/results/get-routes-result.js +2 -0
  437. package/build/module/routers/alpha-router/quoters/model/results/index.d.ts +2 -0
  438. package/build/module/routers/alpha-router/quoters/model/results/index.js +3 -0
  439. package/build/module/routers/alpha-router/quoters/v2-quoter.d.ts +24 -0
  440. package/build/module/routers/alpha-router/quoters/v2-quoter.js +138 -0
  441. package/build/module/routers/alpha-router/quoters/v3-quoter.d.ts +19 -0
  442. package/build/module/routers/alpha-router/quoters/v3-quoter.js +118 -0
  443. package/build/module/routers/alpha-router/quoters/v4-quoter.d.ts +18 -0
  444. package/build/module/routers/alpha-router/quoters/v4-quoter.js +114 -0
  445. package/build/module/routers/index.d.ts +4 -0
  446. package/build/module/routers/index.js +5 -0
  447. package/build/module/routers/legacy-router/bases.d.ts +201 -0
  448. package/build/module/routers/legacy-router/bases.js +127 -0
  449. package/build/module/routers/legacy-router/index.d.ts +1 -0
  450. package/build/module/routers/legacy-router/index.js +2 -0
  451. package/build/module/routers/legacy-router/legacy-router.d.ts +41 -0
  452. package/build/module/routers/legacy-router/legacy-router.js +292 -0
  453. package/build/module/routers/router.d.ts +195 -0
  454. package/build/module/routers/router.js +79 -0
  455. package/build/module/tsconfig.module.tsbuildinfo +1 -0
  456. package/build/module/types/other/commons.d.ts +16 -0
  457. package/build/module/types/other/commons.js +5 -0
  458. package/build/module/types/other/factories/Erc20__factory.d.ts +45 -0
  459. package/build/module/types/other/factories/Erc20__factory.js +236 -0
  460. package/build/module/types/other/factories/GasDataArbitrum__factory.d.ts +18 -0
  461. package/build/module/types/other/factories/GasDataArbitrum__factory.js +54 -0
  462. package/build/module/types/other/factories/IMixedRouteQuoterV1__factory.d.ts +41 -0
  463. package/build/module/types/other/factories/IMixedRouteQuoterV1__factory.js +152 -0
  464. package/build/module/types/other/factories/ITokenValidator__factory.d.ts +22 -0
  465. package/build/module/types/other/factories/ITokenValidator__factory.js +74 -0
  466. package/build/module/types/other/factories/MixedRouteQuoterV2__factory.d.ts +86 -0
  467. package/build/module/types/other/factories/MixedRouteQuoterV2__factory.js +473 -0
  468. package/build/module/types/other/factories/Permit2__factory.d.ts +87 -0
  469. package/build/module/types/other/factories/Permit2__factory.js +932 -0
  470. package/build/module/types/other/factories/StateView__factory.d.ts +32 -0
  471. package/build/module/types/other/factories/StateView__factory.js +379 -0
  472. package/build/module/types/other/factories/SwapRouter02__factory.d.ts +67 -0
  473. package/build/module/types/other/factories/SwapRouter02__factory.js +1094 -0
  474. package/build/module/types/other/factories/TokenFeeDetector__factory.d.ts +47 -0
  475. package/build/module/types/other/factories/TokenFeeDetector__factory.js +239 -0
  476. package/build/module/types/other/factories/V4Quoter__factory.d.ts +37 -0
  477. package/build/module/types/other/factories/V4Quoter__factory.js +308 -0
  478. package/build/module/types/v2/commons.d.ts +16 -0
  479. package/build/module/types/v2/commons.js +5 -0
  480. package/build/module/types/v2/factories/IUniswapV2Pair__factory.d.ts +35 -0
  481. package/build/module/types/v2/factories/IUniswapV2Pair__factory.js +667 -0
  482. package/build/module/types/v3/commons.d.ts +16 -0
  483. package/build/module/types/v3/commons.js +5 -0
  484. package/build/module/types/v3/factories/IERC20Metadata__factory.d.ts +35 -0
  485. package/build/module/types/v3/factories/IERC20Metadata__factory.js +238 -0
  486. package/build/module/types/v3/factories/IQuoterV2__factory.d.ts +41 -0
  487. package/build/module/types/v3/factories/IQuoterV2__factory.js +216 -0
  488. package/build/module/types/v3/factories/IUniswapV3PoolState__factory.d.ts +22 -0
  489. package/build/module/types/v3/factories/IUniswapV3PoolState__factory.js +262 -0
  490. package/build/module/types/v3/factories/UniswapInterfaceMulticall__factory.d.ts +61 -0
  491. package/build/module/types/v3/factories/UniswapInterfaceMulticall__factory.js +123 -0
  492. package/build/module/util/addresses.d.ts +32 -0
  493. package/build/module/util/addresses.js +223 -0
  494. package/build/module/util/amounts.d.ts +10 -0
  495. package/build/module/util/amounts.js +82 -0
  496. package/build/module/util/callData.d.ts +1 -0
  497. package/build/module/util/callData.js +3 -0
  498. package/build/module/util/chains.d.ts +69 -0
  499. package/build/module/util/chains.js +686 -0
  500. package/build/module/util/defaultBlocksToLive.d.ts +4 -0
  501. package/build/module/util/defaultBlocksToLive.js +50 -0
  502. package/build/module/util/gas-factory-helpers.d.ts +34 -0
  503. package/build/module/util/gas-factory-helpers.js +421 -0
  504. package/build/module/util/hooksOptions.d.ts +5 -0
  505. package/build/module/util/hooksOptions.js +7 -0
  506. package/build/module/util/index.d.ts +10 -0
  507. package/build/module/util/index.js +11 -0
  508. package/build/module/util/intent.d.ts +6 -0
  509. package/build/module/util/intent.js +10 -0
  510. package/build/module/util/l2FeeChains.d.ts +2 -0
  511. package/build/module/util/l2FeeChains.js +15 -0
  512. package/build/module/util/log.d.ts +3 -0
  513. package/build/module/util/log.js +93 -0
  514. package/build/module/util/methodParameters.d.ts +5 -0
  515. package/build/module/util/methodParameters.js +145 -0
  516. package/build/module/util/metric.d.ts +48 -0
  517. package/build/module/util/metric.js +53 -0
  518. package/build/module/util/mixedRouteFilterOutV4Pools.d.ts +3 -0
  519. package/build/module/util/mixedRouteFilterOutV4Pools.js +12 -0
  520. package/build/module/util/onchainQuoteProviderConfigs.d.ts +42 -0
  521. package/build/module/util/onchainQuoteProviderConfigs.js +74 -0
  522. package/build/module/util/pool.d.ts +5 -0
  523. package/build/module/util/pool.js +39 -0
  524. package/build/module/util/protocols.d.ts +2 -0
  525. package/build/module/util/protocols.js +16 -0
  526. package/build/module/util/routes.d.ts +11 -0
  527. package/build/module/util/routes.js +136 -0
  528. package/build/module/util/serializeRouteIds.d.ts +2 -0
  529. package/build/module/util/serializeRouteIds.js +7 -0
  530. package/build/module/util/tenderlySimulationErrorBreakDown.d.ts +3 -0
  531. package/build/module/util/tenderlySimulationErrorBreakDown.js +29 -0
  532. package/build/module/util/unsupported-tokens.d.ts +37 -0
  533. package/build/module/util/unsupported-tokens.js +1116 -0
  534. package/package.json +131 -0
@@ -0,0 +1,1515 @@
1
+ import { ADDRESS_ZERO, Protocol } from '@juiceswapxyz/router-sdk';
2
+ import { ChainId, TradeType } from '@juiceswapxyz/sdk-core';
3
+ import _ from 'lodash';
4
+ import { isNativeCurrency } from '@juiceswapxyz/universal-router-sdk';
5
+ import { DYNAMIC_FEE_FLAG } from '@juiceswapxyz/v4-sdk';
6
+ import { DAI_OPTIMISM_SEPOLIA, isPoolFeeDynamic, USDC_ARBITRUM_SEPOLIA, USDC_OPTIMISM_SEPOLIA, USDT_OPTIMISM_SEPOLIA, WBTC_OPTIMISM_SEPOLIA, } from '../../../providers';
7
+ import { CELO, CELO_ALFAJORES, CEUR_CELO, CEUR_CELO_ALFAJORES, CUSD_CELO, CUSD_CELO_ALFAJORES, DAI_ARBITRUM, DAI_AVAX, DAI_BNB, DAI_MAINNET, DAI_MOONBEAM, DAI_OPTIMISM, DAI_OPTIMISM_GOERLI, DAI_POLYGON_MUMBAI, DAI_SEPOLIA, DAI_UNICHAIN, FEI_MAINNET, USDB_BLAST, USDC_ARBITRUM, USDC_ARBITRUM_GOERLI, USDC_AVAX, USDC_BASE, USDC_BASE_SEPOLIA, USDC_BNB, USDC_ETHEREUM_GNOSIS, USDC_MAINNET, USDC_MOONBEAM, USDC_OPTIMISM, USDC_OPTIMISM_GOERLI, USDC_POLYGON, USDC_SEPOLIA, USDC_SONEIUM, USDC_UNICHAIN, USDT_ARBITRUM, USDT_BNB, USDT_MAINNET, USDT_MONAD_TESTNET, USDT_OPTIMISM, USDT_OPTIMISM_GOERLI, WBTC_ARBITRUM, WBTC_GNOSIS, WBTC_MAINNET, WBTC_MOONBEAM, WBTC_OPTIMISM, WBTC_OPTIMISM_GOERLI, WGLMR_MOONBEAM, WMATIC_POLYGON, WMATIC_POLYGON_MUMBAI, WSTETH_MAINNET, WXDAI_GNOSIS, } from '../../../providers/token-provider';
8
+ import { getAddress, getAddressLowerCase, getApplicableV3FeeAmounts, getApplicableV4FeesTickspacingsHooks, HooksOptions, nativeOnChain, unparseFeeAmount, WRAPPED_NATIVE_CURRENCY, } from '../../../util';
9
+ import { parseFeeAmount } from '../../../util/amounts';
10
+ import { log } from '../../../util/log';
11
+ import { metric, MetricLoggerUnit } from '../../../util/metric';
12
+ const baseTokensByChain = {
13
+ [ChainId.MAINNET]: [
14
+ USDC_MAINNET,
15
+ USDT_MAINNET,
16
+ WBTC_MAINNET,
17
+ DAI_MAINNET,
18
+ WRAPPED_NATIVE_CURRENCY[1],
19
+ FEI_MAINNET,
20
+ WSTETH_MAINNET,
21
+ ],
22
+ [ChainId.OPTIMISM]: [
23
+ DAI_OPTIMISM,
24
+ USDC_OPTIMISM,
25
+ USDT_OPTIMISM,
26
+ WBTC_OPTIMISM,
27
+ ],
28
+ [ChainId.SEPOLIA]: [DAI_SEPOLIA, USDC_SEPOLIA],
29
+ [ChainId.OPTIMISM_GOERLI]: [
30
+ DAI_OPTIMISM_GOERLI,
31
+ USDC_OPTIMISM_GOERLI,
32
+ USDT_OPTIMISM_GOERLI,
33
+ WBTC_OPTIMISM_GOERLI,
34
+ ],
35
+ [ChainId.OPTIMISM_SEPOLIA]: [
36
+ DAI_OPTIMISM_SEPOLIA,
37
+ USDC_OPTIMISM_SEPOLIA,
38
+ USDT_OPTIMISM_SEPOLIA,
39
+ WBTC_OPTIMISM_SEPOLIA,
40
+ ],
41
+ [ChainId.ARBITRUM_ONE]: [
42
+ DAI_ARBITRUM,
43
+ USDC_ARBITRUM,
44
+ WBTC_ARBITRUM,
45
+ USDT_ARBITRUM,
46
+ ],
47
+ [ChainId.ARBITRUM_GOERLI]: [USDC_ARBITRUM_GOERLI],
48
+ [ChainId.ARBITRUM_SEPOLIA]: [USDC_ARBITRUM_SEPOLIA],
49
+ [ChainId.POLYGON]: [USDC_POLYGON, WMATIC_POLYGON],
50
+ [ChainId.POLYGON_MUMBAI]: [DAI_POLYGON_MUMBAI, WMATIC_POLYGON_MUMBAI],
51
+ [ChainId.CELO]: [CUSD_CELO, CEUR_CELO, CELO],
52
+ [ChainId.CELO_ALFAJORES]: [
53
+ CUSD_CELO_ALFAJORES,
54
+ CEUR_CELO_ALFAJORES,
55
+ CELO_ALFAJORES,
56
+ ],
57
+ [ChainId.GNOSIS]: [WBTC_GNOSIS, WXDAI_GNOSIS, USDC_ETHEREUM_GNOSIS],
58
+ [ChainId.MOONBEAM]: [
59
+ DAI_MOONBEAM,
60
+ USDC_MOONBEAM,
61
+ WBTC_MOONBEAM,
62
+ WGLMR_MOONBEAM,
63
+ ],
64
+ [ChainId.BNB]: [DAI_BNB, USDC_BNB, USDT_BNB],
65
+ [ChainId.AVALANCHE]: [DAI_AVAX, USDC_AVAX],
66
+ [ChainId.BASE]: [USDC_BASE],
67
+ [ChainId.BLAST]: [WRAPPED_NATIVE_CURRENCY[ChainId.BLAST], USDB_BLAST],
68
+ [ChainId.ZORA]: [WRAPPED_NATIVE_CURRENCY[ChainId.ZORA]],
69
+ [ChainId.ZKSYNC]: [WRAPPED_NATIVE_CURRENCY[ChainId.ZKSYNC]],
70
+ [ChainId.WORLDCHAIN]: [WRAPPED_NATIVE_CURRENCY[ChainId.WORLDCHAIN]],
71
+ [ChainId.UNICHAIN_SEPOLIA]: [
72
+ WRAPPED_NATIVE_CURRENCY[ChainId.UNICHAIN_SEPOLIA],
73
+ ],
74
+ [ChainId.MONAD_TESTNET]: [
75
+ WRAPPED_NATIVE_CURRENCY[ChainId.MONAD_TESTNET],
76
+ USDT_MONAD_TESTNET,
77
+ ],
78
+ [ChainId.BASE_SEPOLIA]: [
79
+ WRAPPED_NATIVE_CURRENCY[ChainId.BASE_SEPOLIA],
80
+ USDC_BASE_SEPOLIA,
81
+ ],
82
+ [ChainId.UNICHAIN]: [
83
+ WRAPPED_NATIVE_CURRENCY[ChainId.UNICHAIN],
84
+ DAI_UNICHAIN,
85
+ USDC_UNICHAIN,
86
+ ],
87
+ [ChainId.SONEIUM]: [USDC_SONEIUM, WRAPPED_NATIVE_CURRENCY[ChainId.SONEIUM]],
88
+ };
89
+ const excludedV3PoolIds = new Set([
90
+ // https://linear.app/uniswap/issue/CX-1005
91
+ '0x0f681f10ab1aa1cde04232a199fe3c6f2652a80c'.toLowerCase(),
92
+ ]);
93
+ class SubcategorySelectionPools {
94
+ constructor(pools, poolsNeeded) {
95
+ this.pools = pools;
96
+ this.poolsNeeded = poolsNeeded;
97
+ }
98
+ hasEnoughPools() {
99
+ return this.pools.length >= this.poolsNeeded;
100
+ }
101
+ }
102
+ /**
103
+ * Function that finds any missing pools that were not selected by the heuristic but that would
104
+ * create a route with the topPool by TVL with either tokenIn or tokenOut across protocols.
105
+ *
106
+ * e.g. In V2CandidatePools we found that wstETH/DOG is the most liquid pool,
107
+ * then in V3CandidatePools ETH/wstETH is *not* the most liquid pool, so it is not selected
108
+ * This process will look for that pool in order to complete the route.
109
+ *
110
+ */
111
+ export async function getMixedCrossLiquidityCandidatePools({ tokenIn, tokenOut, blockNumber, v2SubgraphProvider, v3SubgraphProvider, v2Candidates, v3Candidates, v4Candidates, mixedCrossLiquidityV3AgainstV4Supported, chainId, }) {
112
+ var _a, _b, _c, _d, _e, _f, _g, _h;
113
+ const v2Pools = (await v2SubgraphProvider.getPools(tokenIn, tokenOut, {
114
+ blockNumber,
115
+ })).sort((a, b) => b.reserve - a.reserve);
116
+ const v3Pools = (await v3SubgraphProvider.getPools(tokenIn, tokenOut, {
117
+ blockNumber,
118
+ })).sort((a, b) => b.tvlUSD - a.tvlUSD);
119
+ const tokenInAddress = tokenIn.address.toLowerCase();
120
+ const tokenOutAddress = tokenOut.address.toLowerCase();
121
+ const v2AgainstV3SelectedPools = findCrossProtocolMissingPools(tokenInAddress, tokenOutAddress, v2Pools, v2Candidates, v3Candidates);
122
+ const v3AgainstV2SelectedPools = findCrossProtocolMissingPools(tokenInAddress, tokenOutAddress, v3Pools, v3Candidates, v2Candidates);
123
+ const v3AgainstV4SelectedPools = chainId && (mixedCrossLiquidityV3AgainstV4Supported === null || mixedCrossLiquidityV3AgainstV4Supported === void 0 ? void 0 : mixedCrossLiquidityV3AgainstV4Supported.includes(chainId))
124
+ ? findCrossProtocolMissingPools(tokenInAddress, tokenOutAddress, v3Pools, v3Candidates, v4Candidates)
125
+ : { forTokenIn: undefined, forTokenOut: undefined };
126
+ // this is for deduplicate v3 pools, in case both v4 and v2 select the same v3 pools for tokenIn/tokenOut
127
+ if (((_a = v3AgainstV4SelectedPools.forTokenIn) === null || _a === void 0 ? void 0 : _a.id) ===
128
+ ((_b = v3AgainstV2SelectedPools.forTokenIn) === null || _b === void 0 ? void 0 : _b.id) ||
129
+ ((_c = v3AgainstV4SelectedPools.forTokenIn) === null || _c === void 0 ? void 0 : _c.id) ===
130
+ ((_d = v3AgainstV2SelectedPools.forTokenOut) === null || _d === void 0 ? void 0 : _d.id)) {
131
+ v3AgainstV4SelectedPools.forTokenIn = undefined;
132
+ }
133
+ if (((_e = v3AgainstV4SelectedPools.forTokenOut) === null || _e === void 0 ? void 0 : _e.id) ===
134
+ ((_f = v3AgainstV2SelectedPools.forTokenIn) === null || _f === void 0 ? void 0 : _f.id) ||
135
+ ((_g = v3AgainstV4SelectedPools.forTokenOut) === null || _g === void 0 ? void 0 : _g.id) ===
136
+ ((_h = v3AgainstV2SelectedPools.forTokenOut) === null || _h === void 0 ? void 0 : _h.id)) {
137
+ v3AgainstV4SelectedPools.forTokenOut = undefined;
138
+ }
139
+ const selectedV2Pools = [
140
+ v2AgainstV3SelectedPools.forTokenIn,
141
+ v2AgainstV3SelectedPools.forTokenOut,
142
+ ].filter((pool) => pool !== undefined);
143
+ const selectedV3Pools = [
144
+ v3AgainstV2SelectedPools.forTokenIn,
145
+ v3AgainstV2SelectedPools.forTokenOut,
146
+ v3AgainstV4SelectedPools.forTokenIn,
147
+ v3AgainstV4SelectedPools.forTokenOut,
148
+ ].filter((pool) => pool !== undefined);
149
+ return {
150
+ v2Pools: selectedV2Pools,
151
+ v3Pools: selectedV3Pools,
152
+ v4Pools: [],
153
+ };
154
+ }
155
+ function findCrossProtocolMissingPools(tokenInAddress, tokenOutAddress, pools, candidatesInProtocolToSearch, candidatesInContextProtocol) {
156
+ var _a;
157
+ const selectedPools = {};
158
+ const previouslySelectedPools = new Set((_a = candidatesInProtocolToSearch === null || candidatesInProtocolToSearch === void 0 ? void 0 : candidatesInProtocolToSearch.subgraphPools.map((pool) => pool.id)) !== null && _a !== void 0 ? _a : []);
159
+ const topPoolByTvlWithTokenOut = candidatesInContextProtocol === null || candidatesInContextProtocol === void 0 ? void 0 : candidatesInContextProtocol.candidatePools.selections.topByTVLUsingTokenOut[0];
160
+ const crossTokenAgainstTokenOut = (topPoolByTvlWithTokenOut === null || topPoolByTvlWithTokenOut === void 0 ? void 0 : topPoolByTvlWithTokenOut.token0.id.toLowerCase()) === tokenOutAddress
161
+ ? topPoolByTvlWithTokenOut === null || topPoolByTvlWithTokenOut === void 0 ? void 0 : topPoolByTvlWithTokenOut.token1.id.toLowerCase()
162
+ : topPoolByTvlWithTokenOut === null || topPoolByTvlWithTokenOut === void 0 ? void 0 : topPoolByTvlWithTokenOut.token0.id.toLowerCase();
163
+ const topPoolByTvlWithTokenIn = candidatesInContextProtocol === null || candidatesInContextProtocol === void 0 ? void 0 : candidatesInContextProtocol.candidatePools.selections.topByTVLUsingTokenIn[0];
164
+ const crossTokenAgainstTokenIn = (topPoolByTvlWithTokenIn === null || topPoolByTvlWithTokenIn === void 0 ? void 0 : topPoolByTvlWithTokenIn.token0.id.toLowerCase()) === tokenInAddress
165
+ ? topPoolByTvlWithTokenIn === null || topPoolByTvlWithTokenIn === void 0 ? void 0 : topPoolByTvlWithTokenIn.token1.id.toLowerCase()
166
+ : topPoolByTvlWithTokenIn === null || topPoolByTvlWithTokenIn === void 0 ? void 0 : topPoolByTvlWithTokenIn.token0.id.toLowerCase();
167
+ for (const pool of pools) {
168
+ // If we already found both pools for tokenIn and tokenOut. break out of this for loop.
169
+ if (selectedPools.forTokenIn !== undefined &&
170
+ selectedPools.forTokenOut !== undefined) {
171
+ break;
172
+ }
173
+ // If the pool has already been selected. continue to the next pool.
174
+ if (previouslySelectedPools.has(pool.id.toLowerCase())) {
175
+ continue;
176
+ }
177
+ const poolToken0Address = pool.token0.id.toLowerCase();
178
+ const poolToken1Address = pool.token1.id.toLowerCase();
179
+ // If we haven't selected the pool for tokenIn, and we found a pool matching the tokenOut, and the intermediateToken, select this pool
180
+ if (selectedPools.forTokenIn === undefined &&
181
+ ((poolToken0Address === tokenOutAddress &&
182
+ poolToken1Address === crossTokenAgainstTokenIn) ||
183
+ (poolToken1Address === tokenOutAddress &&
184
+ poolToken0Address === crossTokenAgainstTokenIn))) {
185
+ selectedPools.forTokenIn = pool;
186
+ }
187
+ // If we haven't selected the pool for tokenOut, and we found a pool matching the tokenIn, and the intermediateToken, select this pool
188
+ if (selectedPools.forTokenOut === undefined &&
189
+ ((poolToken0Address === tokenInAddress &&
190
+ poolToken1Address === crossTokenAgainstTokenOut) ||
191
+ (poolToken1Address === tokenInAddress &&
192
+ poolToken0Address === crossTokenAgainstTokenOut))) {
193
+ selectedPools.forTokenOut = pool;
194
+ }
195
+ }
196
+ return selectedPools;
197
+ }
198
+ // TODO: ROUTE-241 - refactor getV3CandidatePools against getV4CandidatePools
199
+ export async function getV4CandidatePools({ currencyIn, currencyOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, v4PoolParams = getApplicableV4FeesTickspacingsHooks(chainId), }) {
200
+ var _a, _b, _c, _d, _e;
201
+ const { blockNumber, v4PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, topNSecondHopForTokenAddress, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
202
+ const tokenInAddress = getAddressLowerCase(currencyIn);
203
+ const tokenOutAddress = getAddressLowerCase(currencyOut);
204
+ const beforeSubgraphPools = Date.now();
205
+ const allPools = await subgraphProvider.getPools(currencyIn, currencyOut, {
206
+ blockNumber,
207
+ });
208
+ log.info({ samplePools: allPools.slice(0, 3) }, 'Got all pools from V4 subgraph provider');
209
+ // Although this is less of an optimization than the V2 equivalent,
210
+ // save some time copying objects by mutating the underlying pool directly.
211
+ for (const pool of allPools) {
212
+ pool.token0.id = pool.token0.id.toLowerCase();
213
+ pool.token1.id = pool.token1.id.toLowerCase();
214
+ }
215
+ metric.putMetric('V4SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
216
+ const beforePoolsFiltered = Date.now();
217
+ // Only consider pools where neither tokens are in the blocked token list.
218
+ let filteredPools = allPools;
219
+ if (blockedTokenListProvider) {
220
+ filteredPools = [];
221
+ for (const pool of allPools) {
222
+ const token0InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token0.id);
223
+ const token1InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token1.id);
224
+ if (token0InBlocklist || token1InBlocklist) {
225
+ continue;
226
+ }
227
+ filteredPools.push(pool);
228
+ }
229
+ }
230
+ // Sort by tvlUSD in descending order
231
+ const subgraphPoolsSorted = filteredPools.sort((a, b) => b.tvlUSD - a.tvlUSD);
232
+ log.info(`After filtering blocked tokens went from ${allPools.length} to ${subgraphPoolsSorted.length}.`);
233
+ const poolAddressesSoFar = new Set();
234
+ const addToAddressSet = (pools) => {
235
+ _(pools)
236
+ .map((pool) => pool.id)
237
+ .forEach((poolAddress) => poolAddressesSoFar.add(poolAddress));
238
+ };
239
+ const baseTokens = (_a = baseTokensByChain[chainId]) !== null && _a !== void 0 ? _a : [];
240
+ const topByBaseWithTokenIn = _(baseTokens)
241
+ .flatMap((token) => {
242
+ return _(subgraphPoolsSorted)
243
+ .filter((subgraphPool) => {
244
+ const tokenAddress = token.address.toLowerCase();
245
+ return ((subgraphPool.token0.id == tokenAddress &&
246
+ subgraphPool.token1.id == tokenInAddress) ||
247
+ (subgraphPool.token1.id == tokenAddress &&
248
+ subgraphPool.token0.id == tokenInAddress));
249
+ })
250
+ .filter((subgraphPool) => {
251
+ // in case of hooks only, it means we want to filter out hookless pools
252
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
253
+ return subgraphPool.hooks !== ADDRESS_ZERO;
254
+ }
255
+ // in case of no hooks, it means we want to filter out hook pools
256
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
257
+ return subgraphPool.hooks === ADDRESS_ZERO;
258
+ }
259
+ // otherwise it's the default case, so we just return true
260
+ return true;
261
+ })
262
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
263
+ .slice(0, topNWithEachBaseToken)
264
+ .value();
265
+ })
266
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
267
+ .slice(0, topNWithBaseToken)
268
+ .value();
269
+ const topByBaseWithTokenOut = _(baseTokens)
270
+ .flatMap((token) => {
271
+ return _(subgraphPoolsSorted)
272
+ .filter((subgraphPool) => {
273
+ const tokenAddress = token.address.toLowerCase();
274
+ return ((subgraphPool.token0.id == tokenAddress &&
275
+ subgraphPool.token1.id == tokenOutAddress) ||
276
+ (subgraphPool.token1.id == tokenAddress &&
277
+ subgraphPool.token0.id == tokenOutAddress));
278
+ })
279
+ .filter((subgraphPool) => {
280
+ // in case of hooks only, it means we want to filter out hookless pools
281
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
282
+ return subgraphPool.hooks !== ADDRESS_ZERO;
283
+ }
284
+ // in case of no hooks, it means we want to filter out hook pools
285
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
286
+ return subgraphPool.hooks === ADDRESS_ZERO;
287
+ }
288
+ // otherwise it's the default case, so we just return true
289
+ return true;
290
+ })
291
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
292
+ .slice(0, topNWithEachBaseToken)
293
+ .value();
294
+ })
295
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
296
+ .slice(0, topNWithBaseToken)
297
+ .value();
298
+ let top2DirectSwapPool = _(subgraphPoolsSorted)
299
+ .filter((subgraphPool) => {
300
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
301
+ ((subgraphPool.token0.id == tokenInAddress &&
302
+ subgraphPool.token1.id == tokenOutAddress) ||
303
+ (subgraphPool.token1.id == tokenInAddress &&
304
+ subgraphPool.token0.id == tokenOutAddress)));
305
+ })
306
+ .filter((subgraphPool) => {
307
+ // in case of hooks only, it means we want to filter out hookless pools
308
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
309
+ return subgraphPool.hooks !== ADDRESS_ZERO;
310
+ }
311
+ // in case of no hooks, it means we want to filter out hook pools
312
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
313
+ return subgraphPool.hooks === ADDRESS_ZERO;
314
+ }
315
+ // otherwise it's the default case, so we just return true
316
+ return true;
317
+ })
318
+ .slice(0, topNDirectSwaps)
319
+ .value();
320
+ if (top2DirectSwapPool.length == 0 &&
321
+ topNDirectSwaps > 0 &&
322
+ routingConfig.hooksOptions !== HooksOptions.HOOKS_ONLY) {
323
+ // If we requested direct swap pools but did not find any in the subgraph query.
324
+ // Optimistically add them into the query regardless. Invalid pools ones will be dropped anyway
325
+ // when we query the pool on-chain. Ensures that new pools for new pairs can be swapped on immediately.
326
+ // Also we need to avoid adding hookless pools into the query, when upstream requested hooksOnly
327
+ top2DirectSwapPool = _.map(v4PoolParams, (poolParams) => {
328
+ const [fee, tickSpacing, hooks] = poolParams;
329
+ const { currency0, currency1, poolId } = poolProvider.getPoolId(currencyIn, currencyOut, fee, tickSpacing, hooks);
330
+ return {
331
+ id: poolId,
332
+ feeTier: fee.toString(),
333
+ tickSpacing: tickSpacing.toString(),
334
+ hooks: hooks,
335
+ liquidity: '10000',
336
+ token0: {
337
+ symbol: currency0.symbol,
338
+ id: getAddress(currency0),
339
+ name: currency0.name,
340
+ decimals: currency0.decimals.toString(),
341
+ },
342
+ token1: {
343
+ symbol: currency1.symbol,
344
+ id: getAddress(currency1),
345
+ name: currency1.name,
346
+ decimals: currency1.decimals.toString(),
347
+ },
348
+ tvlETH: 10000,
349
+ tvlUSD: 10000,
350
+ };
351
+ });
352
+ }
353
+ addToAddressSet(top2DirectSwapPool);
354
+ const wrappedNativeAddress = (_b = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _b === void 0 ? void 0 : _b.address.toLowerCase();
355
+ // Main reason we need this is for gas estimates, only needed if token out is not native.
356
+ // We don't check the seen address set because if we've already added pools for getting native quotes
357
+ // theres no need to add more.
358
+ let top2EthQuoteTokenPool = [];
359
+ if ((((_c = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _c === void 0 ? void 0 : _c.symbol) ==
360
+ ((_d = WRAPPED_NATIVE_CURRENCY[ChainId.MAINNET]) === null || _d === void 0 ? void 0 : _d.symbol) &&
361
+ currencyOut.symbol != 'WETH' &&
362
+ currencyOut.symbol != 'WETH9' &&
363
+ currencyOut.symbol != 'ETH') ||
364
+ (((_e = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _e === void 0 ? void 0 : _e.symbol) == WMATIC_POLYGON.symbol &&
365
+ currencyOut.symbol != 'MATIC' &&
366
+ currencyOut.symbol != 'WMATIC')) {
367
+ top2EthQuoteTokenPool = _(subgraphPoolsSorted)
368
+ .filter((subgraphPool) => {
369
+ if (routeType == TradeType.EXACT_INPUT) {
370
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
371
+ subgraphPool.token1.id == tokenOutAddress) ||
372
+ (subgraphPool.token1.id == wrappedNativeAddress &&
373
+ subgraphPool.token0.id == tokenOutAddress));
374
+ }
375
+ else {
376
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
377
+ subgraphPool.token1.id == tokenInAddress) ||
378
+ (subgraphPool.token1.id == wrappedNativeAddress &&
379
+ subgraphPool.token0.id == tokenInAddress));
380
+ }
381
+ })
382
+ .slice(0, 1)
383
+ .value();
384
+ }
385
+ addToAddressSet(top2EthQuoteTokenPool);
386
+ const topByTVL = _(subgraphPoolsSorted)
387
+ .filter((subgraphPool) => {
388
+ return !poolAddressesSoFar.has(subgraphPool.id);
389
+ })
390
+ .slice(0, topN)
391
+ .value();
392
+ addToAddressSet(topByTVL);
393
+ const topByTVLUsingTokenIn = _(subgraphPoolsSorted)
394
+ .filter((subgraphPool) => {
395
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
396
+ (subgraphPool.token0.id == tokenInAddress ||
397
+ subgraphPool.token1.id == tokenInAddress));
398
+ })
399
+ .filter((subgraphPool) => {
400
+ // in case of hooks only, it means we want to filter out hookless pools
401
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
402
+ return subgraphPool.hooks !== ADDRESS_ZERO;
403
+ }
404
+ // in case of no hooks, it means we want to filter out hook pools
405
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
406
+ return subgraphPool.hooks === ADDRESS_ZERO;
407
+ }
408
+ // otherwise it's the default case, so we just return true
409
+ return true;
410
+ })
411
+ .slice(0, topNTokenInOut)
412
+ .value();
413
+ addToAddressSet(topByTVLUsingTokenIn);
414
+ const topByTVLUsingTokenOut = _(subgraphPoolsSorted)
415
+ .filter((subgraphPool) => {
416
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
417
+ (subgraphPool.token0.id == tokenOutAddress ||
418
+ subgraphPool.token1.id == tokenOutAddress));
419
+ })
420
+ .filter((subgraphPool) => {
421
+ // in case of hooks only, it means we want to filter out hookless pools
422
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
423
+ return subgraphPool.hooks !== ADDRESS_ZERO;
424
+ }
425
+ // in case of no hooks, it means we want to filter out hook pools
426
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
427
+ return subgraphPool.hooks === ADDRESS_ZERO;
428
+ }
429
+ // otherwise it's the default case, so we just return true
430
+ return true;
431
+ })
432
+ .slice(0, topNTokenInOut)
433
+ .value();
434
+ addToAddressSet(topByTVLUsingTokenOut);
435
+ const topByTVLUsingTokenInSecondHops = _(topByTVLUsingTokenIn)
436
+ .map((subgraphPool) => {
437
+ return tokenInAddress == subgraphPool.token0.id
438
+ ? subgraphPool.token1.id
439
+ : subgraphPool.token0.id;
440
+ })
441
+ .flatMap((secondHopId) => {
442
+ var _a;
443
+ return _(subgraphPoolsSorted)
444
+ .filter((subgraphPool) => {
445
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
446
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
447
+ (subgraphPool.token0.id == secondHopId ||
448
+ subgraphPool.token1.id == secondHopId));
449
+ })
450
+ .filter((subgraphPool) => {
451
+ // in case of hooks only, it means we want to filter out hookless pools
452
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
453
+ return subgraphPool.hooks !== ADDRESS_ZERO;
454
+ }
455
+ // in case of no hooks, it means we want to filter out hook pools
456
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
457
+ return subgraphPool.hooks === ADDRESS_ZERO;
458
+ }
459
+ // otherwise it's the default case, so we just return true
460
+ return true;
461
+ })
462
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
463
+ .value();
464
+ })
465
+ .uniqBy((pool) => pool.id)
466
+ .value();
467
+ addToAddressSet(topByTVLUsingTokenInSecondHops);
468
+ const topByTVLUsingTokenOutSecondHops = _(topByTVLUsingTokenOut)
469
+ .map((subgraphPool) => {
470
+ return tokenOutAddress == subgraphPool.token0.id
471
+ ? subgraphPool.token1.id
472
+ : subgraphPool.token0.id;
473
+ })
474
+ .flatMap((secondHopId) => {
475
+ var _a;
476
+ return _(subgraphPoolsSorted)
477
+ .filter((subgraphPool) => {
478
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
479
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
480
+ (subgraphPool.token0.id == secondHopId ||
481
+ subgraphPool.token1.id == secondHopId));
482
+ })
483
+ .filter((subgraphPool) => {
484
+ // in case of hooks only, it means we want to filter out hookless pools
485
+ if (routingConfig.hooksOptions === HooksOptions.HOOKS_ONLY) {
486
+ return subgraphPool.hooks !== ADDRESS_ZERO;
487
+ }
488
+ // in case of no hooks, it means we want to filter out hook pools
489
+ if (routingConfig.hooksOptions === HooksOptions.NO_HOOKS) {
490
+ return subgraphPool.hooks === ADDRESS_ZERO;
491
+ }
492
+ // otherwise it's the default case, so we just return true
493
+ return true;
494
+ })
495
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
496
+ .value();
497
+ })
498
+ .uniqBy((pool) => pool.id)
499
+ .value();
500
+ addToAddressSet(topByTVLUsingTokenOutSecondHops);
501
+ const subgraphPools = _([
502
+ ...topByBaseWithTokenIn,
503
+ ...topByBaseWithTokenOut,
504
+ ...top2DirectSwapPool,
505
+ ...top2EthQuoteTokenPool,
506
+ ...topByTVL,
507
+ ...topByTVLUsingTokenIn,
508
+ ...topByTVLUsingTokenOut,
509
+ ...topByTVLUsingTokenInSecondHops,
510
+ ...topByTVLUsingTokenOutSecondHops,
511
+ ])
512
+ .compact()
513
+ .uniqBy((pool) => pool.id)
514
+ .value();
515
+ const tokenAddresses = _(subgraphPools)
516
+ .flatMap((subgraphPool) => [subgraphPool.token0.id, subgraphPool.token1.id])
517
+ .compact()
518
+ .uniq()
519
+ .value();
520
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V4 pools we are considering`);
521
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
522
+ blockNumber,
523
+ });
524
+ const printV4SubgraphPool = (s) => {
525
+ var _a, _b, _c, _d;
526
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}/${s.feeTier}/${s.tickSpacing}/${s.hooks}`;
527
+ };
528
+ log.info({
529
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV4SubgraphPool),
530
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV4SubgraphPool),
531
+ topByTVL: topByTVL.map(printV4SubgraphPool),
532
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV4SubgraphPool),
533
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV4SubgraphPool),
534
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV4SubgraphPool),
535
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV4SubgraphPool),
536
+ top2DirectSwap: top2DirectSwapPool.map(printV4SubgraphPool),
537
+ top2EthQuotePool: top2EthQuoteTokenPool.map(printV4SubgraphPool),
538
+ }, `V4 Candidate Pools`);
539
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
540
+ // native currency is not erc20 token, therefore there's no way to retrieve native currency metadata as the erc20 token.
541
+ const tokenA = isNativeCurrency(subgraphPool.token0.id)
542
+ ? nativeOnChain(chainId)
543
+ : tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
544
+ const tokenB = isNativeCurrency(subgraphPool.token1.id)
545
+ ? nativeOnChain(chainId)
546
+ : tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
547
+ let fee;
548
+ try {
549
+ fee = Number(subgraphPool.feeTier);
550
+ fee = isPoolFeeDynamic(tokenA, tokenB, subgraphPool)
551
+ ? DYNAMIC_FEE_FLAG
552
+ : fee;
553
+ }
554
+ catch (err) {
555
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier} because fee tier not supported`);
556
+ return undefined;
557
+ }
558
+ if (!tokenA || !tokenB) {
559
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
560
+ return undefined;
561
+ }
562
+ return [
563
+ tokenA,
564
+ tokenB,
565
+ fee,
566
+ Number(subgraphPool.tickSpacing),
567
+ subgraphPool.hooks,
568
+ ];
569
+ });
570
+ const tokenPairs = _.compact(tokenPairsRaw);
571
+ metric.putMetric('V4PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
572
+ const beforePoolsLoad = Date.now();
573
+ const poolAccessor = await poolProvider.getPools(tokenPairs, {
574
+ blockNumber,
575
+ });
576
+ metric.putMetric('V4PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
577
+ const poolsBySelection = {
578
+ protocol: Protocol.V4,
579
+ selections: {
580
+ topByBaseWithTokenIn,
581
+ topByBaseWithTokenOut,
582
+ topByDirectSwapPool: top2DirectSwapPool,
583
+ topByEthQuoteTokenPool: top2EthQuoteTokenPool,
584
+ topByTVL,
585
+ topByTVLUsingTokenIn,
586
+ topByTVLUsingTokenOut,
587
+ topByTVLUsingTokenInSecondHops,
588
+ topByTVLUsingTokenOutSecondHops,
589
+ },
590
+ };
591
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
592
+ }
593
+ export async function getV3CandidatePools({ tokenIn, tokenOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, }) {
594
+ var _a, _b, _c, _d, _e;
595
+ const { blockNumber, v3PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, topNSecondHopForTokenAddress, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
596
+ const tokenInAddress = tokenIn.address.toLowerCase();
597
+ const tokenOutAddress = tokenOut.address.toLowerCase();
598
+ const beforeSubgraphPools = Date.now();
599
+ const allPools = await subgraphProvider.getPools(tokenIn, tokenOut, {
600
+ blockNumber,
601
+ });
602
+ log.info({ samplePools: allPools.slice(0, 3) }, 'Got all pools from V3 subgraph provider');
603
+ // Although this is less of an optimization than the V2 equivalent,
604
+ // save some time copying objects by mutating the underlying pool directly.
605
+ for (const pool of allPools) {
606
+ pool.token0.id = pool.token0.id.toLowerCase();
607
+ pool.token1.id = pool.token1.id.toLowerCase();
608
+ }
609
+ metric.putMetric('V3SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
610
+ const beforePoolsFiltered = Date.now();
611
+ // Only consider pools where neither tokens are in the blocked token list.
612
+ let filteredPools = allPools;
613
+ if (blockedTokenListProvider) {
614
+ filteredPools = [];
615
+ for (const pool of allPools) {
616
+ const token0InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token0.id);
617
+ const token1InBlocklist = await blockedTokenListProvider.hasTokenByAddress(pool.token1.id);
618
+ if (token0InBlocklist || token1InBlocklist) {
619
+ continue;
620
+ }
621
+ filteredPools.push(pool);
622
+ }
623
+ }
624
+ // Sort by tvlUSD in descending order
625
+ const subgraphPoolsSorted = filteredPools.sort((a, b) => b.tvlUSD - a.tvlUSD);
626
+ log.info(`After filtering blocked tokens went from ${allPools.length} to ${subgraphPoolsSorted.length}.`);
627
+ const poolAddressesSoFar = new Set();
628
+ const addToAddressSet = (pools) => {
629
+ _(pools)
630
+ .map((pool) => pool.id)
631
+ .forEach((poolAddress) => poolAddressesSoFar.add(poolAddress));
632
+ };
633
+ const baseTokens = (_a = baseTokensByChain[chainId]) !== null && _a !== void 0 ? _a : [];
634
+ const topByBaseWithTokenIn = _(baseTokens)
635
+ .flatMap((token) => {
636
+ return _(subgraphPoolsSorted)
637
+ .filter((subgraphPool) => {
638
+ const tokenAddress = token.address.toLowerCase();
639
+ return ((subgraphPool.token0.id == tokenAddress &&
640
+ subgraphPool.token1.id == tokenInAddress) ||
641
+ (subgraphPool.token1.id == tokenAddress &&
642
+ subgraphPool.token0.id == tokenInAddress));
643
+ })
644
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
645
+ .slice(0, topNWithEachBaseToken)
646
+ .value();
647
+ })
648
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
649
+ .slice(0, topNWithBaseToken)
650
+ .value();
651
+ const topByBaseWithTokenOut = _(baseTokens)
652
+ .flatMap((token) => {
653
+ return _(subgraphPoolsSorted)
654
+ .filter((subgraphPool) => {
655
+ const tokenAddress = token.address.toLowerCase();
656
+ return ((subgraphPool.token0.id == tokenAddress &&
657
+ subgraphPool.token1.id == tokenOutAddress) ||
658
+ (subgraphPool.token1.id == tokenAddress &&
659
+ subgraphPool.token0.id == tokenOutAddress));
660
+ })
661
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
662
+ .slice(0, topNWithEachBaseToken)
663
+ .value();
664
+ })
665
+ .sortBy((tokenListPool) => -tokenListPool.tvlUSD)
666
+ .slice(0, topNWithBaseToken)
667
+ .value();
668
+ let top2DirectSwapPool = _(subgraphPoolsSorted)
669
+ .filter((subgraphPool) => {
670
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
671
+ ((subgraphPool.token0.id == tokenInAddress &&
672
+ subgraphPool.token1.id == tokenOutAddress) ||
673
+ (subgraphPool.token1.id == tokenInAddress &&
674
+ subgraphPool.token0.id == tokenOutAddress)));
675
+ })
676
+ .slice(0, topNDirectSwaps)
677
+ .value();
678
+ if (top2DirectSwapPool.length == 0 && topNDirectSwaps > 0) {
679
+ // We don't want to re-add AMPL token pools for V3 in Mainnet.
680
+ // TODO: ROUTE-347, Remove this check once we have a better way to sync filters from subgraph cronjob <> routing path.
681
+ if (!(chainId == ChainId.MAINNET &&
682
+ (tokenIn.address.toLowerCase() ===
683
+ '0xd46ba6d942050d489dbd938a2c909a5d5039a161' ||
684
+ tokenOut.address.toLowerCase() ===
685
+ '0xd46ba6d942050d489dbd938a2c909a5d5039a161'))) {
686
+ // If we requested direct swap pools but did not find any in the subgraph query.
687
+ // Optimistically add them into the query regardless. Invalid pools ones will be dropped anyway
688
+ // when we query the pool on-chain. Ensures that new pools for new pairs can be swapped on immediately.
689
+ top2DirectSwapPool = _.map(getApplicableV3FeeAmounts(chainId), (feeAmount) => {
690
+ const { token0, token1, poolAddress } = poolProvider.getPoolAddress(tokenIn, tokenOut, feeAmount);
691
+ return {
692
+ id: poolAddress,
693
+ feeTier: unparseFeeAmount(feeAmount),
694
+ liquidity: '10000',
695
+ token0: {
696
+ id: token0.address,
697
+ },
698
+ token1: {
699
+ id: token1.address,
700
+ },
701
+ tvlETH: 10000,
702
+ tvlUSD: 10000,
703
+ };
704
+ });
705
+ top2DirectSwapPool = top2DirectSwapPool.filter((pool) => !excludedV3PoolIds.has(pool.id.toLowerCase()));
706
+ }
707
+ }
708
+ addToAddressSet(top2DirectSwapPool);
709
+ const wrappedNativeAddress = (_b = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _b === void 0 ? void 0 : _b.address.toLowerCase();
710
+ // Main reason we need this is for gas estimates, only needed if token out is not native.
711
+ // We don't check the seen address set because if we've already added pools for getting native quotes
712
+ // theres no need to add more.
713
+ let top2EthQuoteTokenPool = [];
714
+ if ((((_c = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _c === void 0 ? void 0 : _c.symbol) ==
715
+ ((_d = WRAPPED_NATIVE_CURRENCY[ChainId.MAINNET]) === null || _d === void 0 ? void 0 : _d.symbol) &&
716
+ tokenOut.symbol != 'WETH' &&
717
+ tokenOut.symbol != 'WETH9' &&
718
+ tokenOut.symbol != 'ETH') ||
719
+ (((_e = WRAPPED_NATIVE_CURRENCY[chainId]) === null || _e === void 0 ? void 0 : _e.symbol) == WMATIC_POLYGON.symbol &&
720
+ tokenOut.symbol != 'MATIC' &&
721
+ tokenOut.symbol != 'WMATIC')) {
722
+ top2EthQuoteTokenPool = _(subgraphPoolsSorted)
723
+ .filter((subgraphPool) => {
724
+ if (routeType == TradeType.EXACT_INPUT) {
725
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
726
+ subgraphPool.token1.id == tokenOutAddress) ||
727
+ (subgraphPool.token1.id == wrappedNativeAddress &&
728
+ subgraphPool.token0.id == tokenOutAddress));
729
+ }
730
+ else {
731
+ return ((subgraphPool.token0.id == wrappedNativeAddress &&
732
+ subgraphPool.token1.id == tokenInAddress) ||
733
+ (subgraphPool.token1.id == wrappedNativeAddress &&
734
+ subgraphPool.token0.id == tokenInAddress));
735
+ }
736
+ })
737
+ .slice(0, 1)
738
+ .value();
739
+ }
740
+ addToAddressSet(top2EthQuoteTokenPool);
741
+ const topByTVL = _(subgraphPoolsSorted)
742
+ .filter((subgraphPool) => {
743
+ return !poolAddressesSoFar.has(subgraphPool.id);
744
+ })
745
+ .slice(0, topN)
746
+ .value();
747
+ addToAddressSet(topByTVL);
748
+ const topByTVLUsingTokenIn = _(subgraphPoolsSorted)
749
+ .filter((subgraphPool) => {
750
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
751
+ (subgraphPool.token0.id == tokenInAddress ||
752
+ subgraphPool.token1.id == tokenInAddress));
753
+ })
754
+ .slice(0, topNTokenInOut)
755
+ .value();
756
+ addToAddressSet(topByTVLUsingTokenIn);
757
+ const topByTVLUsingTokenOut = _(subgraphPoolsSorted)
758
+ .filter((subgraphPool) => {
759
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
760
+ (subgraphPool.token0.id == tokenOutAddress ||
761
+ subgraphPool.token1.id == tokenOutAddress));
762
+ })
763
+ .slice(0, topNTokenInOut)
764
+ .value();
765
+ addToAddressSet(topByTVLUsingTokenOut);
766
+ const topByTVLUsingTokenInSecondHops = _(topByTVLUsingTokenIn)
767
+ .map((subgraphPool) => {
768
+ return tokenInAddress == subgraphPool.token0.id
769
+ ? subgraphPool.token1.id
770
+ : subgraphPool.token0.id;
771
+ })
772
+ .flatMap((secondHopId) => {
773
+ var _a;
774
+ return _(subgraphPoolsSorted)
775
+ .filter((subgraphPool) => {
776
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
777
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
778
+ (subgraphPool.token0.id == secondHopId ||
779
+ subgraphPool.token1.id == secondHopId));
780
+ })
781
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
782
+ .value();
783
+ })
784
+ .uniqBy((pool) => pool.id)
785
+ .value();
786
+ addToAddressSet(topByTVLUsingTokenInSecondHops);
787
+ const topByTVLUsingTokenOutSecondHops = _(topByTVLUsingTokenOut)
788
+ .map((subgraphPool) => {
789
+ return tokenOutAddress == subgraphPool.token0.id
790
+ ? subgraphPool.token1.id
791
+ : subgraphPool.token0.id;
792
+ })
793
+ .flatMap((secondHopId) => {
794
+ var _a;
795
+ return _(subgraphPoolsSorted)
796
+ .filter((subgraphPool) => {
797
+ return (!poolAddressesSoFar.has(subgraphPool.id) &&
798
+ !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(secondHopId.toLowerCase())) &&
799
+ (subgraphPool.token0.id == secondHopId ||
800
+ subgraphPool.token1.id == secondHopId));
801
+ })
802
+ .slice(0, (_a = topNSecondHopForTokenAddress === null || topNSecondHopForTokenAddress === void 0 ? void 0 : topNSecondHopForTokenAddress.get(secondHopId)) !== null && _a !== void 0 ? _a : topNSecondHop)
803
+ .value();
804
+ })
805
+ .uniqBy((pool) => pool.id)
806
+ .value();
807
+ addToAddressSet(topByTVLUsingTokenOutSecondHops);
808
+ const subgraphPools = _([
809
+ ...topByBaseWithTokenIn,
810
+ ...topByBaseWithTokenOut,
811
+ ...top2DirectSwapPool,
812
+ ...top2EthQuoteTokenPool,
813
+ ...topByTVL,
814
+ ...topByTVLUsingTokenIn,
815
+ ...topByTVLUsingTokenOut,
816
+ ...topByTVLUsingTokenInSecondHops,
817
+ ...topByTVLUsingTokenOutSecondHops,
818
+ ])
819
+ .compact()
820
+ .uniqBy((pool) => pool.id)
821
+ .value();
822
+ const tokenAddresses = _(subgraphPools)
823
+ .flatMap((subgraphPool) => [subgraphPool.token0.id, subgraphPool.token1.id])
824
+ .compact()
825
+ .uniq()
826
+ .value();
827
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V3 pools we are considering`);
828
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
829
+ blockNumber,
830
+ });
831
+ const printV3SubgraphPool = (s) => {
832
+ var _a, _b, _c, _d;
833
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}/${s.feeTier}`;
834
+ };
835
+ log.info({
836
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV3SubgraphPool),
837
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV3SubgraphPool),
838
+ topByTVL: topByTVL.map(printV3SubgraphPool),
839
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV3SubgraphPool),
840
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV3SubgraphPool),
841
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV3SubgraphPool),
842
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV3SubgraphPool),
843
+ top2DirectSwap: top2DirectSwapPool.map(printV3SubgraphPool),
844
+ top2EthQuotePool: top2EthQuoteTokenPool.map(printV3SubgraphPool),
845
+ }, `V3 Candidate Pools`);
846
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
847
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
848
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
849
+ let fee;
850
+ try {
851
+ fee = parseFeeAmount(subgraphPool.feeTier);
852
+ }
853
+ catch (err) {
854
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier} because fee tier not supported`);
855
+ return undefined;
856
+ }
857
+ if (!tokenA || !tokenB) {
858
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
859
+ return undefined;
860
+ }
861
+ return [tokenA, tokenB, fee];
862
+ });
863
+ const tokenPairs = _.compact(tokenPairsRaw);
864
+ metric.putMetric('V3PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
865
+ const beforePoolsLoad = Date.now();
866
+ const poolAccessor = await poolProvider.getPools(tokenPairs, {
867
+ blockNumber,
868
+ });
869
+ metric.putMetric('V3PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
870
+ const poolsBySelection = {
871
+ protocol: Protocol.V3,
872
+ selections: {
873
+ topByBaseWithTokenIn,
874
+ topByBaseWithTokenOut,
875
+ topByDirectSwapPool: top2DirectSwapPool,
876
+ topByEthQuoteTokenPool: top2EthQuoteTokenPool,
877
+ topByTVL,
878
+ topByTVLUsingTokenIn,
879
+ topByTVLUsingTokenOut,
880
+ topByTVLUsingTokenInSecondHops,
881
+ topByTVLUsingTokenOutSecondHops,
882
+ },
883
+ };
884
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
885
+ }
886
+ export async function getV2CandidatePools({ tokenIn, tokenOut, routeType, routingConfig, subgraphProvider, tokenProvider, poolProvider, blockedTokenListProvider, chainId, }) {
887
+ var _a;
888
+ const { blockNumber, v2PoolSelection: { topN, topNDirectSwaps, topNTokenInOut, topNSecondHop, tokensToAvoidOnSecondHops, topNWithEachBaseToken, topNWithBaseToken, }, } = routingConfig;
889
+ const tokenInAddress = tokenIn.address.toLowerCase();
890
+ const tokenOutAddress = tokenOut.address.toLowerCase();
891
+ const beforeSubgraphPools = Date.now();
892
+ const allPoolsRaw = await subgraphProvider.getPools(tokenIn, tokenOut, {
893
+ blockNumber,
894
+ });
895
+ // With tens of thousands of V2 pools, operations that copy pools become costly.
896
+ // Mutate the pool directly rather than creating a new pool / token to optimmize for speed.
897
+ for (const pool of allPoolsRaw) {
898
+ pool.token0.id = pool.token0.id.toLowerCase();
899
+ pool.token1.id = pool.token1.id.toLowerCase();
900
+ }
901
+ metric.putMetric('V2SubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
902
+ const beforePoolsFiltered = Date.now();
903
+ // Sort by pool reserve in descending order.
904
+ const subgraphPoolsSorted = allPoolsRaw.sort((a, b) => b.reserve - a.reserve);
905
+ const poolAddressesSoFar = new Set();
906
+ // Always add the direct swap pool into the mix regardless of if it exists in the subgraph pool list.
907
+ // Ensures that new pools can be swapped on immediately, and that if a pool was filtered out of the
908
+ // subgraph query for some reason (e.g. trackedReserveETH was 0), then we still consider it.
909
+ let topByDirectSwapPool = [];
910
+ if (topNDirectSwaps > 0) {
911
+ const { token0, token1, poolAddress } = poolProvider.getPoolAddress(tokenIn, tokenOut);
912
+ poolAddressesSoFar.add(poolAddress.toLowerCase());
913
+ topByDirectSwapPool = [
914
+ {
915
+ id: poolAddress,
916
+ token0: {
917
+ id: token0.address,
918
+ },
919
+ token1: {
920
+ id: token1.address,
921
+ },
922
+ supply: 10000,
923
+ reserve: 10000,
924
+ reserveUSD: 10000, // Not used. Set to arbitrary number.
925
+ },
926
+ ];
927
+ }
928
+ const wethAddress = WRAPPED_NATIVE_CURRENCY[chainId].address.toLowerCase();
929
+ const topByBaseWithTokenInMap = new Map();
930
+ const topByBaseWithTokenOutMap = new Map();
931
+ const baseTokens = (_a = baseTokensByChain[chainId]) !== null && _a !== void 0 ? _a : [];
932
+ const baseTokensAddresses = new Set();
933
+ baseTokens.forEach((token) => {
934
+ const baseTokenAddr = token.address.toLowerCase();
935
+ baseTokensAddresses.add(baseTokenAddr);
936
+ topByBaseWithTokenInMap.set(baseTokenAddr, new SubcategorySelectionPools([], topNWithEachBaseToken));
937
+ topByBaseWithTokenOutMap.set(baseTokenAddr, new SubcategorySelectionPools([], topNWithEachBaseToken));
938
+ });
939
+ let topByBaseWithTokenInPoolsFound = 0;
940
+ let topByBaseWithTokenOutPoolsFound = 0;
941
+ // Main reason we need this is for gas estimates
942
+ // There can ever only be 1 Token/ETH pool, so we will only look for 1
943
+ let topNEthQuoteToken = 1;
944
+ // but, we only need it if token out is not ETH.
945
+ if (tokenOut.symbol == 'WETH' ||
946
+ tokenOut.symbol == 'WETH9' ||
947
+ tokenOut.symbol == 'ETH') {
948
+ // if it's eth we change the topN to 0, so we can break early from the loop.
949
+ topNEthQuoteToken = 0;
950
+ }
951
+ const topByEthQuoteTokenPool = [];
952
+ const topByTVLUsingTokenIn = [];
953
+ const topByTVLUsingTokenOut = [];
954
+ const topByTVL = [];
955
+ // Used to track how many iterations we do in the first loop
956
+ let loopsInFirstIteration = 0;
957
+ // Filtering step for up to first hop
958
+ // The pools are pre-sorted, so we can just iterate through them and fill our heuristics.
959
+ for (const subgraphPool of subgraphPoolsSorted) {
960
+ loopsInFirstIteration += 1;
961
+ // Check if we have satisfied all the heuristics, if so, we can stop.
962
+ if (topByBaseWithTokenInPoolsFound >= topNWithBaseToken &&
963
+ topByBaseWithTokenOutPoolsFound >= topNWithBaseToken &&
964
+ topByEthQuoteTokenPool.length >= topNEthQuoteToken &&
965
+ topByTVL.length >= topN &&
966
+ topByTVLUsingTokenIn.length >= topNTokenInOut &&
967
+ topByTVLUsingTokenOut.length >= topNTokenInOut) {
968
+ // We have satisfied all the heuristics, so we can stop.
969
+ break;
970
+ }
971
+ if (poolAddressesSoFar.has(subgraphPool.id)) {
972
+ // We've already added this pool, so skip it.
973
+ continue;
974
+ }
975
+ // Only consider pools where neither tokens are in the blocked token list.
976
+ if (blockedTokenListProvider) {
977
+ const [token0InBlocklist, token1InBlocklist] = await Promise.all([
978
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token0.id),
979
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token1.id),
980
+ ]);
981
+ if (token0InBlocklist || token1InBlocklist) {
982
+ continue;
983
+ }
984
+ }
985
+ const tokenInToken0TopByBase = topByBaseWithTokenInMap.get(subgraphPool.token0.id);
986
+ if (topByBaseWithTokenInPoolsFound < topNWithBaseToken &&
987
+ tokenInToken0TopByBase &&
988
+ subgraphPool.token0.id != tokenOutAddress &&
989
+ subgraphPool.token1.id == tokenInAddress) {
990
+ topByBaseWithTokenInPoolsFound += 1;
991
+ poolAddressesSoFar.add(subgraphPool.id);
992
+ if (topByTVLUsingTokenIn.length < topNTokenInOut) {
993
+ topByTVLUsingTokenIn.push(subgraphPool);
994
+ }
995
+ if (routeType === TradeType.EXACT_OUTPUT &&
996
+ subgraphPool.token0.id == wethAddress) {
997
+ topByEthQuoteTokenPool.push(subgraphPool);
998
+ }
999
+ tokenInToken0TopByBase.pools.push(subgraphPool);
1000
+ continue;
1001
+ }
1002
+ const tokenInToken1TopByBase = topByBaseWithTokenInMap.get(subgraphPool.token1.id);
1003
+ if (topByBaseWithTokenInPoolsFound < topNWithBaseToken &&
1004
+ tokenInToken1TopByBase &&
1005
+ subgraphPool.token0.id == tokenInAddress &&
1006
+ subgraphPool.token1.id != tokenOutAddress) {
1007
+ topByBaseWithTokenInPoolsFound += 1;
1008
+ poolAddressesSoFar.add(subgraphPool.id);
1009
+ if (topByTVLUsingTokenIn.length < topNTokenInOut) {
1010
+ topByTVLUsingTokenIn.push(subgraphPool);
1011
+ }
1012
+ if (routeType === TradeType.EXACT_OUTPUT &&
1013
+ subgraphPool.token1.id == wethAddress) {
1014
+ topByEthQuoteTokenPool.push(subgraphPool);
1015
+ }
1016
+ tokenInToken1TopByBase.pools.push(subgraphPool);
1017
+ continue;
1018
+ }
1019
+ const tokenOutToken0TopByBase = topByBaseWithTokenOutMap.get(subgraphPool.token0.id);
1020
+ if (topByBaseWithTokenOutPoolsFound < topNWithBaseToken &&
1021
+ tokenOutToken0TopByBase &&
1022
+ subgraphPool.token0.id != tokenInAddress &&
1023
+ subgraphPool.token1.id == tokenOutAddress) {
1024
+ topByBaseWithTokenOutPoolsFound += 1;
1025
+ poolAddressesSoFar.add(subgraphPool.id);
1026
+ if (topByTVLUsingTokenOut.length < topNTokenInOut) {
1027
+ topByTVLUsingTokenOut.push(subgraphPool);
1028
+ }
1029
+ if (routeType === TradeType.EXACT_INPUT &&
1030
+ subgraphPool.token0.id == wethAddress) {
1031
+ topByEthQuoteTokenPool.push(subgraphPool);
1032
+ }
1033
+ tokenOutToken0TopByBase.pools.push(subgraphPool);
1034
+ continue;
1035
+ }
1036
+ const tokenOutToken1TopByBase = topByBaseWithTokenOutMap.get(subgraphPool.token1.id);
1037
+ if (topByBaseWithTokenOutPoolsFound < topNWithBaseToken &&
1038
+ tokenOutToken1TopByBase &&
1039
+ subgraphPool.token0.id == tokenOutAddress &&
1040
+ subgraphPool.token1.id != tokenInAddress) {
1041
+ topByBaseWithTokenOutPoolsFound += 1;
1042
+ poolAddressesSoFar.add(subgraphPool.id);
1043
+ if (topByTVLUsingTokenOut.length < topNTokenInOut) {
1044
+ topByTVLUsingTokenOut.push(subgraphPool);
1045
+ }
1046
+ if (routeType === TradeType.EXACT_INPUT &&
1047
+ subgraphPool.token1.id == wethAddress) {
1048
+ topByEthQuoteTokenPool.push(subgraphPool);
1049
+ }
1050
+ tokenOutToken1TopByBase.pools.push(subgraphPool);
1051
+ continue;
1052
+ }
1053
+ // Note: we do not need to check other native currencies for the V2 Protocol
1054
+ if (topByEthQuoteTokenPool.length < topNEthQuoteToken &&
1055
+ ((routeType === TradeType.EXACT_INPUT &&
1056
+ ((subgraphPool.token0.id == wethAddress &&
1057
+ subgraphPool.token1.id == tokenOutAddress) ||
1058
+ (subgraphPool.token1.id == wethAddress &&
1059
+ subgraphPool.token0.id == tokenOutAddress))) ||
1060
+ (routeType === TradeType.EXACT_OUTPUT &&
1061
+ ((subgraphPool.token0.id == wethAddress &&
1062
+ subgraphPool.token1.id == tokenInAddress) ||
1063
+ (subgraphPool.token1.id == wethAddress &&
1064
+ subgraphPool.token0.id == tokenInAddress))))) {
1065
+ poolAddressesSoFar.add(subgraphPool.id);
1066
+ topByEthQuoteTokenPool.push(subgraphPool);
1067
+ continue;
1068
+ }
1069
+ if (topByTVL.length < topN) {
1070
+ poolAddressesSoFar.add(subgraphPool.id);
1071
+ topByTVL.push(subgraphPool);
1072
+ continue;
1073
+ }
1074
+ if (topByTVLUsingTokenIn.length < topNTokenInOut &&
1075
+ (subgraphPool.token0.id == tokenInAddress ||
1076
+ subgraphPool.token1.id == tokenInAddress)) {
1077
+ poolAddressesSoFar.add(subgraphPool.id);
1078
+ topByTVLUsingTokenIn.push(subgraphPool);
1079
+ continue;
1080
+ }
1081
+ if (topByTVLUsingTokenOut.length < topNTokenInOut &&
1082
+ (subgraphPool.token0.id == tokenOutAddress ||
1083
+ subgraphPool.token1.id == tokenOutAddress)) {
1084
+ poolAddressesSoFar.add(subgraphPool.id);
1085
+ topByTVLUsingTokenOut.push(subgraphPool);
1086
+ continue;
1087
+ }
1088
+ }
1089
+ metric.putMetric('V2SubgraphLoopsInFirstIteration', loopsInFirstIteration, MetricLoggerUnit.Count);
1090
+ const topByBaseWithTokenIn = [];
1091
+ for (const topByBaseWithTokenInSelection of topByBaseWithTokenInMap.values()) {
1092
+ topByBaseWithTokenIn.push(...topByBaseWithTokenInSelection.pools);
1093
+ }
1094
+ const topByBaseWithTokenOut = [];
1095
+ for (const topByBaseWithTokenOutSelection of topByBaseWithTokenOutMap.values()) {
1096
+ topByBaseWithTokenOut.push(...topByBaseWithTokenOutSelection.pools);
1097
+ }
1098
+ // Filtering step for second hops
1099
+ const topByTVLUsingTokenInSecondHopsMap = new Map();
1100
+ const topByTVLUsingTokenOutSecondHopsMap = new Map();
1101
+ const tokenInSecondHopAddresses = topByTVLUsingTokenIn
1102
+ .filter((pool) => {
1103
+ // filtering second hops
1104
+ if (tokenInAddress === pool.token0.id) {
1105
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token1.id.toLowerCase()));
1106
+ }
1107
+ else {
1108
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token0.id.toLowerCase()));
1109
+ }
1110
+ })
1111
+ .map((pool) => tokenInAddress === pool.token0.id ? pool.token1.id : pool.token0.id);
1112
+ const tokenOutSecondHopAddresses = topByTVLUsingTokenOut
1113
+ .filter((pool) => {
1114
+ // filtering second hops
1115
+ if (tokenOutAddress === pool.token0.id) {
1116
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token1.id.toLowerCase()));
1117
+ }
1118
+ else {
1119
+ return !(tokensToAvoidOnSecondHops === null || tokensToAvoidOnSecondHops === void 0 ? void 0 : tokensToAvoidOnSecondHops.includes(pool.token0.id.toLowerCase()));
1120
+ }
1121
+ })
1122
+ .map((pool) => tokenOutAddress === pool.token0.id ? pool.token1.id : pool.token0.id);
1123
+ for (const secondHopId of tokenInSecondHopAddresses) {
1124
+ topByTVLUsingTokenInSecondHopsMap.set(secondHopId, new SubcategorySelectionPools([], topNSecondHop));
1125
+ }
1126
+ for (const secondHopId of tokenOutSecondHopAddresses) {
1127
+ topByTVLUsingTokenOutSecondHopsMap.set(secondHopId, new SubcategorySelectionPools([], topNSecondHop));
1128
+ }
1129
+ // Used to track how many iterations we do in the second loop
1130
+ let loopsInSecondIteration = 0;
1131
+ if (tokenInSecondHopAddresses.length > 0 ||
1132
+ tokenOutSecondHopAddresses.length > 0) {
1133
+ for (const subgraphPool of subgraphPoolsSorted) {
1134
+ loopsInSecondIteration += 1;
1135
+ let allTokenInSecondHopsHaveTheirTopN = true;
1136
+ for (const secondHopPools of topByTVLUsingTokenInSecondHopsMap.values()) {
1137
+ if (!secondHopPools.hasEnoughPools()) {
1138
+ allTokenInSecondHopsHaveTheirTopN = false;
1139
+ break;
1140
+ }
1141
+ }
1142
+ let allTokenOutSecondHopsHaveTheirTopN = true;
1143
+ for (const secondHopPools of topByTVLUsingTokenOutSecondHopsMap.values()) {
1144
+ if (!secondHopPools.hasEnoughPools()) {
1145
+ allTokenOutSecondHopsHaveTheirTopN = false;
1146
+ break;
1147
+ }
1148
+ }
1149
+ if (allTokenInSecondHopsHaveTheirTopN &&
1150
+ allTokenOutSecondHopsHaveTheirTopN) {
1151
+ // We have satisfied all the heuristics, so we can stop.
1152
+ break;
1153
+ }
1154
+ if (poolAddressesSoFar.has(subgraphPool.id)) {
1155
+ continue;
1156
+ }
1157
+ // Only consider pools where neither tokens are in the blocked token list.
1158
+ if (blockedTokenListProvider) {
1159
+ const [token0InBlocklist, token1InBlocklist] = await Promise.all([
1160
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token0.id),
1161
+ blockedTokenListProvider.hasTokenByAddress(subgraphPool.token1.id),
1162
+ ]);
1163
+ if (token0InBlocklist || token1InBlocklist) {
1164
+ continue;
1165
+ }
1166
+ }
1167
+ const tokenInToken0SecondHop = topByTVLUsingTokenInSecondHopsMap.get(subgraphPool.token0.id);
1168
+ if (tokenInToken0SecondHop && !tokenInToken0SecondHop.hasEnoughPools()) {
1169
+ poolAddressesSoFar.add(subgraphPool.id);
1170
+ tokenInToken0SecondHop.pools.push(subgraphPool);
1171
+ continue;
1172
+ }
1173
+ const tokenInToken1SecondHop = topByTVLUsingTokenInSecondHopsMap.get(subgraphPool.token1.id);
1174
+ if (tokenInToken1SecondHop && !tokenInToken1SecondHop.hasEnoughPools()) {
1175
+ poolAddressesSoFar.add(subgraphPool.id);
1176
+ tokenInToken1SecondHop.pools.push(subgraphPool);
1177
+ continue;
1178
+ }
1179
+ const tokenOutToken0SecondHop = topByTVLUsingTokenOutSecondHopsMap.get(subgraphPool.token0.id);
1180
+ if (tokenOutToken0SecondHop &&
1181
+ !tokenOutToken0SecondHop.hasEnoughPools()) {
1182
+ poolAddressesSoFar.add(subgraphPool.id);
1183
+ tokenOutToken0SecondHop.pools.push(subgraphPool);
1184
+ continue;
1185
+ }
1186
+ const tokenOutToken1SecondHop = topByTVLUsingTokenOutSecondHopsMap.get(subgraphPool.token1.id);
1187
+ if (tokenOutToken1SecondHop &&
1188
+ !tokenOutToken1SecondHop.hasEnoughPools()) {
1189
+ poolAddressesSoFar.add(subgraphPool.id);
1190
+ tokenOutToken1SecondHop.pools.push(subgraphPool);
1191
+ continue;
1192
+ }
1193
+ }
1194
+ }
1195
+ metric.putMetric('V2SubgraphLoopsInSecondIteration', loopsInSecondIteration, MetricLoggerUnit.Count);
1196
+ const topByTVLUsingTokenInSecondHops = [];
1197
+ for (const secondHopPools of topByTVLUsingTokenInSecondHopsMap.values()) {
1198
+ topByTVLUsingTokenInSecondHops.push(...secondHopPools.pools);
1199
+ }
1200
+ const topByTVLUsingTokenOutSecondHops = [];
1201
+ for (const secondHopPools of topByTVLUsingTokenOutSecondHopsMap.values()) {
1202
+ topByTVLUsingTokenOutSecondHops.push(...secondHopPools.pools);
1203
+ }
1204
+ const subgraphPools = _([
1205
+ ...topByBaseWithTokenIn,
1206
+ ...topByBaseWithTokenOut,
1207
+ ...topByDirectSwapPool,
1208
+ ...topByEthQuoteTokenPool,
1209
+ ...topByTVL,
1210
+ ...topByTVLUsingTokenIn,
1211
+ ...topByTVLUsingTokenOut,
1212
+ ...topByTVLUsingTokenInSecondHops,
1213
+ ...topByTVLUsingTokenOutSecondHops,
1214
+ ])
1215
+ .uniqBy((pool) => pool.id)
1216
+ .value();
1217
+ const tokenAddressesSet = new Set();
1218
+ for (const pool of subgraphPools) {
1219
+ tokenAddressesSet.add(pool.token0.id);
1220
+ tokenAddressesSet.add(pool.token1.id);
1221
+ }
1222
+ const tokenAddresses = Array.from(tokenAddressesSet);
1223
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} V2 pools we are considering`);
1224
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, {
1225
+ blockNumber,
1226
+ });
1227
+ const printV2SubgraphPool = (s) => {
1228
+ var _a, _b, _c, _d;
1229
+ return `${(_b = (_a = tokenAccessor.getTokenByAddress(s.token0.id)) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : s.token0.id}/${(_d = (_c = tokenAccessor.getTokenByAddress(s.token1.id)) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : s.token1.id}`;
1230
+ };
1231
+ log.info({
1232
+ topByBaseWithTokenIn: topByBaseWithTokenIn.map(printV2SubgraphPool),
1233
+ topByBaseWithTokenOut: topByBaseWithTokenOut.map(printV2SubgraphPool),
1234
+ topByTVL: topByTVL.map(printV2SubgraphPool),
1235
+ topByTVLUsingTokenIn: topByTVLUsingTokenIn.map(printV2SubgraphPool),
1236
+ topByTVLUsingTokenOut: topByTVLUsingTokenOut.map(printV2SubgraphPool),
1237
+ topByTVLUsingTokenInSecondHops: topByTVLUsingTokenInSecondHops.map(printV2SubgraphPool),
1238
+ topByTVLUsingTokenOutSecondHops: topByTVLUsingTokenOutSecondHops.map(printV2SubgraphPool),
1239
+ top2DirectSwap: topByDirectSwapPool.map(printV2SubgraphPool),
1240
+ top2EthQuotePool: topByEthQuoteTokenPool.map(printV2SubgraphPool),
1241
+ }, `V2 Candidate pools`);
1242
+ const tokenPairsRaw = _.map(subgraphPools, (subgraphPool) => {
1243
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
1244
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
1245
+ if (!tokenA || !tokenB) {
1246
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}`);
1247
+ return undefined;
1248
+ }
1249
+ return [tokenA, tokenB];
1250
+ });
1251
+ const tokenPairs = _.compact(tokenPairsRaw);
1252
+ metric.putMetric('V2PoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
1253
+ const beforePoolsLoad = Date.now();
1254
+ // this should be the only place to enable fee-on-transfer fee fetching,
1255
+ // because this places loads pools (pairs of tokens with fot taxes) from the subgraph
1256
+ const poolAccessor = await poolProvider.getPools(tokenPairs, routingConfig);
1257
+ metric.putMetric('V2PoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
1258
+ const poolsBySelection = {
1259
+ protocol: Protocol.V2,
1260
+ selections: {
1261
+ topByBaseWithTokenIn,
1262
+ topByBaseWithTokenOut,
1263
+ topByDirectSwapPool,
1264
+ topByEthQuoteTokenPool,
1265
+ topByTVL,
1266
+ topByTVLUsingTokenIn,
1267
+ topByTVLUsingTokenOut,
1268
+ topByTVLUsingTokenInSecondHops,
1269
+ topByTVLUsingTokenOutSecondHops,
1270
+ },
1271
+ };
1272
+ return { poolAccessor, candidatePools: poolsBySelection, subgraphPools };
1273
+ }
1274
+ export async function getMixedRouteCandidatePools({ v4CandidatePools, v3CandidatePools, v2CandidatePools, crossLiquidityPools, routingConfig, tokenProvider, v4PoolProvider, v3poolProvider, v2poolProvider, chainId, }) {
1275
+ const beforeSubgraphPools = Date.now();
1276
+ const [v4Results, v3Results, v2Results] = [
1277
+ v4CandidatePools,
1278
+ v3CandidatePools,
1279
+ v2CandidatePools,
1280
+ ];
1281
+ // Create empty defaults for undefined results
1282
+ const { subgraphPools: V4subgraphPools = [], candidatePools: V4candidatePools = {
1283
+ protocol: Protocol.V4,
1284
+ selections: {
1285
+ topByBaseWithTokenIn: [],
1286
+ topByBaseWithTokenOut: [],
1287
+ topByDirectSwapPool: [],
1288
+ topByEthQuoteTokenPool: [],
1289
+ topByTVL: [],
1290
+ topByTVLUsingTokenIn: [],
1291
+ topByTVLUsingTokenOut: [],
1292
+ topByTVLUsingTokenInSecondHops: [],
1293
+ topByTVLUsingTokenOutSecondHops: [],
1294
+ },
1295
+ }, } = v4Results || {};
1296
+ const { subgraphPools: V3subgraphPools = [], candidatePools: V3candidatePools = {
1297
+ protocol: Protocol.V3,
1298
+ selections: {
1299
+ topByBaseWithTokenIn: [],
1300
+ topByBaseWithTokenOut: [],
1301
+ topByDirectSwapPool: [],
1302
+ topByEthQuoteTokenPool: [],
1303
+ topByTVL: [],
1304
+ topByTVLUsingTokenIn: [],
1305
+ topByTVLUsingTokenOut: [],
1306
+ topByTVLUsingTokenInSecondHops: [],
1307
+ topByTVLUsingTokenOutSecondHops: [],
1308
+ },
1309
+ }, } = v3Results || {};
1310
+ const { subgraphPools: V2subgraphPools = [], candidatePools: V2candidatePools = {
1311
+ protocol: Protocol.V2,
1312
+ selections: {
1313
+ topByBaseWithTokenIn: [],
1314
+ topByBaseWithTokenOut: [],
1315
+ topByDirectSwapPool: [],
1316
+ topByEthQuoteTokenPool: [],
1317
+ topByTVL: [],
1318
+ topByTVLUsingTokenIn: [],
1319
+ topByTVLUsingTokenOut: [],
1320
+ topByTVLUsingTokenInSecondHops: [],
1321
+ topByTVLUsingTokenOutSecondHops: [],
1322
+ },
1323
+ }, } = v2Results || {};
1324
+ // Injects the liquidity pools found by the getMixedCrossLiquidityCandidatePools function
1325
+ V2subgraphPools.push(...crossLiquidityPools.v2Pools);
1326
+ V3subgraphPools.push(...crossLiquidityPools.v3Pools);
1327
+ V4subgraphPools.push(...crossLiquidityPools.v4Pools);
1328
+ metric.putMetric('MixedSubgraphPoolsLoad', Date.now() - beforeSubgraphPools, MetricLoggerUnit.Milliseconds);
1329
+ const beforePoolsFiltered = Date.now();
1330
+ /**
1331
+ * Main heuristic for pruning mixedRoutes:
1332
+ * - we pick V2 pools with higher liq than respective V3 pools, or if the v3 pool doesn't exist
1333
+ *
1334
+ * This way we can reduce calls to our provider since it's possible to generate a lot of mixed routes
1335
+ */
1336
+ /// We only really care about pools involving the tokenIn or tokenOut explictly,
1337
+ /// since there's no way a long tail token in V2 would be routed through as an intermediary
1338
+ const V2topByTVLPoolIds = new Set([
1339
+ ...V2candidatePools.selections.topByTVLUsingTokenIn,
1340
+ ...V2candidatePools.selections.topByBaseWithTokenIn,
1341
+ /// tokenOut:
1342
+ ...V2candidatePools.selections.topByTVLUsingTokenOut,
1343
+ ...V2candidatePools.selections.topByBaseWithTokenOut,
1344
+ /// Direct swap:
1345
+ ...V2candidatePools.selections.topByDirectSwapPool,
1346
+ // Cross Liquidity (has to be added to be considered):
1347
+ ...crossLiquidityPools.v2Pools,
1348
+ ].map((poolId) => poolId.id));
1349
+ const V2topByTVLSortedPools = _(V2subgraphPools)
1350
+ .filter((pool) => V2topByTVLPoolIds.has(pool.id))
1351
+ .sortBy((pool) => -pool.reserveUSD)
1352
+ .value();
1353
+ /// we consider all returned V3 pools for this heuristic to "fill in the gaps"
1354
+ const V3sortedPools = _(V3subgraphPools)
1355
+ .sortBy((pool) => -pool.tvlUSD)
1356
+ .value();
1357
+ const V4sortedPools = _(V4subgraphPools)
1358
+ .sortBy((pool) => -pool.tvlUSD)
1359
+ .value();
1360
+ /// Finding pools with greater reserveUSD on v2 than tvlUSD on v3, or if there is no v3 liquidity
1361
+ const buildV2Pools = [];
1362
+ V2topByTVLSortedPools.forEach((V2subgraphPool) => {
1363
+ const V3subgraphPool = V3sortedPools.find((pool) => (pool.token0.id == V2subgraphPool.token0.id &&
1364
+ pool.token1.id == V2subgraphPool.token1.id) ||
1365
+ (pool.token0.id == V2subgraphPool.token1.id &&
1366
+ pool.token1.id == V2subgraphPool.token0.id));
1367
+ if (V3subgraphPool) {
1368
+ if (V2subgraphPool.reserveUSD > V3subgraphPool.tvlUSD) {
1369
+ log.info({
1370
+ token0: V2subgraphPool.token0.id,
1371
+ token1: V2subgraphPool.token1.id,
1372
+ v2reserveUSD: V2subgraphPool.reserveUSD,
1373
+ v3tvlUSD: V3subgraphPool.tvlUSD,
1374
+ }, `MixedRoute heuristic, found a V2 pool with higher liquidity than its V3 counterpart`);
1375
+ buildV2Pools.push(V2subgraphPool);
1376
+ }
1377
+ }
1378
+ else {
1379
+ log.info({
1380
+ token0: V2subgraphPool.token0.id,
1381
+ token1: V2subgraphPool.token1.id,
1382
+ v2reserveUSD: V2subgraphPool.reserveUSD,
1383
+ }, `MixedRoute heuristic, found a V2 pool with no V3 counterpart`);
1384
+ buildV2Pools.push(V2subgraphPool);
1385
+ }
1386
+ const V4subgraphPool = V4sortedPools.find((pool) => (pool.token0.id == V2subgraphPool.token0.id &&
1387
+ pool.token1.id == V2subgraphPool.token1.id) ||
1388
+ (pool.token0.id == V2subgraphPool.token1.id &&
1389
+ pool.token1.id == V2subgraphPool.token0.id));
1390
+ if (V4subgraphPool) {
1391
+ if (V2subgraphPool.reserveUSD > V4subgraphPool.tvlUSD) {
1392
+ log.info({
1393
+ token0: V2subgraphPool.token0.id,
1394
+ token1: V2subgraphPool.token1.id,
1395
+ v2reserveUSD: V2subgraphPool.reserveUSD,
1396
+ v4tvlUSD: V4subgraphPool.tvlUSD,
1397
+ }, `MixedRoute heuristic, found a V2 pool with higher liquidity than its V4 counterpart`);
1398
+ buildV2Pools.push(V2subgraphPool);
1399
+ }
1400
+ }
1401
+ else {
1402
+ log.info({
1403
+ token0: V2subgraphPool.token0.id,
1404
+ token1: V2subgraphPool.token1.id,
1405
+ v2reserveUSD: V2subgraphPool.reserveUSD,
1406
+ }, `MixedRoute heuristic, found a V2 pool with no V3 counterpart`);
1407
+ buildV2Pools.push(V2subgraphPool);
1408
+ }
1409
+ });
1410
+ log.info(buildV2Pools.length, `Number of V2 candidate pools that fit first heuristic`);
1411
+ const subgraphPools = [...buildV2Pools, ...V3sortedPools, ...V4sortedPools];
1412
+ const tokenAddresses = _(subgraphPools)
1413
+ .flatMap((subgraphPool) => [subgraphPool.token0.id, subgraphPool.token1.id])
1414
+ .compact()
1415
+ .uniq()
1416
+ .value();
1417
+ log.info(`Getting the ${tokenAddresses.length} tokens within the ${subgraphPools.length} pools we are considering`);
1418
+ const tokenAccessor = await tokenProvider.getTokens(tokenAddresses, routingConfig);
1419
+ const V4tokenPairsRaw = _.map(V4sortedPools, (subgraphPool) => {
1420
+ // native currency is not erc20 token, therefore there's no way to retrieve native currency metadata as the erc20 token.
1421
+ const tokenA = isNativeCurrency(subgraphPool.token0.id)
1422
+ ? nativeOnChain(chainId)
1423
+ : tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
1424
+ const tokenB = isNativeCurrency(subgraphPool.token1.id)
1425
+ ? nativeOnChain(chainId)
1426
+ : tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
1427
+ let fee;
1428
+ try {
1429
+ fee = Number(subgraphPool.feeTier);
1430
+ }
1431
+ catch (err) {
1432
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier}/${subgraphPool.tickSpacing}/${subgraphPool.hooks} because fee tier not supported`);
1433
+ return undefined;
1434
+ }
1435
+ if (!tokenA || !tokenB) {
1436
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee}/${subgraphPool.tickSpacing}/${subgraphPool.hooks} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
1437
+ return undefined;
1438
+ }
1439
+ return [
1440
+ tokenA,
1441
+ tokenB,
1442
+ fee,
1443
+ Number(subgraphPool.tickSpacing),
1444
+ subgraphPool.hooks,
1445
+ ];
1446
+ });
1447
+ const V4tokenPairs = _.compact(V4tokenPairsRaw);
1448
+ const V3tokenPairsRaw = _.map(V3sortedPools, (subgraphPool) => {
1449
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
1450
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
1451
+ let fee;
1452
+ try {
1453
+ fee = parseFeeAmount(subgraphPool.feeTier);
1454
+ }
1455
+ catch (err) {
1456
+ log.info({ subgraphPool }, `Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${subgraphPool.feeTier} because fee tier not supported`);
1457
+ return undefined;
1458
+ }
1459
+ if (!tokenA || !tokenB) {
1460
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}/${fee} because ${tokenA ? subgraphPool.token1.id : subgraphPool.token0.id} not found by token provider`);
1461
+ return undefined;
1462
+ }
1463
+ return [tokenA, tokenB, fee];
1464
+ });
1465
+ const V3tokenPairs = _.compact(V3tokenPairsRaw);
1466
+ const V2tokenPairsRaw = _.map(buildV2Pools, (subgraphPool) => {
1467
+ const tokenA = tokenAccessor.getTokenByAddress(subgraphPool.token0.id);
1468
+ const tokenB = tokenAccessor.getTokenByAddress(subgraphPool.token1.id);
1469
+ if (!tokenA || !tokenB) {
1470
+ log.info(`Dropping candidate pool for ${subgraphPool.token0.id}/${subgraphPool.token1.id}`);
1471
+ return undefined;
1472
+ }
1473
+ return [tokenA, tokenB];
1474
+ });
1475
+ const V2tokenPairs = _.compact(V2tokenPairsRaw);
1476
+ metric.putMetric('MixedPoolsFilterLoad', Date.now() - beforePoolsFiltered, MetricLoggerUnit.Milliseconds);
1477
+ const beforePoolsLoad = Date.now();
1478
+ const [V2poolAccessor, V3poolAccessor, V4poolAccessor] = await Promise.all([
1479
+ v2poolProvider.getPools(V2tokenPairs, routingConfig),
1480
+ v3poolProvider.getPools(V3tokenPairs, routingConfig),
1481
+ v4PoolProvider.getPools(V4tokenPairs, routingConfig),
1482
+ ]);
1483
+ metric.putMetric('MixedPoolsLoad', Date.now() - beforePoolsLoad, MetricLoggerUnit.Milliseconds);
1484
+ /// @dev a bit tricky here since the original V2CandidateSelections object included pools that we may have dropped
1485
+ /// as part of the heuristic. We need to reconstruct a new object with the v3 pools too.
1486
+ const buildPoolsBySelection = (key) => {
1487
+ return [
1488
+ ...buildV2Pools.filter((pool) => V2candidatePools.selections[key].map((p) => p.id).includes(pool.id)),
1489
+ ...V3candidatePools.selections[key],
1490
+ ...V4candidatePools.selections[key],
1491
+ ];
1492
+ };
1493
+ const poolsBySelection = {
1494
+ protocol: Protocol.MIXED,
1495
+ selections: {
1496
+ topByBaseWithTokenIn: buildPoolsBySelection('topByBaseWithTokenIn'),
1497
+ topByBaseWithTokenOut: buildPoolsBySelection('topByBaseWithTokenOut'),
1498
+ topByDirectSwapPool: buildPoolsBySelection('topByDirectSwapPool'),
1499
+ topByEthQuoteTokenPool: buildPoolsBySelection('topByEthQuoteTokenPool'),
1500
+ topByTVL: buildPoolsBySelection('topByTVL'),
1501
+ topByTVLUsingTokenIn: buildPoolsBySelection('topByTVLUsingTokenIn'),
1502
+ topByTVLUsingTokenOut: buildPoolsBySelection('topByTVLUsingTokenOut'),
1503
+ topByTVLUsingTokenInSecondHops: buildPoolsBySelection('topByTVLUsingTokenInSecondHops'),
1504
+ topByTVLUsingTokenOutSecondHops: buildPoolsBySelection('topByTVLUsingTokenOutSecondHops'),
1505
+ },
1506
+ };
1507
+ return {
1508
+ V2poolAccessor,
1509
+ V3poolAccessor,
1510
+ V4poolAccessor,
1511
+ candidatePools: poolsBySelection,
1512
+ subgraphPools,
1513
+ };
1514
+ }
1515
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LWNhbmRpZGF0ZS1wb29scy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9yb3V0ZXJzL2FscGhhLXJvdXRlci9mdW5jdGlvbnMvZ2V0LWNhbmRpZGF0ZS1wb29scy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxPQUFPLEVBQW1CLFNBQVMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTdFLE9BQU8sQ0FBQyxNQUFNLFFBQVEsQ0FBQztBQUV2QixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN0RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN4RCxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLGdCQUFnQixFQUtoQixxQkFBcUIsRUFDckIscUJBQXFCLEVBQ3JCLHFCQUFxQixFQUlyQixxQkFBcUIsR0FDdEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQ0wsSUFBSSxFQUNKLGNBQWMsRUFDZCxTQUFTLEVBQ1QsbUJBQW1CLEVBQ25CLFNBQVMsRUFDVCxtQkFBbUIsRUFDbkIsWUFBWSxFQUNaLFFBQVEsRUFDUixPQUFPLEVBQ1AsV0FBVyxFQUNYLFlBQVksRUFDWixZQUFZLEVBQ1osbUJBQW1CLEVBQ25CLGtCQUFrQixFQUNsQixXQUFXLEVBQ1gsWUFBWSxFQUNaLFdBQVcsRUFFWCxVQUFVLEVBQ1YsYUFBYSxFQUNiLG9CQUFvQixFQUNwQixTQUFTLEVBQ1QsU0FBUyxFQUNULGlCQUFpQixFQUNqQixRQUFRLEVBQ1Isb0JBQW9CLEVBQ3BCLFlBQVksRUFDWixhQUFhLEVBQ2IsYUFBYSxFQUNiLG9CQUFvQixFQUNwQixZQUFZLEVBQ1osWUFBWSxFQUNaLFlBQVksRUFDWixhQUFhLEVBQ2IsYUFBYSxFQUNiLFFBQVEsRUFDUixZQUFZLEVBQ1osa0JBQWtCLEVBQ2xCLGFBQWEsRUFDYixvQkFBb0IsRUFDcEIsYUFBYSxFQUNiLFdBQVcsRUFDWCxZQUFZLEVBQ1osYUFBYSxFQUNiLGFBQWEsRUFDYixvQkFBb0IsRUFDcEIsY0FBYyxFQUNkLGNBQWMsRUFDZCxxQkFBcUIsRUFDckIsY0FBYyxFQUNkLFlBQVksR0FDYixNQUFNLG1DQUFtQyxDQUFDO0FBYTNDLE9BQU8sRUFDTCxVQUFVLEVBQ1YsbUJBQW1CLEVBQ25CLHlCQUF5QixFQUN6QixvQ0FBb0MsRUFDcEMsWUFBWSxFQUNaLGFBQWEsRUFDYixnQkFBZ0IsRUFDaEIsdUJBQXVCLEdBQ3hCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDeEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBMkZoRSxNQUFNLGlCQUFpQixHQUF1QztJQUM1RCxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUNqQixZQUFZO1FBQ1osWUFBWTtRQUNaLFlBQVk7UUFDWixXQUFXO1FBQ1gsdUJBQXVCLENBQUMsQ0FBQyxDQUFFO1FBQzNCLFdBQVc7UUFDWCxjQUFjO0tBQ2Y7SUFDRCxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRTtRQUNsQixZQUFZO1FBQ1osYUFBYTtRQUNiLGFBQWE7UUFDYixhQUFhO0tBQ2Q7SUFDRCxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxZQUFZLENBQUM7SUFDOUMsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLEVBQUU7UUFDekIsbUJBQW1CO1FBQ25CLG9CQUFvQjtRQUNwQixvQkFBb0I7UUFDcEIsb0JBQW9CO0tBQ3JCO0lBQ0QsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtRQUMxQixvQkFBb0I7UUFDcEIscUJBQXFCO1FBQ3JCLHFCQUFxQjtRQUNyQixxQkFBcUI7S0FDdEI7SUFDRCxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsRUFBRTtRQUN0QixZQUFZO1FBQ1osYUFBYTtRQUNiLGFBQWE7UUFDYixhQUFhO0tBQ2Q7SUFDRCxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLG9CQUFvQixDQUFDO0lBQ2pELENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQztJQUNuRCxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSxjQUFjLENBQUM7SUFDakQsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxrQkFBa0IsRUFBRSxxQkFBcUIsQ0FBQztJQUNyRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDO0lBQzVDLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxFQUFFO1FBQ3hCLG1CQUFtQjtRQUNuQixtQkFBbUI7UUFDbkIsY0FBYztLQUNmO0lBQ0QsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixDQUFDO0lBQ25FLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFO1FBQ2xCLFlBQVk7UUFDWixhQUFhO1FBQ2IsYUFBYTtRQUNiLGNBQWM7S0FDZjtJQUNELENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLENBQUM7SUFDNUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDO0lBQzFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDO0lBQzNCLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsdUJBQXVCLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBRSxFQUFFLFVBQVUsQ0FBQztJQUN0RSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLHVCQUF1QixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUUsQ0FBQztJQUN4RCxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLHVCQUF1QixDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUUsQ0FBQztJQUM1RCxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLHVCQUF1QixDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUUsQ0FBQztJQUNwRSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFO1FBQzFCLHVCQUF1QixDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBRTtLQUNuRDtJQUNELENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxFQUFFO1FBQ3ZCLHVCQUF1QixDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUU7UUFDL0Msa0JBQWtCO0tBQ25CO0lBQ0QsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUU7UUFDdEIsdUJBQXVCLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBRTtRQUM5QyxpQkFBaUI7S0FDbEI7SUFDRCxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRTtRQUNsQix1QkFBdUIsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFFO1FBQzFDLFlBQVk7UUFDWixhQUFhO0tBQ2Q7SUFDRCxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSx1QkFBdUIsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFFLENBQUM7Q0FDN0UsQ0FBQztBQUVGLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDaEMsMkNBQTJDO0lBQzNDLDRDQUE0QyxDQUFDLFdBQVcsRUFBRTtDQUMzRCxDQUFDLENBQUM7QUFFSCxNQUFNLHlCQUF5QjtJQUM3QixZQUNTLEtBQXFCLEVBQ1osV0FBbUI7UUFENUIsVUFBSyxHQUFMLEtBQUssQ0FBZ0I7UUFDWixnQkFBVyxHQUFYLFdBQVcsQ0FBUTtJQUNqQyxDQUFDO0lBRUUsY0FBYztRQUNuQixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDL0MsQ0FBQztDQUNGO0FBUUQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLG9DQUFvQyxDQUFDLEVBQ3pELE9BQU8sRUFDUCxRQUFRLEVBQ1IsV0FBVyxFQUNYLGtCQUFrQixFQUNsQixrQkFBa0IsRUFDbEIsWUFBWSxFQUNaLFlBQVksRUFDWixZQUFZLEVBQ1osdUNBQXVDLEVBQ3ZDLE9BQU8sR0FDaUM7O0lBQ3hDLE1BQU0sT0FBTyxHQUFHLENBQ2QsTUFBTSxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRTtRQUNuRCxXQUFXO0tBQ1osQ0FBQyxDQUNILENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDeEMsTUFBTSxPQUFPLEdBQUcsQ0FDZCxNQUFNLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFO1FBQ25ELFdBQVc7S0FDWixDQUFDLENBQ0gsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUV0QyxNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3JELE1BQU0sZUFBZSxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFdkQsTUFBTSx3QkFBd0IsR0FBRyw2QkFBNkIsQ0FDNUQsY0FBYyxFQUNkLGVBQWUsRUFDZixPQUFPLEVBQ1AsWUFBWSxFQUNaLFlBQVksQ0FDYixDQUFDO0lBRUYsTUFBTSx3QkFBd0IsR0FBRyw2QkFBNkIsQ0FDNUQsY0FBYyxFQUNkLGVBQWUsRUFDZixPQUFPLEVBQ1AsWUFBWSxFQUNaLFlBQVksQ0FDYixDQUFDO0lBRUYsTUFBTSx3QkFBd0IsR0FDNUIsT0FBTyxLQUFJLHVDQUF1QyxhQUF2Qyx1Q0FBdUMsdUJBQXZDLHVDQUF1QyxDQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUNuRSxDQUFDLENBQUMsNkJBQTZCLENBQzdCLGNBQWMsRUFDZCxlQUFlLEVBQ2YsT0FBTyxFQUNQLFlBQVksRUFDWixZQUFZLENBQ2I7UUFDRCxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsQ0FBQztJQUV4RCx5R0FBeUc7SUFDekcsSUFDRSxDQUFBLE1BQUEsd0JBQXdCLENBQUMsVUFBVSwwQ0FBRSxFQUFFO1NBQ3ZDLE1BQUEsd0JBQXdCLENBQUMsVUFBVSwwQ0FBRSxFQUFFLENBQUE7UUFDdkMsQ0FBQSxNQUFBLHdCQUF3QixDQUFDLFVBQVUsMENBQUUsRUFBRTthQUN2QyxNQUFBLHdCQUF3QixDQUFDLFdBQVcsMENBQUUsRUFBRSxDQUFBLEVBQ3hDO1FBQ0Esd0JBQXdCLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztLQUNqRDtJQUNELElBQ0UsQ0FBQSxNQUFBLHdCQUF3QixDQUFDLFdBQVcsMENBQUUsRUFBRTtTQUN4QyxNQUFBLHdCQUF3QixDQUFDLFVBQVUsMENBQUUsRUFBRSxDQUFBO1FBQ3ZDLENBQUEsTUFBQSx3QkFBd0IsQ0FBQyxXQUFXLDBDQUFFLEVBQUU7YUFDeEMsTUFBQSx3QkFBd0IsQ0FBQyxXQUFXLDBDQUFFLEVBQUUsQ0FBQSxFQUN4QztRQUNBLHdCQUF3QixDQUFDLFdBQVcsR0FBRyxTQUFTLENBQUM7S0FDbEQ7SUFFRCxNQUFNLGVBQWUsR0FBRztRQUN0Qix3QkFBd0IsQ0FBQyxVQUFVO1FBQ25DLHdCQUF3QixDQUFDLFdBQVc7S0FDckMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksS0FBSyxTQUFTLENBQXFCLENBQUM7SUFDM0QsTUFBTSxlQUFlLEdBQUc7UUFDdEIsd0JBQXdCLENBQUMsVUFBVTtRQUNuQyx3QkFBd0IsQ0FBQyxXQUFXO1FBQ3BDLHdCQUF3QixDQUFDLFVBQVU7UUFDbkMsd0JBQXdCLENBQUMsV0FBVztLQUNyQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBcUIsQ0FBQztJQUUzRCxPQUFPO1FBQ0wsT0FBTyxFQUFFLGVBQWU7UUFDeEIsT0FBTyxFQUFFLGVBQWU7UUFDeEIsT0FBTyxFQUFFLEVBQUU7S0FDWixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsNkJBQTZCLENBV3BDLGNBQXNCLEVBQ3RCLGVBQXVCLEVBQ3ZCLEtBQXNCLEVBQ3RCLDRCQUF3RSxFQUN4RSwyQkFBeUU7O0lBS3pFLE1BQU0sYUFBYSxHQUdmLEVBQUUsQ0FBQztJQUNQLE1BQU0sdUJBQXVCLEdBQUcsSUFBSSxHQUFHLENBQ3JDLE1BQUEsNEJBQTRCLGFBQTVCLDRCQUE0Qix1QkFBNUIsNEJBQTRCLENBQUUsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxtQ0FBSSxFQUFFLENBQ3pFLENBQUM7SUFFRixNQUFNLHdCQUF3QixHQUM1QiwyQkFBMkIsYUFBM0IsMkJBQTJCLHVCQUEzQiwyQkFBMkIsQ0FBRSxjQUFjLENBQUMsVUFBVSxDQUNuRCxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QixNQUFNLHlCQUF5QixHQUM3QixDQUFBLHdCQUF3QixhQUF4Qix3QkFBd0IsdUJBQXhCLHdCQUF3QixDQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLE1BQUssZUFBZTtRQUNuRSxDQUFDLENBQUMsd0JBQXdCLGFBQXhCLHdCQUF3Qix1QkFBeEIsd0JBQXdCLENBQUUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUU7UUFDbkQsQ0FBQyxDQUFDLHdCQUF3QixhQUF4Qix3QkFBd0IsdUJBQXhCLHdCQUF3QixDQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFeEQsTUFBTSx1QkFBdUIsR0FDM0IsMkJBQTJCLGFBQTNCLDJCQUEyQix1QkFBM0IsMkJBQTJCLENBQUUsY0FBYyxDQUFDLFVBQVUsQ0FDbkQsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0IsTUFBTSx3QkFBd0IsR0FDNUIsQ0FBQSx1QkFBdUIsYUFBdkIsdUJBQXVCLHVCQUF2Qix1QkFBdUIsQ0FBRSxNQUFNLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxNQUFLLGNBQWM7UUFDakUsQ0FBQyxDQUFDLHVCQUF1QixhQUF2Qix1QkFBdUIsdUJBQXZCLHVCQUF1QixDQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFO1FBQ2xELENBQUMsQ0FBQyx1QkFBdUIsYUFBdkIsdUJBQXVCLHVCQUF2Qix1QkFBdUIsQ0FBRSxNQUFNLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBRXZELEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFO1FBQ3hCLHVGQUF1RjtRQUN2RixJQUNFLGFBQWEsQ0FBQyxVQUFVLEtBQUssU0FBUztZQUN0QyxhQUFhLENBQUMsV0FBVyxLQUFLLFNBQVMsRUFDdkM7WUFDQSxNQUFNO1NBQ1A7UUFFRCxvRUFBb0U7UUFDcEUsSUFBSSx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxFQUFFO1lBQ3RELFNBQVM7U0FDVjtRQUVELE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDdkQsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUV2RCxzSUFBc0k7UUFDdEksSUFDRSxhQUFhLENBQUMsVUFBVSxLQUFLLFNBQVM7WUFDdEMsQ0FBQyxDQUFDLGlCQUFpQixLQUFLLGVBQWU7Z0JBQ3JDLGlCQUFpQixLQUFLLHdCQUF3QixDQUFDO2dCQUMvQyxDQUFDLGlCQUFpQixLQUFLLGVBQWU7b0JBQ3BDLGlCQUFpQixLQUFLLHdCQUF3QixDQUFDLENBQUMsRUFDcEQ7WUFDQSxhQUFhLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztTQUNqQztRQUVELHNJQUFzSTtRQUN0SSxJQUNFLGFBQWEsQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN2QyxDQUFDLENBQUMsaUJBQWlCLEtBQUssY0FBYztnQkFDcEMsaUJBQWlCLEtBQUsseUJBQXlCLENBQUM7Z0JBQ2hELENBQUMsaUJBQWlCLEtBQUssY0FBYztvQkFDbkMsaUJBQWlCLEtBQUsseUJBQXlCLENBQUMsQ0FBQyxFQUNyRDtZQUNBLGFBQWEsQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1NBQ2xDO0tBQ0Y7SUFFRCxPQUFPLGFBQWEsQ0FBQztBQUN2QixDQUFDO0FBUUQsNkVBQTZFO0FBQzdFLE1BQU0sQ0FBQyxLQUFLLFVBQVUsbUJBQW1CLENBQUMsRUFDeEMsVUFBVSxFQUNWLFdBQVcsRUFDWCxTQUFTLEVBQ1QsYUFBYSxFQUNiLGdCQUFnQixFQUNoQixhQUFhLEVBQ2IsWUFBWSxFQUNaLHdCQUF3QixFQUN4QixPQUFPLEVBQ1AsWUFBWSxHQUFHLG9DQUFvQyxDQUFDLE9BQU8sQ0FBQyxHQUNsQzs7SUFDMUIsTUFBTSxFQUNKLFdBQVcsRUFDWCxlQUFlLEVBQUUsRUFDZixJQUFJLEVBQ0osZUFBZSxFQUNmLGNBQWMsRUFDZCxhQUFhLEVBQ2IsNEJBQTRCLEVBQzVCLHlCQUF5QixFQUN6QixxQkFBcUIsRUFDckIsaUJBQWlCLEdBQ2xCLEdBQ0YsR0FBRyxhQUFhLENBQUM7SUFDbEIsTUFBTSxjQUFjLEdBQUcsbUJBQW1CLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdkQsTUFBTSxlQUFlLEdBQUcsbUJBQW1CLENBQUMsV0FBVyxDQUFDLENBQUM7SUFFekQsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFFdkMsTUFBTSxRQUFRLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLFdBQVcsRUFBRTtRQUN4RSxXQUFXO0tBQ1osQ0FBQyxDQUFDO0lBRUgsR0FBRyxDQUFDLElBQUksQ0FDTixFQUFFLFdBQVcsRUFBRSxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUNyQyx5Q0FBeUMsQ0FDMUMsQ0FBQztJQUVGLG1FQUFtRTtJQUNuRSwyRUFBMkU7SUFDM0UsS0FBSyxNQUFNLElBQUksSUFBSSxRQUFRLEVBQUU7UUFDM0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDOUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7S0FDL0M7SUFFRCxNQUFNLENBQUMsU0FBUyxDQUNkLHFCQUFxQixFQUNyQixJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsbUJBQW1CLEVBQ2hDLGdCQUFnQixDQUFDLFlBQVksQ0FDOUIsQ0FBQztJQUVGLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBRXZDLDBFQUEwRTtJQUMxRSxJQUFJLGFBQWEsR0FBcUIsUUFBUSxDQUFDO0lBQy9DLElBQUksd0JBQXdCLEVBQUU7UUFDNUIsYUFBYSxHQUFHLEVBQUUsQ0FBQztRQUNuQixLQUFLLE1BQU0sSUFBSSxJQUFJLFFBQVEsRUFBRTtZQUMzQixNQUFNLGlCQUFpQixHQUNyQixNQUFNLHdCQUF3QixDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDbkUsTUFBTSxpQkFBaUIsR0FDckIsTUFBTSx3QkFBd0IsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBRW5FLElBQUksaUJBQWlCLElBQUksaUJBQWlCLEVBQUU7Z0JBQzFDLFNBQVM7YUFDVjtZQUVELGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDMUI7S0FDRjtJQUVELHFDQUFxQztJQUNyQyxNQUFNLG1CQUFtQixHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUU5RSxHQUFHLENBQUMsSUFBSSxDQUNOLDRDQUE0QyxRQUFRLENBQUMsTUFBTSxPQUFPLG1CQUFtQixDQUFDLE1BQU0sR0FBRyxDQUNoRyxDQUFDO0lBRUYsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO0lBQzdDLE1BQU0sZUFBZSxHQUFHLENBQUMsS0FBdUIsRUFBRSxFQUFFO1FBQ2xELENBQUMsQ0FBQyxLQUFLLENBQUM7YUFDTCxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7YUFDdEIsT0FBTyxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUNuRSxDQUFDLENBQUM7SUFFRixNQUFNLFVBQVUsR0FBRyxNQUFBLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxtQ0FBSSxFQUFFLENBQUM7SUFFcEQsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDO1NBQ3ZDLE9BQU8sQ0FBQyxDQUFDLEtBQVksRUFBRSxFQUFFO1FBQ3hCLE9BQU8sQ0FBQyxDQUFDLG1CQUFtQixDQUFDO2FBQzFCLE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1lBQ3ZCLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakQsT0FBTyxDQUNMLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksWUFBWTtnQkFDckMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksY0FBYyxDQUFDO2dCQUMzQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVk7b0JBQ3JDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQyxDQUM1QyxDQUFDO1FBQ0osQ0FBQyxDQUFDO2FBQ0QsTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7WUFDdkIsdUVBQXVFO1lBQ3ZFLElBQUksYUFBYSxDQUFDLFlBQVksS0FBSyxZQUFZLENBQUMsVUFBVSxFQUFFO2dCQUMxRCxPQUFPLFlBQVksQ0FBQyxLQUFLLEtBQUssWUFBWSxDQUFDO2FBQzVDO1lBQ0QsaUVBQWlFO1lBQ2pFLElBQUksYUFBYSxDQUFDLFlBQVksS0FBSyxZQUFZLENBQUMsUUFBUSxFQUFFO2dCQUN4RCxPQUFPLFlBQVksQ0FBQyxLQUFLLEtBQUssWUFBWSxDQUFDO2FBQzVDO1lBQ0QsMERBQTBEO1lBQzFELE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQyxDQUFDO2FBQ0QsTUFBTSxDQUFDLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUM7YUFDaEQsS0FBSyxDQUFDLENBQUMsRUFBRSxxQkFBcUIsQ0FBQzthQUMvQixLQUFLLEVBQUUsQ0FBQztJQUNiLENBQUMsQ0FBQztTQUNELE1BQU0sQ0FBQyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDO1NBQ2hELEtBQUssQ0FBQyxDQUFDLEVBQUUsaUJBQWlCLENBQUM7U0FDM0IsS0FBSyxFQUFFLENBQUM7SUFFWCxNQUFNLHFCQUFxQixHQUFHLENBQUMsQ0FBQyxVQUFVLENBQUM7U0FDeEMsT0FBTyxDQUFDLENBQUMsS0FBWSxFQUFFLEVBQUU7UUFDeEIsT0FBTyxDQUFDLENBQUMsbUJBQW1CLENBQUM7YUFDMUIsTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7WUFDdkIsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNqRCxPQUFPLENBQ0wsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxZQUFZO2dCQUNyQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxlQUFlLENBQUM7Z0JBQzVDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksWUFBWTtvQkFDckMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDLENBQzdDLENBQUM7UUFDSixDQUFDLENBQUM7YUFDRCxNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtZQUN2Qix1RUFBdUU7WUFDdkUsSUFBSSxhQUFhLENBQUMsWUFBWSxLQUFLLFlBQVksQ0FBQyxVQUFVLEVBQUU7Z0JBQzFELE9BQU8sWUFBWSxDQUFDLEtBQUssS0FBSyxZQUFZLENBQUM7YUFDNUM7WUFDRCxpRUFBaUU7WUFDakUsSUFBSSxhQUFhLENBQUMsWUFBWSxLQUFLLFlBQVksQ0FBQyxRQUFRLEVBQUU7Z0JBQ3hELE9BQU8sWUFBWSxDQUFDLEtBQUssS0FBSyxZQUFZLENBQUM7YUFDNUM7WUFDRCwwREFBMEQ7WUFDMUQsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDLENBQUM7YUFDRCxNQUFNLENBQUMsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQzthQUNoRCxLQUFLLENBQUMsQ0FBQyxFQUFFLHFCQUFxQixDQUFDO2FBQy9CLEtBQUssRUFBRSxDQUFDO0lBQ2IsQ0FBQyxDQUFDO1NBQ0QsTUFBTSxDQUFDLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUM7U0FDaEQsS0FBSyxDQUFDLENBQUMsRUFBRSxpQkFBaUIsQ0FBQztTQUMzQixLQUFLLEVBQUUsQ0FBQztJQUVYLElBQUksa0JBQWtCLEdBQUcsQ0FBQyxDQUFDLG1CQUFtQixDQUFDO1NBQzVDLE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1FBQ3ZCLE9BQU8sQ0FDTCxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1lBQ3hDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxjQUFjO2dCQUN4QyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxlQUFlLENBQUM7Z0JBQzFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksY0FBYztvQkFDdkMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDLENBQUMsQ0FDaEQsQ0FBQztJQUNKLENBQUMsQ0FBQztTQUNELE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1FBQ3ZCLHVFQUF1RTtRQUN2RSxJQUFJLGFBQWEsQ0FBQyxZQUFZLEtBQUssWUFBWSxDQUFDLFVBQVUsRUFBRTtZQUMxRCxPQUFPLFlBQVksQ0FBQyxLQUFLLEtBQUssWUFBWSxDQUFDO1NBQzVDO1FBQ0QsaUVBQWlFO1FBQ2pFLElBQUksYUFBYSxDQUFDLFlBQVksS0FBSyxZQUFZLENBQUMsUUFBUSxFQUFFO1lBQ3hELE9BQU8sWUFBWSxDQUFDLEtBQUssS0FBSyxZQUFZLENBQUM7U0FDNUM7UUFDRCwwREFBMEQ7UUFDMUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDLENBQUM7U0FDRCxLQUFLLENBQUMsQ0FBQyxFQUFFLGVBQWUsQ0FBQztTQUN6QixLQUFLLEVBQUUsQ0FBQztJQUVYLElBQ0Usa0JBQWtCLENBQUMsTUFBTSxJQUFJLENBQUM7UUFDOUIsZUFBZSxHQUFHLENBQUM7UUFDbkIsYUFBYSxDQUFDLFlBQVksS0FBSyxZQUFZLENBQUMsVUFBVSxFQUN0RDtRQUNBLGdGQUFnRjtRQUNoRiwrRkFBK0Y7UUFDL0YsdUdBQXVHO1FBQ3ZHLGdHQUFnRztRQUNoRyxrQkFBa0IsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUN4QixZQUErQyxFQUMvQyxDQUFDLFVBQVUsRUFBRSxFQUFFO1lBQ2IsTUFBTSxDQUFDLEdBQUcsRUFBRSxXQUFXLEVBQUUsS0FBSyxDQUFDLEdBQUcsVUFBVSxDQUFDO1lBRTdDLE1BQU0sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxHQUFHLFlBQVksQ0FBQyxTQUFTLENBQzdELFVBQVUsRUFDVixXQUFXLEVBQ1gsR0FBRyxFQUNILFdBQVcsRUFDWCxLQUFLLENBQ04sQ0FBQztZQUNGLE9BQU87Z0JBQ0wsRUFBRSxFQUFFLE1BQU07Z0JBQ1YsT0FBTyxFQUFFLEdBQUcsQ0FBQyxRQUFRLEVBQUU7Z0JBQ3ZCLFdBQVcsRUFBRSxXQUFXLENBQUMsUUFBUSxFQUFFO2dCQUNuQyxLQUFLLEVBQUUsS0FBSztnQkFDWixTQUFTLEVBQUUsT0FBTztnQkFDbEIsTUFBTSxFQUFFO29CQUNOLE1BQU0sRUFBRSxTQUFTLENBQUMsTUFBTTtvQkFDeEIsRUFBRSxFQUFFLFVBQVUsQ0FBQyxTQUFTLENBQUM7b0JBQ3pCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtvQkFDcEIsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFO2lCQUN4QztnQkFDRCxNQUFNLEVBQUU7b0JBQ04sTUFBTSxFQUFFLFNBQVMsQ0FBQyxNQUFNO29CQUN4QixFQUFFLEVBQUUsVUFBVSxDQUFDLFNBQVMsQ0FBQztvQkFDekIsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJO29CQUNwQixRQUFRLEVBQUUsU0FBUyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUU7aUJBQ3hDO2dCQUNELE1BQU0sRUFBRSxLQUFLO2dCQUNiLE1BQU0sRUFBRSxLQUFLO2FBQ2QsQ0FBQztRQUNKLENBQUMsQ0FDRixDQUFDO0tBQ0g7SUFFRCxlQUFlLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUVwQyxNQUFNLG9CQUFvQixHQUN4QixNQUFBLHVCQUF1QixDQUFDLE9BQU8sQ0FBQywwQ0FBRSxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFMUQseUZBQXlGO0lBQ3pGLHFHQUFxRztJQUNyRyw4QkFBOEI7SUFDOUIsSUFBSSxxQkFBcUIsR0FBcUIsRUFBRSxDQUFDO0lBQ2pELElBQ0UsQ0FBQyxDQUFBLE1BQUEsdUJBQXVCLENBQUMsT0FBTyxDQUFDLDBDQUFFLE1BQU07U0FDdkMsTUFBQSx1QkFBdUIsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLDBDQUFFLE1BQU0sQ0FBQTtRQUNoRCxXQUFXLENBQUMsTUFBTSxJQUFJLE1BQU07UUFDNUIsV0FBVyxDQUFDLE1BQU0sSUFBSSxPQUFPO1FBQzdCLFdBQVcsQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDO1FBQzlCLENBQUMsQ0FBQSxNQUFBLHVCQUF1QixDQUFDLE9BQU8sQ0FBQywwQ0FBRSxNQUFNLEtBQUksY0FBYyxDQUFDLE1BQU07WUFDaEUsV0FBVyxDQUFDLE1BQU0sSUFBSSxPQUFPO1lBQzdCLFdBQVcsQ0FBQyxNQUFNLElBQUksUUFBUSxDQUFDLEVBQ2pDO1FBQ0EscUJBQXFCLEdBQUcsQ0FBQyxDQUFDLG1CQUFtQixDQUFDO2FBQzNDLE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1lBQ3ZCLElBQUksU0FBUyxJQUFJLFNBQVMsQ0FBQyxXQUFXLEVBQUU7Z0JBQ3RDLE9BQU8sQ0FDTCxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLG9CQUFvQjtvQkFDN0MsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDO29CQUM1QyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLG9CQUFvQjt3QkFDN0MsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDLENBQzdDLENBQUM7YUFDSDtpQkFBTTtnQkFDTCxPQUFPLENBQ0wsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxvQkFBb0I7b0JBQzdDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQztvQkFDM0MsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxvQkFBb0I7d0JBQzdDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQyxDQUM1QyxDQUFDO2FBQ0g7UUFDSCxDQUFDLENBQUM7YUFDRCxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQzthQUNYLEtBQUssRUFBRSxDQUFDO0tBQ1o7SUFFRCxlQUFlLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUV2QyxNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsbUJBQW1CLENBQUM7U0FDcEMsTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7UUFDdkIsT0FBTyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEQsQ0FBQyxDQUFDO1NBQ0QsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUM7U0FDZCxLQUFLLEVBQUUsQ0FBQztJQUVYLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUUxQixNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQztTQUNoRCxNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtRQUN2QixPQUFPLENBQ0wsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUN4QyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWM7Z0JBQ3ZDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQyxDQUM1QyxDQUFDO0lBQ0osQ0FBQyxDQUFDO1NBQ0QsTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7UUFDdkIsdUVBQXVFO1FBQ3ZFLElBQUksYUFBYSxDQUFDLFlBQVksS0FBSyxZQUFZLENBQUMsVUFBVSxFQUFFO1lBQzFELE9BQU8sWUFBWSxDQUFDLEtBQUssS0FBSyxZQUFZLENBQUM7U0FDNUM7UUFDRCxpRUFBaUU7UUFDakUsSUFBSSxhQUFhLENBQUMsWUFBWSxLQUFLLFlBQVksQ0FBQyxRQUFRLEVBQUU7WUFDeEQsT0FBTyxZQUFZLENBQUMsS0FBSyxLQUFLLFlBQVksQ0FBQztTQUM1QztRQUNELDBEQUEwRDtRQUMxRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUMsQ0FBQztTQUNELEtBQUssQ0FBQyxDQUFDLEVBQUUsY0FBYyxDQUFDO1NBQ3hCLEtBQUssRUFBRSxDQUFDO0lBRVgsZUFBZSxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFFdEMsTUFBTSxxQkFBcUIsR0FBRyxDQUFDLENBQUMsbUJBQW1CLENBQUM7U0FDakQsTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7UUFDdkIsT0FBTyxDQUNMLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7WUFDeEMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxlQUFlO2dCQUN4QyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxlQUFlLENBQUMsQ0FDN0MsQ0FBQztJQUNKLENBQUMsQ0FBQztTQUNELE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1FBQ3ZCLHVFQUF1RTtRQUN2RSxJQUFJLGFBQWEsQ0FBQyxZQUFZLEtBQUssWUFBWSxDQUFDLFVBQVUsRUFBRTtZQUMxRCxPQUFPLFlBQVksQ0FBQyxLQUFLLEtBQUssWUFBWSxDQUFDO1NBQzVDO1FBQ0QsaUVBQWlFO1FBQ2pFLElBQUksYUFBYSxDQUFDLFlBQVksS0FBSyxZQUFZLENBQUMsUUFBUSxFQUFFO1lBQ3hELE9BQU8sWUFBWSxDQUFDLEtBQUssS0FBSyxZQUFZLENBQUM7U0FDNUM7UUFDRCwwREFBMEQ7UUFDMUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDLENBQUM7U0FDRCxLQUFLLENBQUMsQ0FBQyxFQUFFLGNBQWMsQ0FBQztTQUN4QixLQUFLLEVBQUUsQ0FBQztJQUVYLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBRXZDLE1BQU0sOEJBQThCLEdBQUcsQ0FBQyxDQUFDLG9CQUFvQixDQUFDO1NBQzNELEdBQUcsQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1FBQ3BCLE9BQU8sY0FBYyxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUM3QyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ3hCLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztJQUM3QixDQUFDLENBQUM7U0FDRCxPQUFPLENBQUMsQ0FBQyxXQUFtQixFQUFFLEVBQUU7O1FBQy9CLE9BQU8sQ0FBQyxDQUFDLG1CQUFtQixDQUFDO2FBQzFCLE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1lBQ3ZCLE9BQU8sQ0FDTCxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO2dCQUN4QyxDQUFDLENBQUEseUJBQXlCLGFBQXpCLHlCQUF5Qix1QkFBekIseUJBQXlCLENBQUUsUUFBUSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFBO2dCQUMvRCxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFdBQVc7b0JBQ3BDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFdBQVcsQ0FBQyxDQUN6QyxDQUFDO1FBQ0osQ0FBQyxDQUFDO2FBQ0QsTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7WUFDdkIsdUVBQXVFO1lBQ3ZFLElBQUksYUFBYSxDQUFDLFlBQVksS0FBSyxZQUFZLENBQUMsVUFBVSxFQUFFO2dCQUMxRCxPQUFPLFlBQVksQ0FBQyxLQUFLLEtBQUssWUFBWSxDQUFDO2FBQzVDO1lBQ0QsaUVBQWlFO1lBQ2pFLElBQUksYUFBYSxDQUFDLFlBQVksS0FBSyxZQUFZLENBQUMsUUFBUSxFQUFFO2dCQUN4RCxPQUFPLFlBQVksQ0FBQyxLQUFLLEtBQUssWUFBWSxDQUFDO2FBQzVDO1lBQ0QsMERBQTBEO1lBQzFELE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQyxDQUFDO2FBQ0QsS0FBSyxDQUNKLENBQUMsRUFDRCxNQUFBLDRCQUE0QixhQUE1Qiw0QkFBNEIsdUJBQTVCLDRCQUE0QixDQUFFLEdBQUcsQ0FBQyxXQUFXLENBQUMsbUNBQUksYUFBYSxDQUNoRTthQUNBLEtBQUssRUFBRSxDQUFDO0lBQ2IsQ0FBQyxDQUFDO1NBQ0QsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1NBQ3pCLEtBQUssRUFBRSxDQUFDO0lBRVgsZUFBZSxDQUFDLDhCQUE4QixDQUFDLENBQUM7SUFFaEQsTUFBTSwrQkFBK0IsR0FBRyxDQUFDLENBQUMscUJBQXFCLENBQUM7U0FDN0QsR0FBRyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7UUFDcEIsT0FBTyxlQUFlLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQzlDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDeEIsQ0FBQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO0lBQzdCLENBQUMsQ0FBQztTQUNELE9BQU8sQ0FBQyxDQUFDLFdBQW1CLEVBQUUsRUFBRTs7UUFDL0IsT0FBTyxDQUFDLENBQUMsbUJBQW1CLENBQUM7YUFDMUIsTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7WUFDdkIsT0FBTyxDQUNMLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7Z0JBQ3hDLENBQUMsQ0FBQSx5QkFBeUIsYUFBekIseUJBQXlCLHVCQUF6Qix5QkFBeUIsQ0FBRSxRQUFRLENBQUMsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUE7Z0JBQy9ELENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksV0FBVztvQkFDcEMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksV0FBVyxDQUFDLENBQ3pDLENBQUM7UUFDSixDQUFDLENBQUM7YUFDRCxNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtZQUN2Qix1RUFBdUU7WUFDdkUsSUFBSSxhQUFhLENBQUMsWUFBWSxLQUFLLFlBQVksQ0FBQyxVQUFVLEVBQUU7Z0JBQzFELE9BQU8sWUFBWSxDQUFDLEtBQUssS0FBSyxZQUFZLENBQUM7YUFDNUM7WUFDRCxpRUFBaUU7WUFDakUsSUFBSSxhQUFhLENBQUMsWUFBWSxLQUFLLFlBQVksQ0FBQyxRQUFRLEVBQUU7Z0JBQ3hELE9BQU8sWUFBWSxDQUFDLEtBQUssS0FBSyxZQUFZLENBQUM7YUFDNUM7WUFDRCwwREFBMEQ7WUFDMUQsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDLENBQUM7YUFDRCxLQUFLLENBQ0osQ0FBQyxFQUNELE1BQUEsNEJBQTRCLGFBQTVCLDRCQUE0Qix1QkFBNUIsNEJBQTRCLENBQUUsR0FBRyxDQUFDLFdBQVcsQ0FBQyxtQ0FBSSxhQUFhLENBQ2hFO2FBQ0EsS0FBSyxFQUFFLENBQUM7SUFDYixDQUFDLENBQUM7U0FDRCxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7U0FDekIsS0FBSyxFQUFFLENBQUM7SUFFWCxlQUFlLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUVqRCxNQUFNLGFBQWEsR0FBRyxDQUFDLENBQUM7UUFDdEIsR0FBRyxvQkFBb0I7UUFDdkIsR0FBRyxxQkFBcUI7UUFDeEIsR0FBRyxrQkFBa0I7UUFDckIsR0FBRyxxQkFBcUI7UUFDeEIsR0FBRyxRQUFRO1FBQ1gsR0FBRyxvQkFBb0I7UUFDdkIsR0FBRyxxQkFBcUI7UUFDeEIsR0FBRyw4QkFBOEI7UUFDakMsR0FBRywrQkFBK0I7S0FDbkMsQ0FBQztTQUNDLE9BQU8sRUFBRTtTQUNULE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztTQUN6QixLQUFLLEVBQUUsQ0FBQztJQUVYLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQyxhQUFhLENBQUM7U0FDcEMsT0FBTyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDM0UsT0FBTyxFQUFFO1NBQ1QsSUFBSSxFQUFFO1NBQ04sS0FBSyxFQUFFLENBQUM7SUFFWCxHQUFHLENBQUMsSUFBSSxDQUNOLGVBQWUsY0FBYyxDQUFDLE1BQU0sc0JBQXNCLGFBQWEsQ0FBQyxNQUFNLDhCQUE4QixDQUM3RyxDQUFDO0lBRUYsTUFBTSxhQUFhLEdBQUcsTUFBTSxhQUFhLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRTtRQUNsRSxXQUFXO0tBQ1osQ0FBQyxDQUFDO0lBRUgsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLENBQWlCLEVBQUUsRUFBRTs7UUFDaEQsT0FBQSxHQUFHLE1BQUEsTUFBQSxhQUFhLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsMENBQUUsTUFBTSxtQ0FBSSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxNQUFBLE1BQUEsYUFBYSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLDBDQUFFLE1BQU0sbUNBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUMzSSxJQUFJLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUE7S0FBQSxDQUFDO0lBRTlDLEdBQUcsQ0FBQyxJQUFJLENBQ047UUFDRSxvQkFBb0IsRUFBRSxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7UUFDbkUscUJBQXFCLEVBQUUscUJBQXFCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO1FBQ3JFLFFBQVEsRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO1FBQzNDLG9CQUFvQixFQUFFLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztRQUNuRSxxQkFBcUIsRUFBRSxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7UUFDckUsOEJBQThCLEVBQzVCLDhCQUE4QixDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztRQUN6RCwrQkFBK0IsRUFDN0IsK0JBQStCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO1FBQzFELGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7UUFDM0QsZ0JBQWdCLEVBQUUscUJBQXFCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO0tBQ2pFLEVBQ0Qsb0JBQW9CLENBQ3JCLENBQUM7SUFFRixNQUFNLGFBQWEsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUd6QixhQUFhLEVBQUUsQ0FBQyxZQUFZLEVBQUUsRUFBRTtRQUNoQyx3SEFBd0g7UUFDeEgsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDckQsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUM7WUFDeEIsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzVELE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ3JELENBQUMsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDO1lBQ3hCLENBQUMsQ0FBQyxhQUFhLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM1RCxJQUFJLEdBQVcsQ0FBQztRQUNoQixJQUFJO1lBQ0YsR0FBRyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbkMsR0FBRyxHQUFHLGdCQUFnQixDQUFDLE1BQU8sRUFBRSxNQUFPLEVBQUUsWUFBWSxDQUFDO2dCQUNwRCxDQUFDLENBQUMsZ0JBQWdCO2dCQUNsQixDQUFDLENBQUMsR0FBRyxDQUFDO1NBQ1Q7UUFBQyxPQUFPLEdBQUcsRUFBRTtZQUNaLEdBQUcsQ0FBQyxJQUFJLENBQ04sRUFBRSxZQUFZLEVBQUUsRUFDaEIsK0JBQStCLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVksQ0FBQyxPQUFPLGlDQUFpQyxDQUN6SSxDQUFDO1lBQ0YsT0FBTyxTQUFTLENBQUM7U0FDbEI7UUFFRCxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ3RCLEdBQUcsQ0FBQyxJQUFJLENBQ04sK0JBQStCLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFDN0UsSUFBSSxHQUFHLFlBQVksTUFBTSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUN6RSw4QkFBOEIsQ0FDL0IsQ0FBQztZQUNGLE9BQU8sU0FBUyxDQUFDO1NBQ2xCO1FBRUQsT0FBTztZQUNMLE1BQU07WUFDTixNQUFNO1lBQ04sR0FBRztZQUNILE1BQU0sQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDO1lBQ2hDLFlBQVksQ0FBQyxLQUFLO1NBQ25CLENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztJQUVILE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7SUFFNUMsTUFBTSxDQUFDLFNBQVMsQ0FDZCxtQkFBbUIsRUFDbkIsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLG1CQUFtQixFQUNoQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7SUFFRixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFFbkMsTUFBTSxZQUFZLEdBQUcsTUFBTSxZQUFZLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRTtRQUMzRCxXQUFXO0tBQ1osQ0FBQyxDQUFDO0lBRUgsTUFBTSxDQUFDLFNBQVMsQ0FDZCxhQUFhLEVBQ2IsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLGVBQWUsRUFDNUIsZ0JBQWdCLENBQUMsWUFBWSxDQUM5QixDQUFDO0lBRUYsTUFBTSxnQkFBZ0IsR0FBc0M7UUFDMUQsUUFBUSxFQUFFLFFBQVEsQ0FBQyxFQUFFO1FBQ3JCLFVBQVUsRUFBRTtZQUNWLG9CQUFvQjtZQUNwQixxQkFBcUI7WUFDckIsbUJBQW1CLEVBQUUsa0JBQWtCO1lBQ3ZDLHNCQUFzQixFQUFFLHFCQUFxQjtZQUM3QyxRQUFRO1lBQ1Isb0JBQW9CO1lBQ3BCLHFCQUFxQjtZQUNyQiw4QkFBOEI7WUFDOUIsK0JBQStCO1NBQ2hDO0tBQ0YsQ0FBQztJQUVGLE9BQU8sRUFBRSxZQUFZLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSxDQUFDO0FBQzNFLENBQUM7QUFRRCxNQUFNLENBQUMsS0FBSyxVQUFVLG1CQUFtQixDQUFDLEVBQ3hDLE9BQU8sRUFDUCxRQUFRLEVBQ1IsU0FBUyxFQUNULGFBQWEsRUFDYixnQkFBZ0IsRUFDaEIsYUFBYSxFQUNiLFlBQVksRUFDWix3QkFBd0IsRUFDeEIsT0FBTyxHQUNtQjs7SUFDMUIsTUFBTSxFQUNKLFdBQVcsRUFDWCxlQUFlLEVBQUUsRUFDZixJQUFJLEVBQ0osZUFBZSxFQUNmLGNBQWMsRUFDZCxhQUFhLEVBQ2IsNEJBQTRCLEVBQzVCLHlCQUF5QixFQUN6QixxQkFBcUIsRUFDckIsaUJBQWlCLEdBQ2xCLEdBQ0YsR0FBRyxhQUFhLENBQUM7SUFDbEIsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyRCxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBRXZELE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBRXZDLE1BQU0sUUFBUSxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUU7UUFDbEUsV0FBVztLQUNaLENBQUMsQ0FBQztJQUVILEdBQUcsQ0FBQyxJQUFJLENBQ04sRUFBRSxXQUFXLEVBQUUsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFDckMseUNBQXlDLENBQzFDLENBQUM7SUFFRixtRUFBbUU7SUFDbkUsMkVBQTJFO0lBQzNFLEtBQUssTUFBTSxJQUFJLElBQUksUUFBUSxFQUFFO1FBQzNCLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzlDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO0tBQy9DO0lBRUQsTUFBTSxDQUFDLFNBQVMsQ0FDZCxxQkFBcUIsRUFDckIsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLG1CQUFtQixFQUNoQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7SUFFRixNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUV2QywwRUFBMEU7SUFDMUUsSUFBSSxhQUFhLEdBQXFCLFFBQVEsQ0FBQztJQUMvQyxJQUFJLHdCQUF3QixFQUFFO1FBQzVCLGFBQWEsR0FBRyxFQUFFLENBQUM7UUFDbkIsS0FBSyxNQUFNLElBQUksSUFBSSxRQUFRLEVBQUU7WUFDM0IsTUFBTSxpQkFBaUIsR0FDckIsTUFBTSx3QkFBd0IsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ25FLE1BQU0saUJBQWlCLEdBQ3JCLE1BQU0sd0JBQXdCLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUVuRSxJQUFJLGlCQUFpQixJQUFJLGlCQUFpQixFQUFFO2dCQUMxQyxTQUFTO2FBQ1Y7WUFFRCxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQzFCO0tBQ0Y7SUFFRCxxQ0FBcUM7SUFDckMsTUFBTSxtQkFBbUIsR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFOUUsR0FBRyxDQUFDLElBQUksQ0FDTiw0Q0FBNEMsUUFBUSxDQUFDLE1BQU0sT0FBTyxtQkFBbUIsQ0FBQyxNQUFNLEdBQUcsQ0FDaEcsQ0FBQztJQUVGLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUM3QyxNQUFNLGVBQWUsR0FBRyxDQUFDLEtBQXVCLEVBQUUsRUFBRTtRQUNsRCxDQUFDLENBQUMsS0FBSyxDQUFDO2FBQ0wsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2FBQ3RCLE9BQU8sQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDbkUsQ0FBQyxDQUFDO0lBRUYsTUFBTSxVQUFVLEdBQUcsTUFBQSxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsbUNBQUksRUFBRSxDQUFDO0lBRXBELE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxDQUFDLFVBQVUsQ0FBQztTQUN2QyxPQUFPLENBQUMsQ0FBQyxLQUFZLEVBQUUsRUFBRTtRQUN4QixPQUFPLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQzthQUMxQixNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtZQUN2QixNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ2pELE9BQU8sQ0FDTCxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVk7Z0JBQ3JDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQztnQkFDM0MsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxZQUFZO29CQUNyQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxjQUFjLENBQUMsQ0FDNUMsQ0FBQztRQUNKLENBQUMsQ0FBQzthQUNELE1BQU0sQ0FBQyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDO2FBQ2hELEtBQUssQ0FBQyxDQUFDLEVBQUUscUJBQXFCLENBQUM7YUFDL0IsS0FBSyxFQUFFLENBQUM7SUFDYixDQUFDLENBQUM7U0FDRCxNQUFNLENBQUMsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQztTQUNoRCxLQUFLLENBQUMsQ0FBQyxFQUFFLGlCQUFpQixDQUFDO1NBQzNCLEtBQUssRUFBRSxDQUFDO0lBRVgsTUFBTSxxQkFBcUIsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDO1NBQ3hDLE9BQU8sQ0FBQyxDQUFDLEtBQVksRUFBRSxFQUFFO1FBQ3hCLE9BQU8sQ0FBQyxDQUFDLG1CQUFtQixDQUFDO2FBQzFCLE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1lBQ3ZCLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakQsT0FBTyxDQUNMLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksWUFBWTtnQkFDckMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDO2dCQUM1QyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVk7b0JBQ3JDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGVBQWUsQ0FBQyxDQUM3QyxDQUFDO1FBQ0osQ0FBQyxDQUFDO2FBQ0QsTUFBTSxDQUFDLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUM7YUFDaEQsS0FBSyxDQUFDLENBQUMsRUFBRSxxQkFBcUIsQ0FBQzthQUMvQixLQUFLLEVBQUUsQ0FBQztJQUNiLENBQUMsQ0FBQztTQUNELE1BQU0sQ0FBQyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDO1NBQ2hELEtBQUssQ0FBQyxDQUFDLEVBQUUsaUJBQWlCLENBQUM7U0FDM0IsS0FBSyxFQUFFLENBQUM7SUFFWCxJQUFJLGtCQUFrQixHQUFHLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQztTQUM1QyxNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtRQUN2QixPQUFPLENBQ0wsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUN4QyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksY0FBYztnQkFDeEMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDO2dCQUMxQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWM7b0JBQ3ZDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGVBQWUsQ0FBQyxDQUFDLENBQ2hELENBQUM7SUFDSixDQUFDLENBQUM7U0FDRCxLQUFLLENBQUMsQ0FBQyxFQUFFLGVBQWUsQ0FBQztTQUN6QixLQUFLLEVBQUUsQ0FBQztJQUVYLElBQUksa0JBQWtCLENBQUMsTUFBTSxJQUFJLENBQUMsSUFBSSxlQUFlLEdBQUcsQ0FBQyxFQUFFO1FBQ3pELDhEQUE4RDtRQUM5RCxzSEFBc0g7UUFDdEgsSUFDRSxDQUFDLENBQ0MsT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPO1lBQzFCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUU7Z0JBQzVCLDRDQUE0QztnQkFDNUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUU7b0JBQzlCLDRDQUE0QyxDQUFDLENBQ2hELEVBQ0Q7WUFDQSxnRkFBZ0Y7WUFDaEYsK0ZBQStGO1lBQy9GLHVHQUF1RztZQUN2RyxrQkFBa0IsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUN4Qix5QkFBeUIsQ0FBQyxPQUFPLENBQUMsRUFDbEMsQ0FBQyxTQUFTLEVBQUUsRUFBRTtnQkFDWixNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsR0FBRyxZQUFZLENBQUMsY0FBYyxDQUNqRSxPQUFPLEVBQ1AsUUFBUSxFQUNSLFNBQVMsQ0FDVixDQUFDO2dCQUNGLE9BQU87b0JBQ0wsRUFBRSxFQUFFLFdBQVc7b0JBQ2YsT0FBTyxFQUFFLGdCQUFnQixDQUFDLFNBQVMsQ0FBQztvQkFDcEMsU0FBUyxFQUFFLE9BQU87b0JBQ2xCLE1BQU0sRUFBRTt3QkFDTixFQUFFLEVBQUUsTUFBTSxDQUFDLE9BQU87cUJBQ25CO29CQUNELE1BQU0sRUFBRTt3QkFDTixFQUFFLEVBQUUsTUFBTSxDQUFDLE9BQU87cUJBQ25CO29CQUNELE1BQU0sRUFBRSxLQUFLO29CQUNiLE1BQU0sRUFBRSxLQUFLO2lCQUNkLENBQUM7WUFDSixDQUFDLENBQ0YsQ0FBQztZQUVGLGtCQUFrQixHQUFHLGtCQUFrQixDQUFDLE1BQU0sQ0FDNUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FDeEQsQ0FBQztTQUNIO0tBQ0Y7SUFFRCxlQUFlLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUVwQyxNQUFNLG9CQUFvQixHQUN4QixNQUFBLHVCQUF1QixDQUFDLE9BQU8sQ0FBQywwQ0FBRSxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFMUQseUZBQXlGO0lBQ3pGLHFHQUFxRztJQUNyRyw4QkFBOEI7SUFDOUIsSUFBSSxxQkFBcUIsR0FBcUIsRUFBRSxDQUFDO0lBQ2pELElBQ0UsQ0FBQyxDQUFBLE1BQUEsdUJBQXVCLENBQUMsT0FBTyxDQUFDLDBDQUFFLE1BQU07U0FDdkMsTUFBQSx1QkFBdUIsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLDBDQUFFLE1BQU0sQ0FBQTtRQUNoRCxRQUFRLENBQUMsTUFBTSxJQUFJLE1BQU07UUFDekIsUUFBUSxDQUFDLE1BQU0sSUFBSSxPQUFPO1FBQzFCLFFBQVEsQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDO1FBQzNCLENBQUMsQ0FBQSxNQUFBLHVCQUF1QixDQUFDLE9BQU8sQ0FBQywwQ0FBRSxNQUFNLEtBQUksY0FBYyxDQUFDLE1BQU07WUFDaEUsUUFBUSxDQUFDLE1BQU0sSUFBSSxPQUFPO1lBQzFCLFFBQVEsQ0FBQyxNQUFNLElBQUksUUFBUSxDQUFDLEVBQzlCO1FBQ0EscUJBQXFCLEdBQUcsQ0FBQyxDQUFDLG1CQUFtQixDQUFDO2FBQzNDLE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1lBQ3ZCLElBQUksU0FBUyxJQUFJLFNBQVMsQ0FBQyxXQUFXLEVBQUU7Z0JBQ3RDLE9BQU8sQ0FDTCxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLG9CQUFvQjtvQkFDN0MsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDO29CQUM1QyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLG9CQUFvQjt3QkFDN0MsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDLENBQzdDLENBQUM7YUFDSDtpQkFBTTtnQkFDTCxPQUFPLENBQ0wsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxvQkFBb0I7b0JBQzdDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQztvQkFDM0MsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxvQkFBb0I7d0JBQzdDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQyxDQUM1QyxDQUFDO2FBQ0g7UUFDSCxDQUFDLENBQUM7YUFDRCxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQzthQUNYLEtBQUssRUFBRSxDQUFDO0tBQ1o7SUFFRCxlQUFlLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUV2QyxNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsbUJBQW1CLENBQUM7U0FDcEMsTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7UUFDdkIsT0FBTyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEQsQ0FBQyxDQUFDO1NBQ0QsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUM7U0FDZCxLQUFLLEVBQUUsQ0FBQztJQUVYLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUUxQixNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQztTQUNoRCxNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtRQUN2QixPQUFPLENBQ0wsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUN4QyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWM7Z0JBQ3ZDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQyxDQUM1QyxDQUFDO0lBQ0osQ0FBQyxDQUFDO1NBQ0QsS0FBSyxDQUFDLENBQUMsRUFBRSxjQUFjLENBQUM7U0FDeEIsS0FBSyxFQUFFLENBQUM7SUFFWCxlQUFlLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUV0QyxNQUFNLHFCQUFxQixHQUFHLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQztTQUNqRCxNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtRQUN2QixPQUFPLENBQ0wsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUN4QyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGVBQWU7Z0JBQ3hDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGVBQWUsQ0FBQyxDQUM3QyxDQUFDO0lBQ0osQ0FBQyxDQUFDO1NBQ0QsS0FBSyxDQUFDLENBQUMsRUFBRSxjQUFjLENBQUM7U0FDeEIsS0FBSyxFQUFFLENBQUM7SUFFWCxlQUFlLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUV2QyxNQUFNLDhCQUE4QixHQUFHLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQztTQUMzRCxHQUFHLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtRQUNwQixPQUFPLGNBQWMsSUFBSSxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDN0MsQ0FBQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUN4QixDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7SUFDN0IsQ0FBQyxDQUFDO1NBQ0QsT0FBTyxDQUFDLENBQUMsV0FBbUIsRUFBRSxFQUFFOztRQUMvQixPQUFPLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQzthQUMxQixNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtZQUN2QixPQUFPLENBQ0wsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztnQkFDeEMsQ0FBQyxDQUFBLHlCQUF5QixhQUF6Qix5QkFBeUIsdUJBQXpCLHlCQUF5QixDQUFFLFFBQVEsQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQTtnQkFDL0QsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxXQUFXO29CQUNwQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxXQUFXLENBQUMsQ0FDekMsQ0FBQztRQUNKLENBQUMsQ0FBQzthQUNELEtBQUssQ0FDSixDQUFDLEVBQ0QsTUFBQSw0QkFBNEIsYUFBNUIsNEJBQTRCLHVCQUE1Qiw0QkFBNEIsQ0FBRSxHQUFHLENBQUMsV0FBVyxDQUFDLG1DQUFJLGFBQWEsQ0FDaEU7YUFDQSxLQUFLLEVBQUUsQ0FBQztJQUNiLENBQUMsQ0FBQztTQUNELE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztTQUN6QixLQUFLLEVBQUUsQ0FBQztJQUVYLGVBQWUsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0lBRWhELE1BQU0sK0JBQStCLEdBQUcsQ0FBQyxDQUFDLHFCQUFxQixDQUFDO1NBQzdELEdBQUcsQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1FBQ3BCLE9BQU8sZUFBZSxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUM5QyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ3hCLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztJQUM3QixDQUFDLENBQUM7U0FDRCxPQUFPLENBQUMsQ0FBQyxXQUFtQixFQUFFLEVBQUU7O1FBQy9CLE9BQU8sQ0FBQyxDQUFDLG1CQUFtQixDQUFDO2FBQzFCLE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO1lBQ3ZCLE9BQU8sQ0FDTCxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO2dCQUN4QyxDQUFDLENBQUEseUJBQXlCLGFBQXpCLHlCQUF5Qix1QkFBekIseUJBQXlCLENBQUUsUUFBUSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFBO2dCQUMvRCxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFdBQVc7b0JBQ3BDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFdBQVcsQ0FBQyxDQUN6QyxDQUFDO1FBQ0osQ0FBQyxDQUFDO2FBQ0QsS0FBSyxDQUNKLENBQUMsRUFDRCxNQUFBLDRCQUE0QixhQUE1Qiw0QkFBNEIsdUJBQTVCLDRCQUE0QixDQUFFLEdBQUcsQ0FBQyxXQUFXLENBQUMsbUNBQUksYUFBYSxDQUNoRTthQUNBLEtBQUssRUFBRSxDQUFDO0lBQ2IsQ0FBQyxDQUFDO1NBQ0QsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1NBQ3pCLEtBQUssRUFBRSxDQUFDO0lBRVgsZUFBZSxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFFakQsTUFBTSxhQUFhLEdBQUcsQ0FBQyxDQUFDO1FBQ3RCLEdBQUcsb0JBQW9CO1FBQ3ZCLEdBQUcscUJBQXFCO1FBQ3hCLEdBQUcsa0JBQWtCO1FBQ3JCLEdBQUcscUJBQXFCO1FBQ3hCLEdBQUcsUUFBUTtRQUNYLEdBQUcsb0JBQW9CO1FBQ3ZCLEdBQUcscUJBQXFCO1FBQ3hCLEdBQUcsOEJBQThCO1FBQ2pDLEdBQUcsK0JBQStCO0tBQ25DLENBQUM7U0FDQyxPQUFPLEVBQUU7U0FDVCxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7U0FDekIsS0FBSyxFQUFFLENBQUM7SUFFWCxNQUFNLGNBQWMsR0FBRyxDQUFDLENBQUMsYUFBYSxDQUFDO1NBQ3BDLE9BQU8sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQzNFLE9BQU8sRUFBRTtTQUNULElBQUksRUFBRTtTQUNOLEtBQUssRUFBRSxDQUFDO0lBRVgsR0FBRyxDQUFDLElBQUksQ0FDTixlQUFlLGNBQWMsQ0FBQyxNQUFNLHNCQUFzQixhQUFhLENBQUMsTUFBTSw4QkFBOEIsQ0FDN0csQ0FBQztJQUVGLE1BQU0sYUFBYSxHQUFHLE1BQU0sYUFBYSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUU7UUFDbEUsV0FBVztLQUNaLENBQUMsQ0FBQztJQUVILE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFpQixFQUFFLEVBQUU7O1FBQ2hELE9BQUEsR0FBRyxNQUFBLE1BQUEsYUFBYSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLDBDQUFFLE1BQU0sbUNBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksTUFBQSxNQUFBLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQywwQ0FBRSxNQUFNLG1DQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFDM0ksSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUE7S0FBQSxDQUFDO0lBRWxCLEdBQUcsQ0FBQyxJQUFJLENBQ047UUFDRSxvQkFBb0IsRUFBRSxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7UUFDbkUscUJBQXFCLEVBQUUscUJBQXFCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO1FBQ3JFLFFBQVEsRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO1FBQzNDLG9CQUFvQixFQUFFLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztRQUNuRSxxQkFBcUIsRUFBRSxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7UUFDckUsOEJBQThCLEVBQzVCLDhCQUE4QixDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztRQUN6RCwrQkFBK0IsRUFDN0IsK0JBQStCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO1FBQzFELGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7UUFDM0QsZ0JBQWdCLEVBQUUscUJBQXFCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO0tBQ2pFLEVBQ0Qsb0JBQW9CLENBQ3JCLENBQUM7SUFFRixNQUFNLGFBQWEsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUd6QixhQUFhLEVBQUUsQ0FBQyxZQUFZLEVBQUUsRUFBRTtRQUNoQyxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN2RSxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN2RSxJQUFJLEdBQWMsQ0FBQztRQUNuQixJQUFJO1lBQ0YsR0FBRyxHQUFHLGNBQWMsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDNUM7UUFBQyxPQUFPLEdBQUcsRUFBRTtZQUNaLEdBQUcsQ0FBQyxJQUFJLENBQ04sRUFBRSxZQUFZLEVBQUUsRUFDaEIsK0JBQStCLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVksQ0FBQyxPQUFPLGlDQUFpQyxDQUN6SSxDQUFDO1lBQ0YsT0FBTyxTQUFTLENBQUM7U0FDbEI7UUFFRCxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ3RCLEdBQUcsQ0FBQyxJQUFJLENBQ04sK0JBQStCLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFDN0UsSUFBSSxHQUFHLFlBQVksTUFBTSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUN6RSw4QkFBOEIsQ0FDL0IsQ0FBQztZQUNGLE9BQU8sU0FBUyxDQUFDO1NBQ2xCO1FBRUQsT0FBTyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDL0IsQ0FBQyxDQUFDLENBQUM7SUFFSCxNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBRTVDLE1BQU0sQ0FBQyxTQUFTLENBQ2QsbUJBQW1CLEVBQ25CLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxtQkFBbUIsRUFDaEMsZ0JBQWdCLENBQUMsWUFBWSxDQUM5QixDQUFDO0lBRUYsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBRW5DLE1BQU0sWUFBWSxHQUFHLE1BQU0sWUFBWSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUU7UUFDM0QsV0FBVztLQUNaLENBQUMsQ0FBQztJQUVILE1BQU0sQ0FBQyxTQUFTLENBQ2QsYUFBYSxFQUNiLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxlQUFlLEVBQzVCLGdCQUFnQixDQUFDLFlBQVksQ0FDOUIsQ0FBQztJQUVGLE1BQU0sZ0JBQWdCLEdBQXNDO1FBQzFELFFBQVEsRUFBRSxRQUFRLENBQUMsRUFBRTtRQUNyQixVQUFVLEVBQUU7WUFDVixvQkFBb0I7WUFDcEIscUJBQXFCO1lBQ3JCLG1CQUFtQixFQUFFLGtCQUFrQjtZQUN2QyxzQkFBc0IsRUFBRSxxQkFBcUI7WUFDN0MsUUFBUTtZQUNSLG9CQUFvQjtZQUNwQixxQkFBcUI7WUFDckIsOEJBQThCO1lBQzlCLCtCQUErQjtTQUNoQztLQUNGLENBQUM7SUFFRixPQUFPLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsQ0FBQztBQUMzRSxDQUFDO0FBUUQsTUFBTSxDQUFDLEtBQUssVUFBVSxtQkFBbUIsQ0FBQyxFQUN4QyxPQUFPLEVBQ1AsUUFBUSxFQUNSLFNBQVMsRUFDVCxhQUFhLEVBQ2IsZ0JBQWdCLEVBQ2hCLGFBQWEsRUFDYixZQUFZLEVBQ1osd0JBQXdCLEVBQ3hCLE9BQU8sR0FDbUI7O0lBQzFCLE1BQU0sRUFDSixXQUFXLEVBQ1gsZUFBZSxFQUFFLEVBQ2YsSUFBSSxFQUNKLGVBQWUsRUFDZixjQUFjLEVBQ2QsYUFBYSxFQUNiLHlCQUF5QixFQUN6QixxQkFBcUIsRUFDckIsaUJBQWlCLEdBQ2xCLEdBQ0YsR0FBRyxhQUFhLENBQUM7SUFDbEIsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyRCxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBRXZELE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBRXZDLE1BQU0sV0FBVyxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUU7UUFDckUsV0FBVztLQUNaLENBQUMsQ0FBQztJQUVILGdGQUFnRjtJQUNoRiwyRkFBMkY7SUFDM0YsS0FBSyxNQUFNLElBQUksSUFBSSxXQUFXLEVBQUU7UUFDOUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDOUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7S0FDL0M7SUFFRCxNQUFNLENBQUMsU0FBUyxDQUNkLHFCQUFxQixFQUNyQixJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsbUJBQW1CLEVBQ2hDLGdCQUFnQixDQUFDLFlBQVksQ0FDOUIsQ0FBQztJQUVGLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBRXZDLDRDQUE0QztJQUM1QyxNQUFNLG1CQUFtQixHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUU5RSxNQUFNLGtCQUFrQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFFN0MscUdBQXFHO0lBQ3JHLG1HQUFtRztJQUNuRyw0RkFBNEY7SUFDNUYsSUFBSSxtQkFBbUIsR0FBcUIsRUFBRSxDQUFDO0lBQy9DLElBQUksZUFBZSxHQUFHLENBQUMsRUFBRTtRQUN2QixNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsR0FBRyxZQUFZLENBQUMsY0FBYyxDQUNqRSxPQUFPLEVBQ1AsUUFBUSxDQUNULENBQUM7UUFFRixrQkFBa0IsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFFbEQsbUJBQW1CLEdBQUc7WUFDcEI7Z0JBQ0UsRUFBRSxFQUFFLFdBQVc7Z0JBQ2YsTUFBTSxFQUFFO29CQUNOLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTztpQkFDbkI7Z0JBQ0QsTUFBTSxFQUFFO29CQUNOLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTztpQkFDbkI7Z0JBQ0QsTUFBTSxFQUFFLEtBQUs7Z0JBQ2IsT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsVUFBVSxFQUFFLEtBQUssRUFBRSxxQ0FBcUM7YUFDekQ7U0FDRixDQUFDO0tBQ0g7SUFFRCxNQUFNLFdBQVcsR0FBRyx1QkFBdUIsQ0FBQyxPQUFPLENBQUUsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFNUUsTUFBTSx1QkFBdUIsR0FHekIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNkLE1BQU0sd0JBQXdCLEdBRzFCLElBQUksR0FBRyxFQUFFLENBQUM7SUFFZCxNQUFNLFVBQVUsR0FBRyxNQUFBLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxtQ0FBSSxFQUFFLENBQUM7SUFDcEQsTUFBTSxtQkFBbUIsR0FBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUVuRCxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDM0IsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUVsRCxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDdkMsdUJBQXVCLENBQUMsR0FBRyxDQUN6QixhQUFhLEVBQ2IsSUFBSSx5QkFBeUIsQ0FBaUIsRUFBRSxFQUFFLHFCQUFxQixDQUFDLENBQ3pFLENBQUM7UUFDRix3QkFBd0IsQ0FBQyxHQUFHLENBQzFCLGFBQWEsRUFDYixJQUFJLHlCQUF5QixDQUFpQixFQUFFLEVBQUUscUJBQXFCLENBQUMsQ0FDekUsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSw4QkFBOEIsR0FBRyxDQUFDLENBQUM7SUFDdkMsSUFBSSwrQkFBK0IsR0FBRyxDQUFDLENBQUM7SUFFeEMsZ0RBQWdEO0lBQ2hELHNFQUFzRTtJQUN0RSxJQUFJLGlCQUFpQixHQUFHLENBQUMsQ0FBQztJQUMxQixnREFBZ0Q7SUFDaEQsSUFDRSxRQUFRLENBQUMsTUFBTSxJQUFJLE1BQU07UUFDekIsUUFBUSxDQUFDLE1BQU0sSUFBSSxPQUFPO1FBQzFCLFFBQVEsQ0FBQyxNQUFNLElBQUksS0FBSyxFQUN4QjtRQUNBLDRFQUE0RTtRQUM1RSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7S0FDdkI7SUFFRCxNQUFNLHNCQUFzQixHQUFxQixFQUFFLENBQUM7SUFDcEQsTUFBTSxvQkFBb0IsR0FBcUIsRUFBRSxDQUFDO0lBQ2xELE1BQU0scUJBQXFCLEdBQXFCLEVBQUUsQ0FBQztJQUNuRCxNQUFNLFFBQVEsR0FBcUIsRUFBRSxDQUFDO0lBRXRDLDREQUE0RDtJQUM1RCxJQUFJLHFCQUFxQixHQUFHLENBQUMsQ0FBQztJQUU5QixxQ0FBcUM7SUFDckMseUZBQXlGO0lBQ3pGLEtBQUssTUFBTSxZQUFZLElBQUksbUJBQW1CLEVBQUU7UUFDOUMscUJBQXFCLElBQUksQ0FBQyxDQUFDO1FBQzNCLHFFQUFxRTtRQUNyRSxJQUNFLDhCQUE4QixJQUFJLGlCQUFpQjtZQUNuRCwrQkFBK0IsSUFBSSxpQkFBaUI7WUFDcEQsc0JBQXNCLENBQUMsTUFBTSxJQUFJLGlCQUFpQjtZQUNsRCxRQUFRLENBQUMsTUFBTSxJQUFJLElBQUk7WUFDdkIsb0JBQW9CLENBQUMsTUFBTSxJQUFJLGNBQWM7WUFDN0MscUJBQXFCLENBQUMsTUFBTSxJQUFJLGNBQWMsRUFDOUM7WUFDQSx3REFBd0Q7WUFDeEQsTUFBTTtTQUNQO1FBRUQsSUFBSSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQzNDLDZDQUE2QztZQUM3QyxTQUFTO1NBQ1Y7UUFFRCwwRUFBMEU7UUFDMUUsSUFBSSx3QkFBd0IsRUFBRTtZQUM1QixNQUFNLENBQUMsaUJBQWlCLEVBQUUsaUJBQWlCLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7Z0JBQy9ELHdCQUF3QixDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO2dCQUNsRSx3QkFBd0IsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQzthQUNuRSxDQUFDLENBQUM7WUFFSCxJQUFJLGlCQUFpQixJQUFJLGlCQUFpQixFQUFFO2dCQUMxQyxTQUFTO2FBQ1Y7U0FDRjtRQUVELE1BQU0sc0JBQXNCLEdBQUcsdUJBQXVCLENBQUMsR0FBRyxDQUN4RCxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FDdkIsQ0FBQztRQUNGLElBQ0UsOEJBQThCLEdBQUcsaUJBQWlCO1lBQ2xELHNCQUFzQjtZQUN0QixZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxlQUFlO1lBQ3pDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsRUFDeEM7WUFDQSw4QkFBOEIsSUFBSSxDQUFDLENBQUM7WUFDcEMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN4QyxJQUFJLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxjQUFjLEVBQUU7Z0JBQ2hELG9CQUFvQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUN6QztZQUNELElBQ0UsU0FBUyxLQUFLLFNBQVMsQ0FBQyxZQUFZO2dCQUNwQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxXQUFXLEVBQ3JDO2dCQUNBLHNCQUFzQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUMzQztZQUNELHNCQUFzQixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDaEQsU0FBUztTQUNWO1FBRUQsTUFBTSxzQkFBc0IsR0FBRyx1QkFBdUIsQ0FBQyxHQUFHLENBQ3hELFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUN2QixDQUFDO1FBQ0YsSUFDRSw4QkFBOEIsR0FBRyxpQkFBaUI7WUFDbEQsc0JBQXNCO1lBQ3RCLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWM7WUFDeEMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxFQUN6QztZQUNBLDhCQUE4QixJQUFJLENBQUMsQ0FBQztZQUNwQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3hDLElBQUksb0JBQW9CLENBQUMsTUFBTSxHQUFHLGNBQWMsRUFBRTtnQkFDaEQsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQ3pDO1lBQ0QsSUFDRSxTQUFTLEtBQUssU0FBUyxDQUFDLFlBQVk7Z0JBQ3BDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFdBQVcsRUFDckM7Z0JBQ0Esc0JBQXNCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQzNDO1lBQ0Qsc0JBQXNCLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNoRCxTQUFTO1NBQ1Y7UUFFRCxNQUFNLHVCQUF1QixHQUFHLHdCQUF3QixDQUFDLEdBQUcsQ0FDMUQsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQ3ZCLENBQUM7UUFDRixJQUNFLCtCQUErQixHQUFHLGlCQUFpQjtZQUNuRCx1QkFBdUI7WUFDdkIsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksY0FBYztZQUN4QyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxlQUFlLEVBQ3pDO1lBQ0EsK0JBQStCLElBQUksQ0FBQyxDQUFDO1lBQ3JDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDeEMsSUFBSSxxQkFBcUIsQ0FBQyxNQUFNLEdBQUcsY0FBYyxFQUFFO2dCQUNqRCxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7YUFDMUM7WUFDRCxJQUNFLFNBQVMsS0FBSyxTQUFTLENBQUMsV0FBVztnQkFDbkMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksV0FBVyxFQUNyQztnQkFDQSxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7YUFDM0M7WUFDRCx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2pELFNBQVM7U0FDVjtRQUVELE1BQU0sdUJBQXVCLEdBQUcsd0JBQXdCLENBQUMsR0FBRyxDQUMxRCxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FDdkIsQ0FBQztRQUNGLElBQ0UsK0JBQStCLEdBQUcsaUJBQWlCO1lBQ25ELHVCQUF1QjtZQUN2QixZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxlQUFlO1lBQ3pDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsRUFDeEM7WUFDQSwrQkFBK0IsSUFBSSxDQUFDLENBQUM7WUFDckMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN4QyxJQUFJLHFCQUFxQixDQUFDLE1BQU0sR0FBRyxjQUFjLEVBQUU7Z0JBQ2pELHFCQUFxQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUMxQztZQUNELElBQ0UsU0FBUyxLQUFLLFNBQVMsQ0FBQyxXQUFXO2dCQUNuQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxXQUFXLEVBQ3JDO2dCQUNBLHNCQUFzQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUMzQztZQUNELHVCQUF1QixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDakQsU0FBUztTQUNWO1FBRUQsNEVBQTRFO1FBQzVFLElBQ0Usc0JBQXNCLENBQUMsTUFBTSxHQUFHLGlCQUFpQjtZQUNqRCxDQUFDLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQyxXQUFXO2dCQUNuQyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksV0FBVztvQkFDckMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDO29CQUMxQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFdBQVc7d0JBQ3BDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGVBQWUsQ0FBQyxDQUFDLENBQUM7Z0JBQ2hELENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQyxZQUFZO29CQUNuQyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksV0FBVzt3QkFDckMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksY0FBYyxDQUFDO3dCQUN6QyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFdBQVc7NEJBQ3BDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUNwRDtZQUNBLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDeEMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzFDLFNBQVM7U0FDVjtRQUVELElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxJQUFJLEVBQUU7WUFDMUIsa0JBQWtCLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN4QyxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzVCLFNBQVM7U0FDVjtRQUVELElBQ0Usb0JBQW9CLENBQUMsTUFBTSxHQUFHLGNBQWM7WUFDNUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxjQUFjO2dCQUN2QyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxjQUFjLENBQUMsRUFDM0M7WUFDQSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3hDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN4QyxTQUFTO1NBQ1Y7UUFFRCxJQUNFLHFCQUFxQixDQUFDLE1BQU0sR0FBRyxjQUFjO1lBQzdDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZTtnQkFDeEMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksZUFBZSxDQUFDLEVBQzVDO1lBQ0Esa0JBQWtCLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN4QyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDekMsU0FBUztTQUNWO0tBQ0Y7SUFFRCxNQUFNLENBQUMsU0FBUyxDQUNkLGlDQUFpQyxFQUNqQyxxQkFBcUIsRUFDckIsZ0JBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO0lBRUYsTUFBTSxvQkFBb0IsR0FBcUIsRUFBRSxDQUFDO0lBQ2xELEtBQUssTUFBTSw2QkFBNkIsSUFBSSx1QkFBdUIsQ0FBQyxNQUFNLEVBQUUsRUFBRTtRQUM1RSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsR0FBRyw2QkFBNkIsQ0FBQyxLQUFLLENBQUMsQ0FBQztLQUNuRTtJQUVELE1BQU0scUJBQXFCLEdBQXFCLEVBQUUsQ0FBQztJQUNuRCxLQUFLLE1BQU0sOEJBQThCLElBQUksd0JBQXdCLENBQUMsTUFBTSxFQUFFLEVBQUU7UUFDOUUscUJBQXFCLENBQUMsSUFBSSxDQUFDLEdBQUcsOEJBQThCLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDckU7SUFFRCxpQ0FBaUM7SUFDakMsTUFBTSxpQ0FBaUMsR0FHbkMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNkLE1BQU0sa0NBQWtDLEdBR3BDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDZCxNQUFNLHlCQUF5QixHQUFHLG9CQUFvQjtTQUNuRCxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtRQUNmLHdCQUF3QjtRQUN4QixJQUFJLGNBQWMsS0FBSyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRTtZQUNyQyxPQUFPLENBQUMsQ0FBQSx5QkFBeUIsYUFBekIseUJBQXlCLHVCQUF6Qix5QkFBeUIsQ0FBRSxRQUFRLENBQ3pDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUM3QixDQUFBLENBQUM7U0FDSDthQUFNO1lBQ0wsT0FBTyxDQUFDLENBQUEseUJBQXlCLGFBQXpCLHlCQUF5Qix1QkFBekIseUJBQXlCLENBQUUsUUFBUSxDQUN6QyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FDN0IsQ0FBQSxDQUFDO1NBQ0g7SUFDSCxDQUFDLENBQUM7U0FDRCxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUNaLGNBQWMsS0FBSyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUNwRSxDQUFDO0lBQ0osTUFBTSwwQkFBMEIsR0FBRyxxQkFBcUI7U0FDckQsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7UUFDZix3QkFBd0I7UUFDeEIsSUFBSSxlQUFlLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUU7WUFDdEMsT0FBTyxDQUFDLENBQUEseUJBQXlCLGFBQXpCLHlCQUF5Qix1QkFBekIseUJBQXlCLENBQUUsUUFBUSxDQUN6QyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FDN0IsQ0FBQSxDQUFDO1NBQ0g7YUFBTTtZQUNMLE9BQU8sQ0FBQyxDQUFBLHlCQUF5QixhQUF6Qix5QkFBeUIsdUJBQXpCLHlCQUF5QixDQUFFLFFBQVEsQ0FDekMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQzdCLENBQUEsQ0FBQztTQUNIO0lBQ0gsQ0FBQyxDQUFDO1NBQ0QsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FDWixlQUFlLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FDckUsQ0FBQztJQUVKLEtBQUssTUFBTSxXQUFXLElBQUkseUJBQXlCLEVBQUU7UUFDbkQsaUNBQWlDLENBQUMsR0FBRyxDQUNuQyxXQUFXLEVBQ1gsSUFBSSx5QkFBeUIsQ0FBaUIsRUFBRSxFQUFFLGFBQWEsQ0FBQyxDQUNqRSxDQUFDO0tBQ0g7SUFDRCxLQUFLLE1BQU0sV0FBVyxJQUFJLDBCQUEwQixFQUFFO1FBQ3BELGtDQUFrQyxDQUFDLEdBQUcsQ0FDcEMsV0FBVyxFQUNYLElBQUkseUJBQXlCLENBQWlCLEVBQUUsRUFBRSxhQUFhLENBQUMsQ0FDakUsQ0FBQztLQUNIO0lBRUQsNkRBQTZEO0lBQzdELElBQUksc0JBQXNCLEdBQUcsQ0FBQyxDQUFDO0lBRS9CLElBQ0UseUJBQXlCLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDcEMsMEJBQTBCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFDckM7UUFDQSxLQUFLLE1BQU0sWUFBWSxJQUFJLG1CQUFtQixFQUFFO1lBQzlDLHNCQUFzQixJQUFJLENBQUMsQ0FBQztZQUU1QixJQUFJLGlDQUFpQyxHQUFHLElBQUksQ0FBQztZQUM3QyxLQUFLLE1BQU0sY0FBYyxJQUFJLGlDQUFpQyxDQUFDLE1BQU0sRUFBRSxFQUFFO2dCQUN2RSxJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsRUFBRSxFQUFFO29CQUNwQyxpQ0FBaUMsR0FBRyxLQUFLLENBQUM7b0JBQzFDLE1BQU07aUJBQ1A7YUFDRjtZQUVELElBQUksa0NBQWtDLEdBQUcsSUFBSSxDQUFDO1lBQzlDLEtBQUssTUFBTSxjQUFjLElBQUksa0NBQWtDLENBQUMsTUFBTSxFQUFFLEVBQUU7Z0JBQ3hFLElBQUksQ0FBQyxjQUFjLENBQUMsY0FBYyxFQUFFLEVBQUU7b0JBQ3BDLGtDQUFrQyxHQUFHLEtBQUssQ0FBQztvQkFDM0MsTUFBTTtpQkFDUDthQUNGO1lBRUQsSUFDRSxpQ0FBaUM7Z0JBQ2pDLGtDQUFrQyxFQUNsQztnQkFDQSx3REFBd0Q7Z0JBQ3hELE1BQU07YUFDUDtZQUVELElBQUksa0JBQWtCLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRTtnQkFDM0MsU0FBUzthQUNWO1lBRUQsMEVBQTBFO1lBQzFFLElBQUksd0JBQXdCLEVBQUU7Z0JBQzVCLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxpQkFBaUIsQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztvQkFDL0Qsd0JBQXdCLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7b0JBQ2xFLHdCQUF3QixDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO2lCQUNuRSxDQUFDLENBQUM7Z0JBRUgsSUFBSSxpQkFBaUIsSUFBSSxpQkFBaUIsRUFBRTtvQkFDMUMsU0FBUztpQkFDVjthQUNGO1lBRUQsTUFBTSxzQkFBc0IsR0FBRyxpQ0FBaUMsQ0FBQyxHQUFHLENBQ2xFLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUN2QixDQUFDO1lBRUYsSUFBSSxzQkFBc0IsSUFBSSxDQUFDLHNCQUFzQixDQUFDLGNBQWMsRUFBRSxFQUFFO2dCQUN0RSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN4QyxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUNoRCxTQUFTO2FBQ1Y7WUFFRCxNQUFNLHNCQUFzQixHQUFHLGlDQUFpQyxDQUFDLEdBQUcsQ0FDbEUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQ3ZCLENBQUM7WUFFRixJQUFJLHNCQUFzQixJQUFJLENBQUMsc0JBQXNCLENBQUMsY0FBYyxFQUFFLEVBQUU7Z0JBQ3RFLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3hDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQ2hELFNBQVM7YUFDVjtZQUVELE1BQU0sdUJBQXVCLEdBQUcsa0NBQWtDLENBQUMsR0FBRyxDQUNwRSxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FDdkIsQ0FBQztZQUVGLElBQ0UsdUJBQXVCO2dCQUN2QixDQUFDLHVCQUF1QixDQUFDLGNBQWMsRUFBRSxFQUN6QztnQkFDQSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN4Qyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUNqRCxTQUFTO2FBQ1Y7WUFFRCxNQUFNLHVCQUF1QixHQUFHLGtDQUFrQyxDQUFDLEdBQUcsQ0FDcEUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQ3ZCLENBQUM7WUFFRixJQUNFLHVCQUF1QjtnQkFDdkIsQ0FBQyx1QkFBdUIsQ0FBQyxjQUFjLEVBQUUsRUFDekM7Z0JBQ0Esa0JBQWtCLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDeEMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDakQsU0FBUzthQUNWO1NBQ0Y7S0FDRjtJQUVELE1BQU0sQ0FBQyxTQUFTLENBQ2Qsa0NBQWtDLEVBQ2xDLHNCQUFzQixFQUN0QixnQkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7SUFFRixNQUFNLDhCQUE4QixHQUFxQixFQUFFLENBQUM7SUFDNUQsS0FBSyxNQUFNLGNBQWMsSUFBSSxpQ0FBaUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtRQUN2RSw4QkFBOEIsQ0FBQyxJQUFJLENBQUMsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDOUQ7SUFFRCxNQUFNLCtCQUErQixHQUFxQixFQUFFLENBQUM7SUFDN0QsS0FBSyxNQUFNLGNBQWMsSUFBSSxrQ0FBa0MsQ0FBQyxNQUFNLEVBQUUsRUFBRTtRQUN4RSwrQkFBK0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDL0Q7SUFFRCxNQUFNLGFBQWEsR0FBRyxDQUFDLENBQUM7UUFDdEIsR0FBRyxvQkFBb0I7UUFDdkIsR0FBRyxxQkFBcUI7UUFDeEIsR0FBRyxtQkFBbUI7UUFDdEIsR0FBRyxzQkFBc0I7UUFDekIsR0FBRyxRQUFRO1FBQ1gsR0FBRyxvQkFBb0I7UUFDdkIsR0FBRyxxQkFBcUI7UUFDeEIsR0FBRyw4QkFBOEI7UUFDakMsR0FBRywrQkFBK0I7S0FDbkMsQ0FBQztTQUNDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztTQUN6QixLQUFLLEVBQUUsQ0FBQztJQUVYLE1BQU0saUJBQWlCLEdBQWdCLElBQUksR0FBRyxFQUFFLENBQUM7SUFDakQsS0FBSyxNQUFNLElBQUksSUFBSSxhQUFhLEVBQUU7UUFDaEMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7S0FDdkM7SUFDRCxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFFckQsR0FBRyxDQUFDLElBQUksQ0FDTixlQUFlLGNBQWMsQ0FBQyxNQUFNLHNCQUFzQixhQUFhLENBQUMsTUFBTSw4QkFBOEIsQ0FDN0csQ0FBQztJQUVGLE1BQU0sYUFBYSxHQUFHLE1BQU0sYUFBYSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUU7UUFDbEUsV0FBVztLQUNaLENBQUMsQ0FBQztJQUVILE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFpQixFQUFFLEVBQUU7O1FBQ2hELE9BQUEsR0FBRyxNQUFBLE1BQUEsYUFBYSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLDBDQUFFLE1BQU0sbUNBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksTUFBQSxNQUFBLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQywwQ0FBRSxNQUFNLG1DQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFDM0ksRUFBRSxDQUFBO0tBQUEsQ0FBQztJQUVMLEdBQUcsQ0FBQyxJQUFJLENBQ047UUFDRSxvQkFBb0IsRUFBRSxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7UUFDbkUscUJBQXFCLEVBQUUscUJBQXFCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO1FBQ3JFLFFBQVEsRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO1FBQzNDLG9CQUFvQixFQUFFLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztRQUNuRSxxQkFBcUIsRUFBRSxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7UUFDckUsOEJBQThCLEVBQzVCLDhCQUE4QixDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztRQUN6RCwrQkFBK0IsRUFDN0IsK0JBQStCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO1FBQzFELGNBQWMsRUFBRSxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7UUFDNUQsZ0JBQWdCLEVBQUUsc0JBQXNCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO0tBQ2xFLEVBQ0Qsb0JBQW9CLENBQ3JCLENBQUM7SUFFRixNQUFNLGFBQWEsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUN6QixhQUFhLEVBQ2IsQ0FBQyxZQUFZLEVBQUUsRUFBRTtRQUNmLE1BQU0sTUFBTSxHQUFHLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sTUFBTSxHQUFHLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRXZFLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDdEIsR0FBRyxDQUFDLElBQUksQ0FDTiwrQkFBK0IsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsQ0FDbEYsQ0FBQztZQUNGLE9BQU8sU0FBUyxDQUFDO1NBQ2xCO1FBRUQsT0FBTyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMxQixDQUFDLENBQ0YsQ0FBQztJQUVGLE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7SUFFNUMsTUFBTSxDQUFDLFNBQVMsQ0FDZCxtQkFBbUIsRUFDbkIsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLG1CQUFtQixFQUNoQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7SUFFRixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFFbkMsd0VBQXdFO0lBQ3hFLHFGQUFxRjtJQUNyRixNQUFNLFlBQVksR0FBRyxNQUFNLFlBQVksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBRTVFLE1BQU0sQ0FBQyxTQUFTLENBQ2QsYUFBYSxFQUNiLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxlQUFlLEVBQzVCLGdCQUFnQixDQUFDLFlBQVksQ0FDOUIsQ0FBQztJQUVGLE1BQU0sZ0JBQWdCLEdBQXNDO1FBQzFELFFBQVEsRUFBRSxRQUFRLENBQUMsRUFBRTtRQUNyQixVQUFVLEVBQUU7WUFDVixvQkFBb0I7WUFDcEIscUJBQXFCO1lBQ3JCLG1CQUFtQjtZQUNuQixzQkFBc0I7WUFDdEIsUUFBUTtZQUNSLG9CQUFvQjtZQUNwQixxQkFBcUI7WUFDckIsOEJBQThCO1lBQzlCLCtCQUErQjtTQUNoQztLQUNGLENBQUM7SUFFRixPQUFPLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsQ0FBQztBQUMzRSxDQUFDO0FBVUQsTUFBTSxDQUFDLEtBQUssVUFBVSwyQkFBMkIsQ0FBQyxFQUNoRCxnQkFBZ0IsRUFDaEIsZ0JBQWdCLEVBQ2hCLGdCQUFnQixFQUNoQixtQkFBbUIsRUFDbkIsYUFBYSxFQUNiLGFBQWEsRUFDYixjQUFjLEVBQ2QsY0FBYyxFQUNkLGNBQWMsRUFDZCxPQUFPLEdBQzJCO0lBQ2xDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3ZDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQyxHQUFHO1FBQ3hDLGdCQUFnQjtRQUNoQixnQkFBZ0I7UUFDaEIsZ0JBQWdCO0tBQ2pCLENBQUM7SUFFRiw4Q0FBOEM7SUFDOUMsTUFBTSxFQUNKLGFBQWEsRUFBRSxlQUFlLEdBQUcsRUFBRSxFQUNuQyxjQUFjLEVBQUUsZ0JBQWdCLEdBQUc7UUFDakMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxFQUFFO1FBQ3JCLFVBQVUsRUFBRTtZQUNWLG9CQUFvQixFQUFFLEVBQUU7WUFDeEIscUJBQXFCLEVBQUUsRUFBRTtZQUN6QixtQkFBbUIsRUFBRSxFQUFFO1lBQ3ZCLHNCQUFzQixFQUFFLEVBQUU7WUFDMUIsUUFBUSxFQUFFLEVBQUU7WUFDWixvQkFBb0IsRUFBRSxFQUFFO1lBQ3hCLHFCQUFxQixFQUFFLEVBQUU7WUFDekIsOEJBQThCLEVBQUUsRUFBRTtZQUNsQywrQkFBK0IsRUFBRSxFQUFFO1NBQ3BDO0tBQ0YsR0FDRixHQUFHLFNBQVMsSUFBSSxFQUFFLENBQUM7SUFFcEIsTUFBTSxFQUNKLGFBQWEsRUFBRSxlQUFlLEdBQUcsRUFBRSxFQUNuQyxjQUFjLEVBQUUsZ0JBQWdCLEdBQUc7UUFDakMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxFQUFFO1FBQ3JCLFVBQVUsRUFBRTtZQUNWLG9CQUFvQixFQUFFLEVBQUU7WUFDeEIscUJBQXFCLEVBQUUsRUFBRTtZQUN6QixtQkFBbUIsRUFBRSxFQUFFO1lBQ3ZCLHNCQUFzQixFQUFFLEVBQUU7WUFDMUIsUUFBUSxFQUFFLEVBQUU7WUFDWixvQkFBb0IsRUFBRSxFQUFFO1lBQ3hCLHFCQUFxQixFQUFFLEVBQUU7WUFDekIsOEJBQThCLEVBQUUsRUFBRTtZQUNsQywrQkFBK0IsRUFBRSxFQUFFO1NBQ3BDO0tBQ0YsR0FDRixHQUFHLFNBQVMsSUFBSSxFQUFFLENBQUM7SUFFcEIsTUFBTSxFQUNKLGFBQWEsRUFBRSxlQUFlLEdBQUcsRUFBRSxFQUNuQyxjQUFjLEVBQUUsZ0JBQWdCLEdBQUc7UUFDakMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxFQUFFO1FBQ3JCLFVBQVUsRUFBRTtZQUNWLG9CQUFvQixFQUFFLEVBQUU7WUFDeEIscUJBQXFCLEVBQUUsRUFBRTtZQUN6QixtQkFBbUIsRUFBRSxFQUFFO1lBQ3ZCLHNCQUFzQixFQUFFLEVBQUU7WUFDMUIsUUFBUSxFQUFFLEVBQUU7WUFDWixvQkFBb0IsRUFBRSxFQUFFO1lBQ3hCLHFCQUFxQixFQUFFLEVBQUU7WUFDekIsOEJBQThCLEVBQUUsRUFBRTtZQUNsQywrQkFBK0IsRUFBRSxFQUFFO1NBQ3BDO0tBQ0YsR0FDRixHQUFHLFNBQVMsSUFBSSxFQUFFLENBQUM7SUFFcEIseUZBQXlGO0lBQ3pGLGVBQWUsQ0FBQyxJQUFJLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyRCxlQUFlLENBQUMsSUFBSSxDQUFDLEdBQUcsbUJBQW1CLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDckQsZUFBZSxDQUFDLElBQUksQ0FBQyxHQUFHLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRXJELE1BQU0sQ0FBQyxTQUFTLENBQ2Qsd0JBQXdCLEVBQ3hCLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxtQkFBbUIsRUFDaEMsZ0JBQWdCLENBQUMsWUFBWSxDQUM5QixDQUFDO0lBQ0YsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFFdkM7Ozs7O09BS0c7SUFDSCxnRkFBZ0Y7SUFDaEYsMkZBQTJGO0lBQzNGLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLENBQy9CO1FBQ0UsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsb0JBQW9CO1FBQ25ELEdBQUcsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLG9CQUFvQjtRQUNuRCxhQUFhO1FBQ2IsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMscUJBQXFCO1FBQ3BELEdBQUcsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLHFCQUFxQjtRQUNwRCxnQkFBZ0I7UUFDaEIsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsbUJBQW1CO1FBQ2xELHNEQUFzRDtRQUN0RCxHQUFHLG1CQUFtQixDQUFDLE9BQU87S0FDL0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FDN0IsQ0FBQztJQUVGLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFDLGVBQWUsQ0FBQztTQUM3QyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDaEQsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7U0FDbEMsS0FBSyxFQUFFLENBQUM7SUFFWCw4RUFBOEU7SUFDOUUsTUFBTSxhQUFhLEdBQUcsQ0FBQyxDQUFDLGVBQWUsQ0FBQztTQUNyQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztTQUM5QixLQUFLLEVBQUUsQ0FBQztJQUVYLE1BQU0sYUFBYSxHQUFHLENBQUMsQ0FBQyxlQUFlLENBQUM7U0FDckMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7U0FDOUIsS0FBSyxFQUFFLENBQUM7SUFFWCxpR0FBaUc7SUFDakcsTUFBTSxZQUFZLEdBQXFCLEVBQUUsQ0FBQztJQUMxQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxjQUFjLEVBQUUsRUFBRTtRQUMvQyxNQUFNLGNBQWMsR0FBRyxhQUFhLENBQUMsSUFBSSxDQUN2QyxDQUFDLElBQUksRUFBRSxFQUFFLENBQ1AsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDekMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDN0MsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUU7Z0JBQ3pDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQ2hELENBQUM7UUFFRixJQUFJLGNBQWMsRUFBRTtZQUNsQixJQUFJLGNBQWMsQ0FBQyxVQUFVLEdBQUcsY0FBYyxDQUFDLE1BQU0sRUFBRTtnQkFDckQsR0FBRyxDQUFDLElBQUksQ0FDTjtvQkFDRSxNQUFNLEVBQUUsY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFFO29CQUNoQyxNQUFNLEVBQUUsY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFFO29CQUNoQyxZQUFZLEVBQUUsY0FBYyxDQUFDLFVBQVU7b0JBQ3ZDLFFBQVEsRUFBRSxjQUFjLENBQUMsTUFBTTtpQkFDaEMsRUFDRCxxRkFBcUYsQ0FDdEYsQ0FBQztnQkFDRixZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO2FBQ25DO1NBQ0Y7YUFBTTtZQUNMLEdBQUcsQ0FBQyxJQUFJLENBQ047Z0JBQ0UsTUFBTSxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDaEMsTUFBTSxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDaEMsWUFBWSxFQUFFLGNBQWMsQ0FBQyxVQUFVO2FBQ3hDLEVBQ0QsOERBQThELENBQy9ELENBQUM7WUFDRixZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1NBQ25DO1FBRUQsTUFBTSxjQUFjLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FDdkMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUNQLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ3pDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLGNBQWMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQzdDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFFO2dCQUN6QyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUNoRCxDQUFDO1FBRUYsSUFBSSxjQUFjLEVBQUU7WUFDbEIsSUFBSSxjQUFjLENBQUMsVUFBVSxHQUFHLGNBQWMsQ0FBQyxNQUFNLEVBQUU7Z0JBQ3JELEdBQUcsQ0FBQyxJQUFJLENBQ047b0JBQ0UsTUFBTSxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsRUFBRTtvQkFDaEMsTUFBTSxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsRUFBRTtvQkFDaEMsWUFBWSxFQUFFLGNBQWMsQ0FBQyxVQUFVO29CQUN2QyxRQUFRLEVBQUUsY0FBYyxDQUFDLE1BQU07aUJBQ2hDLEVBQ0QscUZBQXFGLENBQ3RGLENBQUM7Z0JBQ0YsWUFBWSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQzthQUNuQztTQUNGO2FBQU07WUFDTCxHQUFHLENBQUMsSUFBSSxDQUNOO2dCQUNFLE1BQU0sRUFBRSxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUU7Z0JBQ2hDLE1BQU0sRUFBRSxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUU7Z0JBQ2hDLFlBQVksRUFBRSxjQUFjLENBQUMsVUFBVTthQUN4QyxFQUNELDhEQUE4RCxDQUMvRCxDQUFDO1lBQ0YsWUFBWSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztTQUNuQztJQUNILENBQUMsQ0FBQyxDQUFDO0lBRUgsR0FBRyxDQUFDLElBQUksQ0FDTixZQUFZLENBQUMsTUFBTSxFQUNuQix1REFBdUQsQ0FDeEQsQ0FBQztJQUVGLE1BQU0sYUFBYSxHQUNqQixDQUFDLEdBQUcsWUFBWSxFQUFFLEdBQUcsYUFBYSxFQUFFLEdBQUcsYUFBYSxDQUFDLENBQUM7SUFFeEQsTUFBTSxjQUFjLEdBQUcsQ0FBQyxDQUFDLGFBQWEsQ0FBQztTQUNwQyxPQUFPLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUMzRSxPQUFPLEVBQUU7U0FDVCxJQUFJLEVBQUU7U0FDTixLQUFLLEVBQUUsQ0FBQztJQUVYLEdBQUcsQ0FBQyxJQUFJLENBQ04sZUFBZSxjQUFjLENBQUMsTUFBTSxzQkFBc0IsYUFBYSxDQUFDLE1BQU0sMkJBQTJCLENBQzFHLENBQUM7SUFFRixNQUFNLGFBQWEsR0FBRyxNQUFNLGFBQWEsQ0FBQyxTQUFTLENBQ2pELGNBQWMsRUFDZCxhQUFhLENBQ2QsQ0FBQztJQUVGLE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBRzNCLGFBQWEsRUFBRSxDQUFDLFlBQVksRUFBRSxFQUFFO1FBQ2hDLHdIQUF3SDtRQUN4SCxNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUNyRCxDQUFDLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQztZQUN4QixDQUFDLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUQsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDckQsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUM7WUFDeEIsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzVELElBQUksR0FBYyxDQUFDO1FBQ25CLElBQUk7WUFDRixHQUFHLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNwQztRQUFDLE9BQU8sR0FBRyxFQUFFO1lBQ1osR0FBRyxDQUFDLElBQUksQ0FDTixFQUFFLFlBQVksRUFBRSxFQUNoQiwrQkFBK0IsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksWUFBWSxDQUFDLE9BQU8sSUFBSSxZQUFZLENBQUMsV0FBVyxJQUFJLFlBQVksQ0FBQyxLQUFLLGlDQUFpQyxDQUMzTCxDQUFDO1lBQ0YsT0FBTyxTQUFTLENBQUM7U0FDbEI7UUFFRCxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ3RCLEdBQUcsQ0FBQyxJQUFJLENBQ04sK0JBQStCLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFDN0UsSUFBSSxHQUFHLElBQUksWUFBWSxDQUFDLFdBQVcsSUFBSSxZQUFZLENBQUMsS0FBSyxZQUFZLE1BQU0sQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFDM0gsOEJBQThCLENBQy9CLENBQUM7WUFDRixPQUFPLFNBQVMsQ0FBQztTQUNsQjtRQUVELE9BQU87WUFDTCxNQUFNO1lBQ04sTUFBTTtZQUNOLEdBQUc7WUFDSCxNQUFNLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQztZQUNoQyxZQUFZLENBQUMsS0FBSztTQUNuQixDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7SUFFSCxNQUFNLFlBQVksR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBRWhELE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBRzNCLGFBQWEsRUFBRSxDQUFDLFlBQVksRUFBRSxFQUFFO1FBQ2hDLE1BQU0sTUFBTSxHQUFHLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sTUFBTSxHQUFHLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksR0FBYyxDQUFDO1FBQ25CLElBQUk7WUFDRixHQUFHLEdBQUcsY0FBYyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUM1QztRQUFDLE9BQU8sR0FBRyxFQUFFO1lBQ1osR0FBRyxDQUFDLElBQUksQ0FDTixFQUFFLFlBQVksRUFBRSxFQUNoQiwrQkFBK0IsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksWUFBWSxDQUFDLE9BQU8saUNBQWlDLENBQ3pJLENBQUM7WUFDRixPQUFPLFNBQVMsQ0FBQztTQUNsQjtRQUVELElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDdEIsR0FBRyxDQUFDLElBQUksQ0FDTiwrQkFBK0IsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUM3RSxJQUFJLEdBQUcsWUFBWSxNQUFNLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQ3pFLDhCQUE4QixDQUMvQixDQUFDO1lBQ0YsT0FBTyxTQUFTLENBQUM7U0FDbEI7UUFFRCxPQUFPLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMvQixDQUFDLENBQUMsQ0FBQztJQUVILE1BQU0sWUFBWSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUM7SUFFaEQsTUFBTSxlQUFlLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FDM0IsWUFBWSxFQUNaLENBQUMsWUFBWSxFQUFFLEVBQUU7UUFDZixNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN2RSxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUV2RSxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ3RCLEdBQUcsQ0FBQyxJQUFJLENBQ04sK0JBQStCLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLENBQ2xGLENBQUM7WUFDRixPQUFPLFNBQVMsQ0FBQztTQUNsQjtRQUVELE9BQU8sQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDMUIsQ0FBQyxDQUNGLENBQUM7SUFFRixNQUFNLFlBQVksR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBRWhELE1BQU0sQ0FBQyxTQUFTLENBQ2Qsc0JBQXNCLEVBQ3RCLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxtQkFBbUIsRUFDaEMsZ0JBQWdCLENBQUMsWUFBWSxDQUM5QixDQUFDO0lBRUYsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBRW5DLE1BQU0sQ0FBQyxjQUFjLEVBQUUsY0FBYyxFQUFFLGNBQWMsQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztRQUN6RSxjQUFjLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxhQUFhLENBQUM7UUFDcEQsY0FBYyxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsYUFBYSxDQUFDO1FBQ3BELGNBQWMsQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLGFBQWEsQ0FBQztLQUNyRCxDQUFDLENBQUM7SUFFSCxNQUFNLENBQUMsU0FBUyxDQUNkLGdCQUFnQixFQUNoQixJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsZUFBZSxFQUM1QixnQkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7SUFFRixrSEFBa0g7SUFDbEgsd0ZBQXdGO0lBQ3hGLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxHQUFtQyxFQUFFLEVBQUU7UUFDcEUsT0FBTztZQUNMLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQzlCLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUNwRTtZQUNELEdBQUcsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQztZQUNuQyxHQUFHLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUM7U0FDcEMsQ0FBQztJQUNKLENBQUMsQ0FBQztJQUVGLE1BQU0sZ0JBQWdCLEdBQXNDO1FBQzFELFFBQVEsRUFBRSxRQUFRLENBQUMsS0FBSztRQUN4QixVQUFVLEVBQUU7WUFDVixvQkFBb0IsRUFBRSxxQkFBcUIsQ0FBQyxzQkFBc0IsQ0FBQztZQUNuRSxxQkFBcUIsRUFBRSxxQkFBcUIsQ0FBQyx1QkFBdUIsQ0FBQztZQUNyRSxtQkFBbUIsRUFBRSxxQkFBcUIsQ0FBQyxxQkFBcUIsQ0FBQztZQUNqRSxzQkFBc0IsRUFBRSxxQkFBcUIsQ0FBQyx3QkFBd0IsQ0FBQztZQUN2RSxRQUFRLEVBQUUscUJBQXFCLENBQUMsVUFBVSxDQUFDO1lBQzNDLG9CQUFvQixFQUFFLHFCQUFxQixDQUFDLHNCQUFzQixDQUFDO1lBQ25FLHFCQUFxQixFQUFFLHFCQUFxQixDQUFDLHVCQUF1QixDQUFDO1lBQ3JFLDhCQUE4QixFQUFFLHFCQUFxQixDQUNuRCxnQ0FBZ0MsQ0FDakM7WUFDRCwrQkFBK0IsRUFBRSxxQkFBcUIsQ0FDcEQsaUNBQWlDLENBQ2xDO1NBQ0Y7S0FDRixDQUFDO0lBRUYsT0FBTztRQUNMLGNBQWM7UUFDZCxjQUFjO1FBQ2QsY0FBYztRQUNkLGNBQWMsRUFBRSxnQkFBZ0I7UUFDaEMsYUFBYTtLQUNkLENBQUM7QUFDSixDQUFDIn0=