@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,1677 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AlphaRouter = exports.LowerCaseStringArray = exports.MapWithLowerCaseKey = void 0;
7
+ const bignumber_1 = require("@ethersproject/bignumber");
8
+ const providers_1 = require("@ethersproject/providers");
9
+ const default_token_list_1 = __importDefault(require("@uniswap/default-token-list"));
10
+ const router_sdk_1 = require("@juiceswapxyz/router-sdk");
11
+ const sdk_core_1 = require("@juiceswapxyz/sdk-core");
12
+ const universal_router_sdk_1 = require("@juiceswapxyz/universal-router-sdk");
13
+ const v2_sdk_1 = require("@juiceswapxyz/v2-sdk");
14
+ const v3_sdk_1 = require("@juiceswapxyz/v3-sdk");
15
+ const v4_sdk_1 = require("@juiceswapxyz/v4-sdk");
16
+ const async_retry_1 = __importDefault(require("async-retry"));
17
+ const jsbi_1 = __importDefault(require("jsbi"));
18
+ const lodash_1 = __importDefault(require("lodash"));
19
+ const node_cache_1 = __importDefault(require("node-cache"));
20
+ const providers_2 = require("../../providers");
21
+ const caching_token_list_provider_1 = require("../../providers/caching-token-list-provider");
22
+ const portion_provider_1 = require("../../providers/portion-provider");
23
+ const token_fee_fetcher_1 = require("../../providers/token-fee-fetcher");
24
+ const token_provider_1 = require("../../providers/token-provider");
25
+ const token_validator_provider_1 = require("../../providers/token-validator-provider");
26
+ const pool_provider_1 = require("../../providers/v2/pool-provider");
27
+ const gas_data_provider_1 = require("../../providers/v3/gas-data-provider");
28
+ const pool_provider_2 = require("../../providers/v3/pool-provider");
29
+ const caching_pool_provider_1 = require("../../providers/v4/caching-pool-provider");
30
+ const pool_provider_3 = require("../../providers/v4/pool-provider");
31
+ const Erc20__factory_1 = require("../../types/other/factories/Erc20__factory");
32
+ const util_1 = require("../../util");
33
+ const amounts_1 = require("../../util/amounts");
34
+ const chains_1 = require("../../util/chains");
35
+ const defaultBlocksToLive_1 = require("../../util/defaultBlocksToLive");
36
+ const gas_factory_helpers_1 = require("../../util/gas-factory-helpers");
37
+ const intent_1 = require("../../util/intent");
38
+ const log_1 = require("../../util/log");
39
+ const methodParameters_1 = require("../../util/methodParameters");
40
+ const metric_1 = require("../../util/metric");
41
+ const onchainQuoteProviderConfigs_1 = require("../../util/onchainQuoteProviderConfigs");
42
+ const serializeRouteIds_1 = require("../../util/serializeRouteIds");
43
+ const unsupported_tokens_1 = require("../../util/unsupported-tokens");
44
+ const router_1 = require("../router");
45
+ const config_1 = require("./config");
46
+ const best_swap_route_1 = require("./functions/best-swap-route");
47
+ const calculate_ratio_amount_in_1 = require("./functions/calculate-ratio-amount-in");
48
+ const get_candidate_pools_1 = require("./functions/get-candidate-pools");
49
+ const gas_costs_1 = require("./gas-models/gas-costs");
50
+ const mixed_route_heuristic_gas_model_1 = require("./gas-models/mixedRoute/mixed-route-heuristic-gas-model");
51
+ const v2_heuristic_gas_model_1 = require("./gas-models/v2/v2-heuristic-gas-model");
52
+ const v3_heuristic_gas_model_1 = require("./gas-models/v3/v3-heuristic-gas-model");
53
+ const v4_heuristic_gas_model_1 = require("./gas-models/v4/v4-heuristic-gas-model");
54
+ const quoters_1 = require("./quoters");
55
+ const v4_quoter_1 = require("./quoters/v4-quoter");
56
+ class MapWithLowerCaseKey extends Map {
57
+ set(key, value) {
58
+ return super.set(key.toLowerCase(), value);
59
+ }
60
+ }
61
+ exports.MapWithLowerCaseKey = MapWithLowerCaseKey;
62
+ class LowerCaseStringArray extends Array {
63
+ constructor(...items) {
64
+ // Convert all items to lowercase before calling the parent constructor
65
+ super(...items.map((item) => item.toLowerCase()));
66
+ }
67
+ }
68
+ exports.LowerCaseStringArray = LowerCaseStringArray;
69
+ class AlphaRouter {
70
+ constructor({ chainId, provider, multicall2Provider, v4SubgraphProvider, v4PoolProvider, v3PoolProvider, onChainQuoteProvider, v2PoolProvider, v2QuoteProvider, v2SubgraphProvider, tokenProvider, blockedTokenListProvider, v3SubgraphProvider, gasPriceProvider, v4GasModelFactory, v3GasModelFactory, v2GasModelFactory, mixedRouteGasModelFactory, swapRouterProvider, tokenValidatorProvider, arbitrumGasDataProvider, simulator, routeCachingProvider, tokenPropertiesProvider, portionProvider, v2Supported, v4Supported, mixedSupported, mixedCrossLiquidityV3AgainstV4Supported, v4PoolParams, cachedRoutesCacheInvalidationFixRolloutPercentage, deleteCacheEnabledChains, }) {
71
+ this.chainId = chainId;
72
+ this.provider = provider;
73
+ this.multicall2Provider =
74
+ multicall2Provider !== null && multicall2Provider !== void 0 ? multicall2Provider : new providers_2.UniswapMulticallProvider(chainId, provider, 375000);
75
+ this.v4PoolProvider =
76
+ v4PoolProvider !== null && v4PoolProvider !== void 0 ? v4PoolProvider : new caching_pool_provider_1.CachingV4PoolProvider(this.chainId, new pool_provider_3.V4PoolProvider((0, chains_1.ID_TO_CHAIN_ID)(chainId), this.multicall2Provider), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 360, useClones: false })));
77
+ this.v3PoolProvider =
78
+ v3PoolProvider !== null && v3PoolProvider !== void 0 ? v3PoolProvider : new providers_2.CachingV3PoolProvider(this.chainId, new pool_provider_2.V3PoolProvider((0, chains_1.ID_TO_CHAIN_ID)(chainId), this.multicall2Provider), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 360, useClones: false })));
79
+ this.simulator = simulator;
80
+ this.routeCachingProvider = routeCachingProvider;
81
+ if (onChainQuoteProvider) {
82
+ this.onChainQuoteProvider = onChainQuoteProvider;
83
+ }
84
+ else {
85
+ switch (chainId) {
86
+ case sdk_core_1.ChainId.OPTIMISM:
87
+ case sdk_core_1.ChainId.OPTIMISM_GOERLI:
88
+ case sdk_core_1.ChainId.OPTIMISM_SEPOLIA:
89
+ this.onChainQuoteProvider = new providers_2.OnChainQuoteProvider(chainId, provider, this.multicall2Provider, {
90
+ retries: 2,
91
+ minTimeout: 100,
92
+ maxTimeout: 1000,
93
+ }, (_) => {
94
+ return {
95
+ multicallChunk: 110,
96
+ gasLimitPerCall: 1200000,
97
+ quoteMinSuccessRate: 0.1,
98
+ };
99
+ }, (_) => {
100
+ return {
101
+ gasLimitOverride: 3000000,
102
+ multicallChunk: 45,
103
+ };
104
+ }, (_) => {
105
+ return {
106
+ gasLimitOverride: 3000000,
107
+ multicallChunk: 45,
108
+ };
109
+ }, (_) => {
110
+ return {
111
+ baseBlockOffset: -10,
112
+ rollback: {
113
+ enabled: true,
114
+ attemptsBeforeRollback: 1,
115
+ rollbackBlockOffset: -10,
116
+ },
117
+ };
118
+ });
119
+ break;
120
+ case sdk_core_1.ChainId.BASE:
121
+ case sdk_core_1.ChainId.BLAST:
122
+ case sdk_core_1.ChainId.ZORA:
123
+ case sdk_core_1.ChainId.WORLDCHAIN:
124
+ case sdk_core_1.ChainId.UNICHAIN_SEPOLIA:
125
+ case sdk_core_1.ChainId.MONAD_TESTNET:
126
+ case sdk_core_1.ChainId.BASE_SEPOLIA:
127
+ case sdk_core_1.ChainId.UNICHAIN:
128
+ case sdk_core_1.ChainId.BASE_GOERLI:
129
+ case sdk_core_1.ChainId.SONEIUM:
130
+ this.onChainQuoteProvider = new providers_2.OnChainQuoteProvider(chainId, provider, this.multicall2Provider, {
131
+ retries: 2,
132
+ minTimeout: 100,
133
+ maxTimeout: 1000,
134
+ }, (_) => {
135
+ return {
136
+ multicallChunk: 80,
137
+ gasLimitPerCall: 1200000,
138
+ quoteMinSuccessRate: 0.1,
139
+ };
140
+ }, (_) => {
141
+ return {
142
+ gasLimitOverride: 3000000,
143
+ multicallChunk: 45,
144
+ };
145
+ }, (_) => {
146
+ return {
147
+ gasLimitOverride: 3000000,
148
+ multicallChunk: 45,
149
+ };
150
+ }, (_) => {
151
+ return {
152
+ baseBlockOffset: -10,
153
+ rollback: {
154
+ enabled: true,
155
+ attemptsBeforeRollback: 1,
156
+ rollbackBlockOffset: -10,
157
+ },
158
+ };
159
+ });
160
+ break;
161
+ case sdk_core_1.ChainId.ZKSYNC:
162
+ this.onChainQuoteProvider = new providers_2.OnChainQuoteProvider(chainId, provider, this.multicall2Provider, {
163
+ retries: 2,
164
+ minTimeout: 100,
165
+ maxTimeout: 1000,
166
+ }, (_) => {
167
+ return {
168
+ multicallChunk: 27,
169
+ gasLimitPerCall: 3000000,
170
+ quoteMinSuccessRate: 0.1,
171
+ };
172
+ }, (_) => {
173
+ return {
174
+ gasLimitOverride: 6000000,
175
+ multicallChunk: 13,
176
+ };
177
+ }, (_) => {
178
+ return {
179
+ gasLimitOverride: 6000000,
180
+ multicallChunk: 13,
181
+ };
182
+ }, (_) => {
183
+ return {
184
+ baseBlockOffset: -10,
185
+ rollback: {
186
+ enabled: true,
187
+ attemptsBeforeRollback: 1,
188
+ rollbackBlockOffset: -10,
189
+ },
190
+ };
191
+ });
192
+ break;
193
+ case sdk_core_1.ChainId.ARBITRUM_ONE:
194
+ case sdk_core_1.ChainId.ARBITRUM_GOERLI:
195
+ case sdk_core_1.ChainId.ARBITRUM_SEPOLIA:
196
+ this.onChainQuoteProvider = new providers_2.OnChainQuoteProvider(chainId, provider, this.multicall2Provider, {
197
+ retries: 2,
198
+ minTimeout: 100,
199
+ maxTimeout: 1000,
200
+ }, (_) => {
201
+ return {
202
+ multicallChunk: 10,
203
+ gasLimitPerCall: 12000000,
204
+ quoteMinSuccessRate: 0.1,
205
+ };
206
+ }, (_) => {
207
+ return {
208
+ gasLimitOverride: 30000000,
209
+ multicallChunk: 6,
210
+ };
211
+ }, (_) => {
212
+ return {
213
+ gasLimitOverride: 30000000,
214
+ multicallChunk: 6,
215
+ };
216
+ });
217
+ break;
218
+ case sdk_core_1.ChainId.CELO:
219
+ case sdk_core_1.ChainId.CELO_ALFAJORES:
220
+ this.onChainQuoteProvider = new providers_2.OnChainQuoteProvider(chainId, provider, this.multicall2Provider, {
221
+ retries: 2,
222
+ minTimeout: 100,
223
+ maxTimeout: 1000,
224
+ }, (_) => {
225
+ return {
226
+ multicallChunk: 10,
227
+ gasLimitPerCall: 5000000,
228
+ quoteMinSuccessRate: 0.1,
229
+ };
230
+ }, (_) => {
231
+ return {
232
+ gasLimitOverride: 5000000,
233
+ multicallChunk: 5,
234
+ };
235
+ }, (_) => {
236
+ return {
237
+ gasLimitOverride: 6250000,
238
+ multicallChunk: 4,
239
+ };
240
+ });
241
+ break;
242
+ case sdk_core_1.ChainId.POLYGON_MUMBAI:
243
+ case sdk_core_1.ChainId.SEPOLIA:
244
+ case sdk_core_1.ChainId.MAINNET:
245
+ case sdk_core_1.ChainId.POLYGON:
246
+ this.onChainQuoteProvider = new providers_2.OnChainQuoteProvider(chainId, provider, this.multicall2Provider, onchainQuoteProviderConfigs_1.RETRY_OPTIONS[chainId], (_) => onchainQuoteProviderConfigs_1.BATCH_PARAMS[chainId], (_) => onchainQuoteProviderConfigs_1.GAS_ERROR_FAILURE_OVERRIDES[chainId], (_) => onchainQuoteProviderConfigs_1.SUCCESS_RATE_FAILURE_OVERRIDES[chainId], (_) => onchainQuoteProviderConfigs_1.BLOCK_NUMBER_CONFIGS[chainId]);
247
+ break;
248
+ default:
249
+ this.onChainQuoteProvider = new providers_2.OnChainQuoteProvider(chainId, provider, this.multicall2Provider, onchainQuoteProviderConfigs_1.DEFAULT_RETRY_OPTIONS, (_) => onchainQuoteProviderConfigs_1.DEFAULT_BATCH_PARAMS, (_) => onchainQuoteProviderConfigs_1.DEFAULT_GAS_ERROR_FAILURE_OVERRIDES, (_) => onchainQuoteProviderConfigs_1.DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES, (_) => onchainQuoteProviderConfigs_1.DEFAULT_BLOCK_NUMBER_CONFIGS);
250
+ break;
251
+ }
252
+ }
253
+ if (tokenValidatorProvider) {
254
+ this.tokenValidatorProvider = tokenValidatorProvider;
255
+ }
256
+ else if (this.chainId === sdk_core_1.ChainId.MAINNET) {
257
+ this.tokenValidatorProvider = new token_validator_provider_1.TokenValidatorProvider(this.chainId, this.multicall2Provider, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 30000, useClones: false })));
258
+ }
259
+ if (tokenPropertiesProvider) {
260
+ this.tokenPropertiesProvider = tokenPropertiesProvider;
261
+ }
262
+ else {
263
+ this.tokenPropertiesProvider = new providers_2.TokenPropertiesProvider(this.chainId, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 86400, useClones: false })), new token_fee_fetcher_1.OnChainTokenFeeFetcher(this.chainId, provider));
264
+ }
265
+ this.v2PoolProvider =
266
+ v2PoolProvider !== null && v2PoolProvider !== void 0 ? v2PoolProvider : new providers_2.CachingV2PoolProvider(chainId, new pool_provider_1.V2PoolProvider(chainId, this.multicall2Provider, this.tokenPropertiesProvider), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 60, useClones: false })));
267
+ this.v2QuoteProvider = v2QuoteProvider !== null && v2QuoteProvider !== void 0 ? v2QuoteProvider : new providers_2.V2QuoteProvider();
268
+ this.blockedTokenListProvider =
269
+ blockedTokenListProvider !== null && blockedTokenListProvider !== void 0 ? blockedTokenListProvider : new caching_token_list_provider_1.CachingTokenListProvider(chainId, unsupported_tokens_1.UNSUPPORTED_TOKENS, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 3600, useClones: false })));
270
+ this.tokenProvider =
271
+ tokenProvider !== null && tokenProvider !== void 0 ? tokenProvider : new providers_2.CachingTokenProviderWithFallback(chainId, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 3600, useClones: false })), new caching_token_list_provider_1.CachingTokenListProvider(chainId, default_token_list_1.default, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 3600, useClones: false }))), new token_provider_1.TokenProvider(chainId, this.multicall2Provider));
272
+ this.portionProvider = portionProvider !== null && portionProvider !== void 0 ? portionProvider : new portion_provider_1.PortionProvider();
273
+ const chainName = (0, chains_1.ID_TO_NETWORK_NAME)(chainId);
274
+ // ipfs urls in the following format: `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/${protocol}/${chainName}.json`;
275
+ if (v2SubgraphProvider) {
276
+ this.v2SubgraphProvider = v2SubgraphProvider;
277
+ }
278
+ else {
279
+ this.v2SubgraphProvider = new providers_2.V2SubgraphProviderWithFallBacks([
280
+ new providers_2.CachingV2SubgraphProvider(chainId, new providers_2.URISubgraphProvider(chainId, `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v2/${chainName}.json`, undefined, 0), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 300, useClones: false }))),
281
+ new providers_2.StaticV2SubgraphProvider(chainId),
282
+ ]);
283
+ }
284
+ if (v3SubgraphProvider) {
285
+ this.v3SubgraphProvider = v3SubgraphProvider;
286
+ }
287
+ else {
288
+ this.v3SubgraphProvider = new providers_2.V3SubgraphProviderWithFallBacks([
289
+ new providers_2.CachingV3SubgraphProvider(chainId, new providers_2.URISubgraphProvider(chainId, `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v3/${chainName}.json`, undefined, 0), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 300, useClones: false }))),
290
+ new providers_2.StaticV3SubgraphProvider(chainId, this.v3PoolProvider),
291
+ ]);
292
+ }
293
+ this.v4PoolParams =
294
+ v4PoolParams !== null && v4PoolParams !== void 0 ? v4PoolParams : (0, util_1.getApplicableV4FeesTickspacingsHooks)(chainId);
295
+ if (v4SubgraphProvider) {
296
+ this.v4SubgraphProvider = v4SubgraphProvider;
297
+ }
298
+ else {
299
+ this.v4SubgraphProvider = new providers_2.V4SubgraphProviderWithFallBacks([
300
+ new providers_2.CachingV4SubgraphProvider(chainId, new providers_2.URISubgraphProvider(chainId, `https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v4/${chainName}.json`, undefined, 0), new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 300, useClones: false }))),
301
+ new providers_2.StaticV4SubgraphProvider(chainId, this.v4PoolProvider, this.v4PoolParams),
302
+ ]);
303
+ }
304
+ let gasPriceProviderInstance;
305
+ if (providers_1.JsonRpcProvider.isProvider(this.provider)) {
306
+ gasPriceProviderInstance = new providers_2.OnChainGasPriceProvider(chainId, new providers_2.EIP1559GasPriceProvider(this.provider), new providers_2.LegacyGasPriceProvider(this.provider));
307
+ }
308
+ else {
309
+ gasPriceProviderInstance = new providers_2.ETHGasStationInfoProvider(config_1.ETH_GAS_STATION_API_URL);
310
+ }
311
+ this.gasPriceProvider =
312
+ gasPriceProvider !== null && gasPriceProvider !== void 0 ? gasPriceProvider : new providers_2.CachingGasStationProvider(chainId, gasPriceProviderInstance, new providers_2.NodeJSCache(new node_cache_1.default({ stdTTL: 7, useClones: false })));
313
+ this.v4GasModelFactory =
314
+ v4GasModelFactory !== null && v4GasModelFactory !== void 0 ? v4GasModelFactory : new v4_heuristic_gas_model_1.V4HeuristicGasModelFactory(this.provider);
315
+ this.v3GasModelFactory =
316
+ v3GasModelFactory !== null && v3GasModelFactory !== void 0 ? v3GasModelFactory : new v3_heuristic_gas_model_1.V3HeuristicGasModelFactory(this.provider);
317
+ this.v2GasModelFactory =
318
+ v2GasModelFactory !== null && v2GasModelFactory !== void 0 ? v2GasModelFactory : new v2_heuristic_gas_model_1.V2HeuristicGasModelFactory(this.provider);
319
+ this.mixedRouteGasModelFactory =
320
+ mixedRouteGasModelFactory !== null && mixedRouteGasModelFactory !== void 0 ? mixedRouteGasModelFactory : new mixed_route_heuristic_gas_model_1.MixedRouteHeuristicGasModelFactory();
321
+ this.swapRouterProvider =
322
+ swapRouterProvider !== null && swapRouterProvider !== void 0 ? swapRouterProvider : new providers_2.SwapRouterProvider(this.multicall2Provider, this.chainId);
323
+ if (chainId === sdk_core_1.ChainId.ARBITRUM_ONE ||
324
+ chainId === sdk_core_1.ChainId.ARBITRUM_GOERLI) {
325
+ this.l2GasDataProvider =
326
+ arbitrumGasDataProvider !== null && arbitrumGasDataProvider !== void 0 ? arbitrumGasDataProvider : new gas_data_provider_1.ArbitrumGasDataProvider(chainId, this.provider);
327
+ }
328
+ // Initialize the Quoters.
329
+ // Quoters are an abstraction encapsulating the business logic of fetching routes and quotes.
330
+ this.v2Quoter = new quoters_1.V2Quoter(this.v2SubgraphProvider, this.v2PoolProvider, this.v2QuoteProvider, this.v2GasModelFactory, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider, this.l2GasDataProvider);
331
+ this.v3Quoter = new quoters_1.V3Quoter(this.v3SubgraphProvider, this.v3PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
332
+ this.v4Quoter = new v4_quoter_1.V4Quoter(this.v4SubgraphProvider, this.v4PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
333
+ this.mixedQuoter = new quoters_1.MixedQuoter(this.v4SubgraphProvider, this.v4PoolProvider, this.v3SubgraphProvider, this.v3PoolProvider, this.v2SubgraphProvider, this.v2PoolProvider, this.onChainQuoteProvider, this.tokenProvider, this.chainId, this.blockedTokenListProvider, this.tokenValidatorProvider);
334
+ this.v2Supported = v2Supported !== null && v2Supported !== void 0 ? v2Supported : chains_1.V2_SUPPORTED;
335
+ this.v4Supported = v4Supported !== null && v4Supported !== void 0 ? v4Supported : util_1.V4_SUPPORTED;
336
+ this.mixedSupported = mixedSupported !== null && mixedSupported !== void 0 ? mixedSupported : util_1.MIXED_SUPPORTED;
337
+ this.mixedCrossLiquidityV3AgainstV4Supported =
338
+ mixedCrossLiquidityV3AgainstV4Supported !== null && mixedCrossLiquidityV3AgainstV4Supported !== void 0 ? mixedCrossLiquidityV3AgainstV4Supported : util_1.MIXED_CROSS_LIQUIDITY_V3_AGAINST_V4_SUPPORTED;
339
+ this.cachedRoutesCacheInvalidationFixRolloutPercentage =
340
+ cachedRoutesCacheInvalidationFixRolloutPercentage;
341
+ // https://linear.app/uniswap/issue/ROUTE-467/tenderly-simulation-during-caching-lambda
342
+ this.deleteCacheEnabledChains = deleteCacheEnabledChains;
343
+ }
344
+ async routeToRatio(token0Balance, token1Balance, position, swapAndAddConfig, swapAndAddOptions, routingConfig = (0, config_1.DEFAULT_ROUTING_CONFIG_BY_CHAIN)(this.chainId)) {
345
+ if (token1Balance.currency.wrapped.sortsBefore(token0Balance.currency.wrapped)) {
346
+ [token0Balance, token1Balance] = [token1Balance, token0Balance];
347
+ }
348
+ let preSwapOptimalRatio = this.calculateOptimalRatio(position, position.pool.sqrtRatioX96, true);
349
+ // set up parameters according to which token will be swapped
350
+ let zeroForOne;
351
+ if (position.pool.tickCurrent > position.tickUpper) {
352
+ zeroForOne = true;
353
+ }
354
+ else if (position.pool.tickCurrent < position.tickLower) {
355
+ zeroForOne = false;
356
+ }
357
+ else {
358
+ zeroForOne = new sdk_core_1.Fraction(token0Balance.quotient, token1Balance.quotient).greaterThan(preSwapOptimalRatio);
359
+ if (!zeroForOne)
360
+ preSwapOptimalRatio = preSwapOptimalRatio.invert();
361
+ }
362
+ const [inputBalance, outputBalance] = zeroForOne
363
+ ? [token0Balance, token1Balance]
364
+ : [token1Balance, token0Balance];
365
+ let optimalRatio = preSwapOptimalRatio;
366
+ let postSwapTargetPool = position.pool;
367
+ let exchangeRate = zeroForOne
368
+ ? position.pool.token0Price
369
+ : position.pool.token1Price;
370
+ let swap = null;
371
+ let ratioAchieved = false;
372
+ let n = 0;
373
+ // iterate until we find a swap with a sufficient ratio or return null
374
+ while (!ratioAchieved) {
375
+ n++;
376
+ if (n > swapAndAddConfig.maxIterations) {
377
+ log_1.log.info('max iterations exceeded');
378
+ return {
379
+ status: router_1.SwapToRatioStatus.NO_ROUTE_FOUND,
380
+ error: 'max iterations exceeded',
381
+ };
382
+ }
383
+ const amountToSwap = (0, calculate_ratio_amount_in_1.calculateRatioAmountIn)(optimalRatio, exchangeRate, inputBalance, outputBalance);
384
+ if (amountToSwap.equalTo(0)) {
385
+ log_1.log.info(`no swap needed: amountToSwap = 0`);
386
+ return {
387
+ status: router_1.SwapToRatioStatus.NO_SWAP_NEEDED,
388
+ };
389
+ }
390
+ swap = await this.route(amountToSwap, outputBalance.currency, sdk_core_1.TradeType.EXACT_INPUT, undefined, Object.assign(Object.assign(Object.assign({}, (0, config_1.DEFAULT_ROUTING_CONFIG_BY_CHAIN)(this.chainId)), routingConfig), {
391
+ /// @dev We do not want to query for mixedRoutes for routeToRatio as they are not supported
392
+ /// [Protocol.V3, Protocol.V2] will make sure we only query for V3 and V2
393
+ protocols: [router_sdk_1.Protocol.V3, router_sdk_1.Protocol.V2] }));
394
+ if (!swap) {
395
+ log_1.log.info('no route found from this.route()');
396
+ return {
397
+ status: router_1.SwapToRatioStatus.NO_ROUTE_FOUND,
398
+ error: 'no route found',
399
+ };
400
+ }
401
+ const inputBalanceUpdated = inputBalance.subtract(swap.trade.inputAmount);
402
+ const outputBalanceUpdated = outputBalance.add(swap.trade.outputAmount);
403
+ const newRatio = inputBalanceUpdated.divide(outputBalanceUpdated);
404
+ let targetPoolPriceUpdate;
405
+ swap.route.forEach((route) => {
406
+ if (route.protocol === router_sdk_1.Protocol.V3) {
407
+ const v3Route = route;
408
+ v3Route.route.pools.forEach((pool, i) => {
409
+ if (pool.token0.equals(position.pool.token0) &&
410
+ pool.token1.equals(position.pool.token1) &&
411
+ pool.fee === position.pool.fee) {
412
+ targetPoolPriceUpdate = jsbi_1.default.BigInt(v3Route.sqrtPriceX96AfterList[i].toString());
413
+ optimalRatio = this.calculateOptimalRatio(position, jsbi_1.default.BigInt(targetPoolPriceUpdate.toString()), zeroForOne);
414
+ }
415
+ });
416
+ }
417
+ });
418
+ if (!targetPoolPriceUpdate) {
419
+ optimalRatio = preSwapOptimalRatio;
420
+ }
421
+ ratioAchieved =
422
+ newRatio.equalTo(optimalRatio) ||
423
+ this.absoluteValue(newRatio.asFraction.divide(optimalRatio).subtract(1)).lessThan(swapAndAddConfig.ratioErrorTolerance);
424
+ if (ratioAchieved && targetPoolPriceUpdate) {
425
+ postSwapTargetPool = new v3_sdk_1.Pool(position.pool.token0, position.pool.token1, position.pool.fee, targetPoolPriceUpdate, position.pool.liquidity, v3_sdk_1.TickMath.getTickAtSqrtRatio(targetPoolPriceUpdate), position.pool.tickDataProvider);
426
+ }
427
+ exchangeRate = swap.trade.outputAmount.divide(swap.trade.inputAmount);
428
+ log_1.log.info({
429
+ exchangeRate: exchangeRate.asFraction.toFixed(18),
430
+ optimalRatio: optimalRatio.asFraction.toFixed(18),
431
+ newRatio: newRatio.asFraction.toFixed(18),
432
+ inputBalanceUpdated: inputBalanceUpdated.asFraction.toFixed(18),
433
+ outputBalanceUpdated: outputBalanceUpdated.asFraction.toFixed(18),
434
+ ratioErrorTolerance: swapAndAddConfig.ratioErrorTolerance.toFixed(18),
435
+ iterationN: n.toString(),
436
+ }, 'QuoteToRatio Iteration Parameters');
437
+ if (exchangeRate.equalTo(0)) {
438
+ log_1.log.info('exchangeRate to 0');
439
+ return {
440
+ status: router_1.SwapToRatioStatus.NO_ROUTE_FOUND,
441
+ error: 'insufficient liquidity to swap to optimal ratio',
442
+ };
443
+ }
444
+ }
445
+ if (!swap) {
446
+ return {
447
+ status: router_1.SwapToRatioStatus.NO_ROUTE_FOUND,
448
+ error: 'no route found',
449
+ };
450
+ }
451
+ let methodParameters;
452
+ if (swapAndAddOptions) {
453
+ methodParameters = await this.buildSwapAndAddMethodParameters(swap.trade, swapAndAddOptions, {
454
+ initialBalanceTokenIn: inputBalance,
455
+ initialBalanceTokenOut: outputBalance,
456
+ preLiquidityPosition: position,
457
+ });
458
+ }
459
+ return {
460
+ status: router_1.SwapToRatioStatus.SUCCESS,
461
+ result: Object.assign(Object.assign({}, swap), { methodParameters, optimalRatio, postSwapTargetPool }),
462
+ };
463
+ }
464
+ /**
465
+ * @inheritdoc IRouter
466
+ */
467
+ async route(amount, quoteCurrency, tradeType, swapConfig, partialRoutingConfig = {}) {
468
+ var _a, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
469
+ const originalAmount = amount;
470
+ const { currencyIn, currencyOut } = this.determineCurrencyInOutFromTradeType(tradeType, amount, quoteCurrency);
471
+ const tokenOutProperties = await this.tokenPropertiesProvider.getTokensProperties([currencyOut], partialRoutingConfig);
472
+ const feeTakenOnTransfer = (_c = (_a = tokenOutProperties[(0, util_1.getAddressLowerCase)(currencyOut)]) === null || _a === void 0 ? void 0 : _a.tokenFeeResult) === null || _c === void 0 ? void 0 : _c.feeTakenOnTransfer;
473
+ const externalTransferFailed = (_e = (_d = tokenOutProperties[(0, util_1.getAddressLowerCase)(currencyOut)]) === null || _d === void 0 ? void 0 : _d.tokenFeeResult) === null || _e === void 0 ? void 0 : _e.externalTransferFailed;
474
+ // We want to log the fee on transfer output tokens that we are taking fee or not
475
+ // Ideally the trade size (normalized in USD) would be ideal to log here, but we don't have spot price of output tokens here.
476
+ // We have to make sure token out is FOT with either buy/sell fee bps > 0
477
+ if (((_h = (_g = (_f = tokenOutProperties[(0, util_1.getAddressLowerCase)(currencyOut)]) === null || _f === void 0 ? void 0 : _f.tokenFeeResult) === null || _g === void 0 ? void 0 : _g.buyFeeBps) === null || _h === void 0 ? void 0 : _h.gt(0)) ||
478
+ ((_l = (_k = (_j = tokenOutProperties[(0, util_1.getAddressLowerCase)(currencyOut)]) === null || _j === void 0 ? void 0 : _j.tokenFeeResult) === null || _k === void 0 ? void 0 : _k.sellFeeBps) === null || _l === void 0 ? void 0 : _l.gt(0))) {
479
+ if (feeTakenOnTransfer || externalTransferFailed) {
480
+ // also to be extra safe, in case of FOT with feeTakenOnTransfer or externalTransferFailed,
481
+ // we nullify the fee and flat fee to avoid any potential issues.
482
+ // although neither web nor wallet should use the calldata returned from routing/SOR
483
+ if ((swapConfig === null || swapConfig === void 0 ? void 0 : swapConfig.type) === router_1.SwapType.UNIVERSAL_ROUTER) {
484
+ swapConfig.fee = undefined;
485
+ swapConfig.flatFee = undefined;
486
+ }
487
+ metric_1.metric.putMetric('TokenOutFeeOnTransferNotTakingFee', 1, metric_1.MetricLoggerUnit.Count);
488
+ }
489
+ else {
490
+ metric_1.metric.putMetric('TokenOutFeeOnTransferTakingFee', 1, metric_1.MetricLoggerUnit.Count);
491
+ }
492
+ }
493
+ if (tradeType === sdk_core_1.TradeType.EXACT_OUTPUT) {
494
+ const portionAmount = this.portionProvider.getPortionAmount(amount, tradeType, feeTakenOnTransfer, externalTransferFailed, swapConfig);
495
+ if (portionAmount && portionAmount.greaterThan(router_sdk_1.ZERO)) {
496
+ // In case of exact out swap, before we route, we need to make sure that the
497
+ // token out amount accounts for flat portion, and token in amount after the best swap route contains the token in equivalent of portion.
498
+ // In other words, in case a pool's LP fee bps is lower than the portion bps (0.01%/0.05% for v3), a pool can go insolvency.
499
+ // This is because instead of the swapper being responsible for the portion,
500
+ // the pool instead gets responsible for the portion.
501
+ // The addition below avoids that situation.
502
+ amount = amount.add(portionAmount);
503
+ }
504
+ }
505
+ metric_1.metric.setProperty('chainId', this.chainId);
506
+ metric_1.metric.setProperty('pair', `${currencyIn.symbol}/${currencyOut.symbol}`);
507
+ metric_1.metric.setProperty('tokenIn', (0, util_1.getAddress)(currencyIn));
508
+ metric_1.metric.setProperty('tokenOut', (0, util_1.getAddress)(currencyOut));
509
+ metric_1.metric.setProperty('tradeType', tradeType === sdk_core_1.TradeType.EXACT_INPUT ? 'ExactIn' : 'ExactOut');
510
+ metric_1.metric.putMetric(`QuoteRequestedForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
511
+ // Get a block number to specify in all our calls. Ensures data we fetch from chain is
512
+ // from the same block.
513
+ const blockNumber = (_m = partialRoutingConfig.blockNumber) !== null && _m !== void 0 ? _m : this.getBlockNumberPromise();
514
+ const routingConfig = lodash_1.default.merge({
515
+ // These settings could be changed by the partialRoutingConfig
516
+ useCachedRoutes: true,
517
+ writeToCachedRoutes: true,
518
+ optimisticCachedRoutes: false,
519
+ }, (0, config_1.DEFAULT_ROUTING_CONFIG_BY_CHAIN)(this.chainId), partialRoutingConfig, { blockNumber });
520
+ if (routingConfig.debugRouting) {
521
+ log_1.log.warn(`Finalized routing config is ${JSON.stringify(routingConfig)}`);
522
+ }
523
+ const gasPriceWei = await this.getGasPriceWei(await blockNumber, await partialRoutingConfig.blockNumber);
524
+ // const gasTokenAccessor = await this.tokenProvider.getTokens([routingConfig.gasToken!]);
525
+ const gasToken = routingConfig.gasToken
526
+ ? (await this.tokenProvider.getTokens([routingConfig.gasToken])).getTokenByAddress(routingConfig.gasToken)
527
+ : undefined;
528
+ const providerConfig = Object.assign(Object.assign({}, routingConfig), { blockNumber, additionalGasOverhead: (0, gas_costs_1.NATIVE_OVERHEAD)(this.chainId, amount.currency, quoteCurrency), gasToken,
529
+ externalTransferFailed,
530
+ feeTakenOnTransfer });
531
+ const { v2GasModel: v2GasModel, v3GasModel: v3GasModel, v4GasModel: v4GasModel, mixedRouteGasModel: mixedRouteGasModel, } = await this.getGasModels(gasPriceWei, amount.currency.wrapped, quoteCurrency.wrapped, providerConfig);
532
+ // Create a Set to sanitize the protocols input, a Set of undefined becomes an empty set,
533
+ // Then create an Array from the values of that Set.
534
+ const protocols = Array.from(new Set(routingConfig.protocols).values());
535
+ const cacheMode = (_o = routingConfig.overwriteCacheMode) !== null && _o !== void 0 ? _o : (await ((_p = this.routeCachingProvider) === null || _p === void 0 ? void 0 : _p.getCacheMode(this.chainId, amount, quoteCurrency, tradeType, protocols)));
536
+ // Fetch CachedRoutes
537
+ let cachedRoutes;
538
+ // Decide whether to use cached routes or not - If |enabledAndRequestedProtocolsMatch| is true we are good to use cached routes.
539
+ // In order to use cached routes, we need to have all enabled protocols specified in the request.
540
+ // By default, all protocols are enabled but for UniversalRouterVersion.V1_2, V4 is not.
541
+ // - ref: https://github.com/Uniswap/routing-api/blob/663b607d80d9249f85e7ab0925a611ec3701da2a/lib/util/supportedProtocolVersions.ts#L15
542
+ // So we take this into account when deciding whether to use cached routes or not.
543
+ // We only want to use cache if all enabled protocols are specified (V2,V3,V4? + MIXED). In any other case, use onchain path.
544
+ // - Cache is optimized for global search, not for specific protocol(s) search.
545
+ // For legacy systems (SWAP_ROUTER_02) or missing swapConfig, follow UniversalRouterVersion.V1_2 logic.
546
+ const availableProtocolsSet = new Set(Object.values(router_sdk_1.Protocol));
547
+ const requestedProtocolsSet = new Set(protocols);
548
+ const swapRouter = !swapConfig ||
549
+ swapConfig.type === router_1.SwapType.SWAP_ROUTER_02 ||
550
+ (swapConfig.type === router_1.SwapType.UNIVERSAL_ROUTER &&
551
+ swapConfig.version === universal_router_sdk_1.UniversalRouterVersion.V1_2);
552
+ if (swapRouter) {
553
+ availableProtocolsSet.delete(router_sdk_1.Protocol.V4);
554
+ if (requestedProtocolsSet.has(router_sdk_1.Protocol.V4)) {
555
+ requestedProtocolsSet.delete(router_sdk_1.Protocol.V4);
556
+ }
557
+ }
558
+ const enabledAndRequestedProtocolsMatch = availableProtocolsSet.size === requestedProtocolsSet.size &&
559
+ [...availableProtocolsSet].every((protocol) => requestedProtocolsSet.has(protocol));
560
+ // If the requested protocols do not match the enabled protocols, we need to set the hooks options to NO_HOOKS.
561
+ if (!requestedProtocolsSet.has(router_sdk_1.Protocol.V4)) {
562
+ routingConfig.hooksOptions = util_1.HooksOptions.NO_HOOKS;
563
+ }
564
+ // If hooksOptions not specified and it's not a swapRouter (i.e. Universal Router it is),
565
+ // we should also set it to HOOKS_INCLUSIVE, as this is default behavior even without hooksOptions.
566
+ if (!routingConfig.hooksOptions) {
567
+ routingConfig.hooksOptions = util_1.HooksOptions.HOOKS_INCLUSIVE;
568
+ }
569
+ log_1.log.debug('UniversalRouterVersion_CacheGate_Check', {
570
+ availableProtocolsSet: Array.from(availableProtocolsSet),
571
+ requestedProtocolsSet: Array.from(requestedProtocolsSet),
572
+ enabledAndRequestedProtocolsMatch,
573
+ swapConfigType: swapConfig === null || swapConfig === void 0 ? void 0 : swapConfig.type,
574
+ swapConfigUniversalRouterVersion: (swapConfig === null || swapConfig === void 0 ? void 0 : swapConfig.type) === router_1.SwapType.UNIVERSAL_ROUTER
575
+ ? swapConfig === null || swapConfig === void 0 ? void 0 : swapConfig.version
576
+ : 'N/A',
577
+ });
578
+ if (routingConfig.useCachedRoutes &&
579
+ cacheMode !== providers_2.CacheMode.Darkmode &&
580
+ AlphaRouter.isAllowedToEnterCachedRoutes(routingConfig.intent, routingConfig.hooksOptions, swapRouter)) {
581
+ if (enabledAndRequestedProtocolsMatch) {
582
+ if (protocols.includes(router_sdk_1.Protocol.V4) &&
583
+ (currencyIn.isNative || currencyOut.isNative)) {
584
+ const [wrappedNativeCachedRoutes, nativeCachedRoutes] = await Promise.all([
585
+ (_q = this.routeCachingProvider) === null || _q === void 0 ? void 0 : _q.getCachedRoute(this.chainId, amounts_1.CurrencyAmount.fromRawAmount(amount.currency.wrapped, amount.quotient), quoteCurrency.wrapped, tradeType, protocols, await blockNumber, routingConfig.optimisticCachedRoutes, routingConfig, swapConfig),
586
+ (_r = this.routeCachingProvider) === null || _r === void 0 ? void 0 : _r.getCachedRoute(this.chainId, amount, quoteCurrency, tradeType, [router_sdk_1.Protocol.V4], await blockNumber, routingConfig.optimisticCachedRoutes, routingConfig, swapConfig),
587
+ ]);
588
+ if ((wrappedNativeCachedRoutes &&
589
+ (wrappedNativeCachedRoutes === null || wrappedNativeCachedRoutes === void 0 ? void 0 : wrappedNativeCachedRoutes.routes.length) > 0) ||
590
+ (nativeCachedRoutes && (nativeCachedRoutes === null || nativeCachedRoutes === void 0 ? void 0 : nativeCachedRoutes.routes.length) > 0)) {
591
+ cachedRoutes = new providers_2.CachedRoutes({
592
+ routes: [
593
+ ...((_s = nativeCachedRoutes === null || nativeCachedRoutes === void 0 ? void 0 : nativeCachedRoutes.routes) !== null && _s !== void 0 ? _s : []),
594
+ ...((_t = wrappedNativeCachedRoutes === null || wrappedNativeCachedRoutes === void 0 ? void 0 : wrappedNativeCachedRoutes.routes) !== null && _t !== void 0 ? _t : []),
595
+ ],
596
+ chainId: this.chainId,
597
+ currencyIn: currencyIn,
598
+ currencyOut: currencyOut,
599
+ protocolsCovered: protocols,
600
+ blockNumber: await blockNumber,
601
+ tradeType: tradeType,
602
+ originalAmount: (_v = (_u = wrappedNativeCachedRoutes === null || wrappedNativeCachedRoutes === void 0 ? void 0 : wrappedNativeCachedRoutes.originalAmount) !== null && _u !== void 0 ? _u : nativeCachedRoutes === null || nativeCachedRoutes === void 0 ? void 0 : nativeCachedRoutes.originalAmount) !== null && _v !== void 0 ? _v : amount.quotient.toString(),
603
+ blocksToLive: (_x = (_w = wrappedNativeCachedRoutes === null || wrappedNativeCachedRoutes === void 0 ? void 0 : wrappedNativeCachedRoutes.blocksToLive) !== null && _w !== void 0 ? _w : nativeCachedRoutes === null || nativeCachedRoutes === void 0 ? void 0 : nativeCachedRoutes.blocksToLive) !== null && _x !== void 0 ? _x : defaultBlocksToLive_1.DEFAULT_BLOCKS_TO_LIVE[this.chainId],
604
+ });
605
+ }
606
+ }
607
+ else {
608
+ cachedRoutes = await ((_y = this.routeCachingProvider) === null || _y === void 0 ? void 0 : _y.getCachedRoute(this.chainId, amount, quoteCurrency, tradeType, protocols, await blockNumber, routingConfig.optimisticCachedRoutes, routingConfig, swapConfig));
609
+ }
610
+ }
611
+ }
612
+ if ((0, util_1.shouldWipeoutCachedRoutes)(cachedRoutes, routingConfig)) {
613
+ cachedRoutes = undefined;
614
+ }
615
+ metric_1.metric.putMetric(routingConfig.useCachedRoutes
616
+ ? 'GetQuoteUsingCachedRoutes'
617
+ : 'GetQuoteNotUsingCachedRoutes', 1, metric_1.MetricLoggerUnit.Count);
618
+ if (cacheMode &&
619
+ routingConfig.useCachedRoutes &&
620
+ cacheMode !== providers_2.CacheMode.Darkmode &&
621
+ !cachedRoutes) {
622
+ metric_1.metric.putMetric(`GetCachedRoute_miss_${cacheMode}`, 1, metric_1.MetricLoggerUnit.Count);
623
+ log_1.log.info({
624
+ currencyIn: currencyIn.symbol,
625
+ currencyInAddress: (0, util_1.getAddress)(currencyIn),
626
+ currencyOut: currencyOut.symbol,
627
+ currencyOutAddress: (0, util_1.getAddress)(currencyOut),
628
+ cacheMode,
629
+ amount: amount.toExact(),
630
+ chainId: this.chainId,
631
+ tradeType: this.tradeTypeStr(tradeType),
632
+ }, `GetCachedRoute miss ${cacheMode} for ${this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType)}`);
633
+ }
634
+ else if (cachedRoutes && routingConfig.useCachedRoutes) {
635
+ metric_1.metric.putMetric(`GetCachedRoute_hit_${cacheMode}`, 1, metric_1.MetricLoggerUnit.Count);
636
+ log_1.log.info({
637
+ currencyIn: currencyIn.symbol,
638
+ currencyInAddress: (0, util_1.getAddress)(currencyIn),
639
+ currencyOut: currencyOut.symbol,
640
+ currencyOutAddress: (0, util_1.getAddress)(currencyOut),
641
+ cacheMode,
642
+ amount: amount.toExact(),
643
+ chainId: this.chainId,
644
+ tradeType: this.tradeTypeStr(tradeType),
645
+ }, `GetCachedRoute hit ${cacheMode} for ${this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType)}`);
646
+ }
647
+ let swapRouteFromCachePromise = Promise.resolve(null);
648
+ if (cachedRoutes) {
649
+ swapRouteFromCachePromise = this.getSwapRouteFromCache(currencyIn, currencyOut, cachedRoutes, await blockNumber, amount, quoteCurrency, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig);
650
+ }
651
+ let swapRouteFromChainPromise = Promise.resolve(null);
652
+ if (!cachedRoutes || cacheMode !== providers_2.CacheMode.Livemode) {
653
+ swapRouteFromChainPromise = this.getSwapRouteFromChain(amount, currencyIn, currencyOut, protocols, quoteCurrency, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig);
654
+ }
655
+ const [swapRouteFromCache, swapRouteFromChain] = await Promise.all([
656
+ swapRouteFromCachePromise,
657
+ swapRouteFromChainPromise,
658
+ ]);
659
+ let swapRouteRaw;
660
+ let hitsCachedRoute = false;
661
+ if (cacheMode === providers_2.CacheMode.Livemode && swapRouteFromCache) {
662
+ // offline lambda is never in cache mode
663
+ // refresh pools to avoid stale data
664
+ const beforeRefreshPools = Date.now();
665
+ await this.refreshPools(swapRouteFromCache.routes, routingConfig, this.v2PoolProvider, this.v3PoolProvider, this.v4PoolProvider);
666
+ metric_1.metric.putMetric(`Route_RefreshPools_Latency`, Date.now() - beforeRefreshPools, metric_1.MetricLoggerUnit.Milliseconds);
667
+ log_1.log.info(`CacheMode is ${cacheMode}, and we are using swapRoute from cache`);
668
+ hitsCachedRoute = true;
669
+ swapRouteRaw = swapRouteFromCache;
670
+ }
671
+ else {
672
+ log_1.log.info(`CacheMode is ${cacheMode}, and we are using materialized swapRoute`);
673
+ swapRouteRaw = swapRouteFromChain;
674
+ }
675
+ if (cacheMode === providers_2.CacheMode.Tapcompare &&
676
+ swapRouteFromCache &&
677
+ swapRouteFromChain) {
678
+ const quoteDiff = swapRouteFromChain.quote.subtract(swapRouteFromCache.quote);
679
+ const quoteGasAdjustedDiff = swapRouteFromChain.quoteGasAdjusted.subtract(swapRouteFromCache.quoteGasAdjusted);
680
+ const gasUsedDiff = swapRouteFromChain.estimatedGasUsed.sub(swapRouteFromCache.estimatedGasUsed);
681
+ // Only log if quoteDiff is different from 0, or if quoteGasAdjustedDiff and gasUsedDiff are both different from 0
682
+ if (!quoteDiff.equalTo(0) ||
683
+ !(quoteGasAdjustedDiff.equalTo(0) || gasUsedDiff.eq(0))) {
684
+ try {
685
+ // Calculates the percentage of the difference with respect to the quoteFromChain (not from cache)
686
+ const misquotePercent = quoteGasAdjustedDiff
687
+ .divide(swapRouteFromChain.quoteGasAdjusted)
688
+ .multiply(100);
689
+ metric_1.metric.putMetric(`TapcompareCachedRoute_quoteGasAdjustedDiffPercent`, Number(misquotePercent.toExact()), metric_1.MetricLoggerUnit.Percent);
690
+ log_1.log.warn({
691
+ quoteFromChain: swapRouteFromChain.quote.toExact(),
692
+ quoteFromCache: swapRouteFromCache.quote.toExact(),
693
+ quoteDiff: quoteDiff.toExact(),
694
+ quoteGasAdjustedFromChain: swapRouteFromChain.quoteGasAdjusted.toExact(),
695
+ quoteGasAdjustedFromCache: swapRouteFromCache.quoteGasAdjusted.toExact(),
696
+ quoteGasAdjustedDiff: quoteGasAdjustedDiff.toExact(),
697
+ gasUsedFromChain: swapRouteFromChain.estimatedGasUsed.toString(),
698
+ gasUsedFromCache: swapRouteFromCache.estimatedGasUsed.toString(),
699
+ gasUsedDiff: gasUsedDiff.toString(),
700
+ routesFromChain: swapRouteFromChain.routes.toString(),
701
+ routesFromCache: swapRouteFromCache.routes.toString(),
702
+ amount: amount.toExact(),
703
+ originalAmount: cachedRoutes === null || cachedRoutes === void 0 ? void 0 : cachedRoutes.originalAmount,
704
+ pair: this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType),
705
+ blockNumber,
706
+ }, `Comparing quotes between Chain and Cache for ${this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType)}`);
707
+ }
708
+ catch (error) {
709
+ // This is in response to the 'division by zero' error
710
+ // during https://uniswapteam.slack.com/archives/C059TGEC57W/p1723997015399579
711
+ if (error instanceof RangeError &&
712
+ error.message.includes('Division by zero')) {
713
+ log_1.log.error({
714
+ quoteGasAdjustedDiff: quoteGasAdjustedDiff.toExact(),
715
+ swapRouteFromChainQuoteGasAdjusted: swapRouteFromChain.quoteGasAdjusted.toExact(),
716
+ }, 'Error calculating misquote percent');
717
+ metric_1.metric.putMetric(`TapcompareCachedRoute_quoteGasAdjustedDiffPercent_divzero`, 1, metric_1.MetricLoggerUnit.Count);
718
+ }
719
+ // Log but don't throw here - this is only for logging.
720
+ }
721
+ }
722
+ }
723
+ let newSetCachedRoutesPath = false;
724
+ const shouldEnableCachedRoutesCacheInvalidationFix = Math.random() * 100 <
725
+ ((_z = this.cachedRoutesCacheInvalidationFixRolloutPercentage) !== null && _z !== void 0 ? _z : 0);
726
+ // we have to write cached routes right before checking swapRouteRaw is null or not
727
+ // because getCachedRoutes in routing-api do not use the blocks-to-live to filter out the expired routes at all
728
+ // there's a possibility the cachedRoutes is always populated, but swapRouteFromCache is always null, because we don't update cachedRoutes in this case at all,
729
+ // as long as it's within 24 hours sliding window TTL
730
+ if (shouldEnableCachedRoutesCacheInvalidationFix) {
731
+ // theoretically, when routingConfig.intent === INTENT.CACHING, optimisticCachedRoutes should be false
732
+ // so that we can always pass in cachedRoutes?.notExpired(await blockNumber, !routingConfig.optimisticCachedRoutes)
733
+ // but just to be safe, we just hardcode true when checking the cached routes expiry for write update
734
+ // we decide to not check cached routes expiry in the read path anyway
735
+ if (!(cachedRoutes === null || cachedRoutes === void 0 ? void 0 : cachedRoutes.notExpired(await blockNumber, true))) {
736
+ // optimisticCachedRoutes === false means at routing-api level, we only want to set cached routes during intent=caching, not intent=quote
737
+ // this means during the online quote endpoint path, we should not reset cached routes
738
+ if (routingConfig.intent === intent_1.INTENT.CACHING) {
739
+ // due to fire and forget nature, we already take note that we should set new cached routes during the new path
740
+ newSetCachedRoutesPath = true;
741
+ metric_1.metric.putMetric(`SetCachedRoute_NewPath`, 1, metric_1.MetricLoggerUnit.Count);
742
+ // there's a chance that swapRouteFromChain might be populated already,
743
+ // when there's no cachedroutes in the dynamo DB.
744
+ // in that case, we don't try to swap route from chain again
745
+ const swapRouteFromChainAgain = swapRouteFromChain !== null && swapRouteFromChain !== void 0 ? swapRouteFromChain :
746
+ // we have to intentionally await here, because routing-api lambda has a chance to return the swapRoute/swapRouteWithSimulation
747
+ // before the routing-api quote handler can finish running getSwapRouteFromChain (getSwapRouteFromChain is runtime intensive)
748
+ (await this.getSwapRouteFromChain(amount, currencyIn, currencyOut, protocols, quoteCurrency, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig));
749
+ if (swapRouteFromChainAgain) {
750
+ const routesToCache = providers_2.CachedRoutes.fromRoutesWithValidQuotes(swapRouteFromChainAgain.routes, this.chainId, currencyIn, currencyOut, protocols.sort(), await blockNumber, tradeType, amount.toExact());
751
+ await this.setCachedRoutesAndLog(amount, currencyIn, currencyOut, tradeType, 'SetCachedRoute_NewPath', routesToCache, routingConfig.cachedRoutesRouteIds);
752
+ }
753
+ }
754
+ }
755
+ }
756
+ if (!swapRouteRaw) {
757
+ return null;
758
+ }
759
+ const { quote, quoteGasAdjusted, estimatedGasUsed, routes: routeAmounts, estimatedGasUsedQuoteToken, estimatedGasUsedUSD, estimatedGasUsedGasToken, } = swapRouteRaw;
760
+ // we intentionally dont add shouldEnableCachedRoutesCacheInvalidationFix in if condition below
761
+ // because we know cached routes in prod dont filter by blocks-to-live
762
+ // so that we know that swapRouteFromChain is always not populated, because
763
+ // if (!cachedRoutes || cacheMode !== CacheMode.Livemode) above always have the cachedRoutes as populated
764
+ if (this.routeCachingProvider &&
765
+ routingConfig.writeToCachedRoutes &&
766
+ cacheMode !== providers_2.CacheMode.Darkmode &&
767
+ swapRouteFromChain) {
768
+ if (newSetCachedRoutesPath) {
769
+ // SetCachedRoute_NewPath and SetCachedRoute_OldPath metrics might have counts during short timeframe.
770
+ // over time, we should expect to see less SetCachedRoute_OldPath metrics count.
771
+ // in AWS metrics, one can investigate, by:
772
+ // 1) seeing the overall metrics count of SetCachedRoute_NewPath and SetCachedRoute_OldPath. SetCachedRoute_NewPath should steadily go up, while SetCachedRoute_OldPath should go down.
773
+ // 2) using the same requestId, one should see eventually when SetCachedRoute_NewPath metric is logged, SetCachedRoute_OldPath metric should not be called.
774
+ metric_1.metric.putMetric(`SetCachedRoute_OldPath_INTENT_${routingConfig.intent}`, 1, metric_1.MetricLoggerUnit.Count);
775
+ }
776
+ // Generate the object to be cached
777
+ const routesToCache = providers_2.CachedRoutes.fromRoutesWithValidQuotes(swapRouteFromChain.routes, this.chainId, currencyIn, currencyOut, protocols.sort(), await blockNumber, tradeType, amount.toExact());
778
+ await this.setCachedRoutesAndLog(amount, currencyIn, currencyOut, tradeType, 'SetCachedRoute_OldPath', routesToCache, routingConfig.cachedRoutesRouteIds);
779
+ }
780
+ metric_1.metric.putMetric(`QuoteFoundForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
781
+ // Build Trade object that represents the optimal swap.
782
+ const trade = (0, methodParameters_1.buildTrade)(currencyIn, currencyOut, tradeType, routeAmounts);
783
+ let methodParameters;
784
+ // If user provided recipient, deadline etc. we also generate the calldata required to execute
785
+ // the swap and return it too.
786
+ if (swapConfig) {
787
+ methodParameters = (0, methodParameters_1.buildSwapMethodParameters)(trade, swapConfig, this.chainId);
788
+ }
789
+ const tokenOutAmount = tradeType === sdk_core_1.TradeType.EXACT_OUTPUT
790
+ ? originalAmount // we need to pass in originalAmount instead of amount, because amount already added portionAmount in case of exact out swap
791
+ : quote;
792
+ const portionAmount = this.portionProvider.getPortionAmount(tokenOutAmount, tradeType, feeTakenOnTransfer, externalTransferFailed, swapConfig);
793
+ const portionQuoteAmount = this.portionProvider.getPortionQuoteAmount(tradeType, quote, amount, // we need to pass in amount instead of originalAmount here, because amount here needs to add the portion for exact out
794
+ portionAmount);
795
+ // we need to correct quote and quote gas adjusted for exact output when portion is part of the exact out swap
796
+ const correctedQuote = this.portionProvider.getQuote(tradeType, quote, portionQuoteAmount);
797
+ const correctedQuoteGasAdjusted = this.portionProvider.getQuoteGasAdjusted(tradeType, quoteGasAdjusted, portionQuoteAmount);
798
+ const quoteGasAndPortionAdjusted = this.portionProvider.getQuoteGasAndPortionAdjusted(tradeType, quoteGasAdjusted, portionAmount);
799
+ const swapRoute = {
800
+ quote: correctedQuote,
801
+ quoteGasAdjusted: correctedQuoteGasAdjusted,
802
+ estimatedGasUsed,
803
+ estimatedGasUsedQuoteToken,
804
+ estimatedGasUsedUSD,
805
+ estimatedGasUsedGasToken,
806
+ gasPriceWei,
807
+ route: routeAmounts,
808
+ trade,
809
+ methodParameters,
810
+ blockNumber: bignumber_1.BigNumber.from(await blockNumber),
811
+ hitsCachedRoute: hitsCachedRoute,
812
+ portionAmount: portionAmount,
813
+ quoteGasAndPortionAdjusted: quoteGasAndPortionAdjusted,
814
+ };
815
+ if (swapConfig &&
816
+ swapConfig.simulate &&
817
+ methodParameters &&
818
+ methodParameters.calldata) {
819
+ if (!this.simulator) {
820
+ throw new Error('Simulator not initialized!');
821
+ }
822
+ log_1.log.info(JSON.stringify({ swapConfig, methodParameters, providerConfig }, null, 2), `Starting simulation`);
823
+ const fromAddress = swapConfig.simulate.fromAddress;
824
+ const beforeSimulate = Date.now();
825
+ const swapRouteWithSimulation = await this.simulator.simulate(fromAddress, swapConfig, swapRoute, amount,
826
+ // Quote will be in WETH even if quoteCurrency is ETH
827
+ // So we init a new CurrencyAmount object here
828
+ amounts_1.CurrencyAmount.fromRawAmount(quoteCurrency, quote.quotient.toString()), providerConfig);
829
+ if (((_0 = this.deleteCacheEnabledChains) === null || _0 === void 0 ? void 0 : _0.includes(this.chainId)) &&
830
+ swapRouteWithSimulation.simulationStatus === providers_2.SimulationStatus.Failed) {
831
+ // invalidate cached route if simulation failed
832
+ log_1.log.info({
833
+ simulationStatus: swapRouteWithSimulation.simulationStatus,
834
+ swapRoute: swapRouteWithSimulation,
835
+ }, `Simulation failed - detailed failure information: CacheInvalidationCount_${this.chainId}`);
836
+ metric_1.metric.putMetric(`CacheInvalidationCount_${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
837
+ // Generate the object to be cached
838
+ const routesToCache = providers_2.CachedRoutes.fromRoutesWithValidQuotes(swapRouteWithSimulation.route, this.chainId, currencyIn, currencyOut, protocols.sort(), await blockNumber, tradeType, amount.toExact());
839
+ if (!routesToCache) {
840
+ log_1.log.error({ swapRouteWithSimulation }, 'Failed to generate cached routes after simulation failure');
841
+ }
842
+ else {
843
+ try {
844
+ await ((_1 = this.routeCachingProvider) === null || _1 === void 0 ? void 0 : _1.deleteCachedRoute(routesToCache));
845
+ }
846
+ catch (err) {
847
+ log_1.log.error({ err, routesToCache }, 'Failed to delete cached route after simulation failure');
848
+ }
849
+ }
850
+ }
851
+ metric_1.metric.putMetric('SimulateTransaction', Date.now() - beforeSimulate, metric_1.MetricLoggerUnit.Milliseconds);
852
+ return swapRouteWithSimulation;
853
+ }
854
+ return swapRoute;
855
+ }
856
+ /**
857
+ * Refreshes the pools for the given routes.
858
+ *
859
+ * @param routes the routes to refresh the pools for
860
+ * @param routingConfig the routing config
861
+ */
862
+ async refreshPools(routes, routingConfig, v2PoolProvider, v3PoolProvider, v4PoolProvider) {
863
+ for (const route of routes) {
864
+ switch (route.protocol) {
865
+ case router_sdk_1.Protocol.V2:
866
+ route.route = await AlphaRouter.refreshV2Pools(route.route, routingConfig, v2PoolProvider);
867
+ break;
868
+ case router_sdk_1.Protocol.V3:
869
+ route.route = await AlphaRouter.refreshV3Pools(route.route, routingConfig, v3PoolProvider);
870
+ break;
871
+ case router_sdk_1.Protocol.V4:
872
+ route.route = await AlphaRouter.refreshV4Pools(route.route, routingConfig, v4PoolProvider);
873
+ break;
874
+ case router_sdk_1.Protocol.MIXED:
875
+ route.route = await AlphaRouter.refreshMixedPools(route.route, routingConfig, v2PoolProvider, v3PoolProvider, v4PoolProvider);
876
+ break;
877
+ default:
878
+ throw new Error(`Unknown protocol: ${route.protocol}`);
879
+ }
880
+ }
881
+ }
882
+ /**
883
+ * Refreshes the V2 pools for the given route.
884
+ *
885
+ * @param route the route to refresh the V2 pools for
886
+ * @param config the routing config
887
+ * @param v2PoolProvider the V2 pool provider
888
+ * @returns the refreshed route
889
+ */
890
+ static async refreshV2Pools(route, config, v2PoolProvider) {
891
+ const refreshedPairs = [];
892
+ for (const pair of route.pairs) {
893
+ const v2Pools = await v2PoolProvider.getPools([[pair.token0, pair.token1]], config);
894
+ const refreshed = v2Pools.getPool(pair.token0, pair.token1);
895
+ if (refreshed)
896
+ refreshedPairs.push(refreshed);
897
+ else {
898
+ // if the pool is not found, we need to log the error and add the original pool back in
899
+ AlphaRouter.logV2PoolRefreshError(pair);
900
+ refreshedPairs.push(pair);
901
+ }
902
+ }
903
+ return (0, router_1.cloneV2RouteWithNewPools)(route, refreshedPairs);
904
+ }
905
+ /**
906
+ * Refreshes the V3 pools for the given route.
907
+ *
908
+ * @param route the route to refresh the V3 pools for
909
+ * @param config the routing config
910
+ * @param v3PoolProvider the V3 pool provider
911
+ * @returns the refreshed route
912
+ */
913
+ static async refreshV3Pools(route, config, v3PoolProvider) {
914
+ const refreshedPools = [];
915
+ for (const pool of route.pools) {
916
+ const v3Pools = await v3PoolProvider.getPools([[pool.token0, pool.token1, pool.fee]], config);
917
+ const refreshed = v3Pools.getPool(pool.token0, pool.token1, pool.fee);
918
+ if (refreshed)
919
+ refreshedPools.push(refreshed);
920
+ else {
921
+ // if the pool is not found, we need to log the error and add the original pool back in
922
+ AlphaRouter.logV3PoolRefreshError(pool);
923
+ refreshedPools.push(pool);
924
+ }
925
+ }
926
+ return (0, router_1.cloneV3RouteWithNewPools)(route, refreshedPools);
927
+ }
928
+ /**
929
+ * Refreshes the V4 pools for the given route.
930
+ *
931
+ * @param route the route to refresh the V4 pools for
932
+ * @param config the routing config
933
+ * @param v4PoolProvider the V4 pool provider
934
+ * @returns the refreshed route
935
+ */
936
+ static async refreshV4Pools(route, config, v4PoolProvider) {
937
+ const refreshedPools = [];
938
+ for (const pool of route.pools) {
939
+ const v4Pools = await v4PoolProvider.getPools([
940
+ [
941
+ pool.currency0,
942
+ pool.currency1,
943
+ pool.fee,
944
+ pool.tickSpacing,
945
+ pool.hooks,
946
+ ],
947
+ ], config);
948
+ const refreshed = v4Pools.getPool(pool.currency0, pool.currency1, pool.fee, pool.tickSpacing, pool.hooks);
949
+ if (refreshed)
950
+ refreshedPools.push(refreshed);
951
+ else {
952
+ // if the pool is not found, we need to log the error and add the original pool back in
953
+ AlphaRouter.logV4PoolRefreshError(pool);
954
+ refreshedPools.push(pool);
955
+ }
956
+ }
957
+ return (0, router_1.cloneV4RouteWithNewPools)(route, refreshedPools);
958
+ }
959
+ /**
960
+ * Refreshes the mixed pools for the given route.
961
+ *
962
+ * @param route the route to refresh the mixed pools for
963
+ * @param config the routing config
964
+ * @param v2PoolProvider the V2 pool provider
965
+ * @param v3PoolProvider the V3 pool provider
966
+ * @param v4PoolProvider the V4 pool provider
967
+ * @returns the refreshed route
968
+ */
969
+ static async refreshMixedPools(route, config, v2PoolProvider, v3PoolProvider, v4PoolProvider) {
970
+ const refreshedPools = [];
971
+ for (const pool of route.pools) {
972
+ if (pool instanceof v2_sdk_1.Pair) {
973
+ const v2Pools = await v2PoolProvider.getPools([[pool.token0, pool.token1]], config);
974
+ const refreshed = v2Pools.getPool(pool.token0, pool.token1);
975
+ if (refreshed)
976
+ refreshedPools.push(refreshed);
977
+ else {
978
+ // if the pool is not found, we need to log the error and add the original pool back in
979
+ AlphaRouter.logV2PoolRefreshError(pool);
980
+ refreshedPools.push(pool);
981
+ }
982
+ }
983
+ else if (pool instanceof v3_sdk_1.Pool) {
984
+ const v3Pools = await v3PoolProvider.getPools([[pool.token0, pool.token1, pool.fee]], config);
985
+ const refreshed = v3Pools.getPool(pool.token0, pool.token1, pool.fee);
986
+ if (refreshed)
987
+ refreshedPools.push(refreshed);
988
+ else {
989
+ // if the pool is not found, we need to log the error and add the original pool back in
990
+ AlphaRouter.logV3PoolRefreshError(pool);
991
+ refreshedPools.push(pool);
992
+ }
993
+ }
994
+ else if (pool instanceof v4_sdk_1.Pool) {
995
+ const v4Pools = await v4PoolProvider.getPools([
996
+ [
997
+ pool.currency0,
998
+ pool.currency1,
999
+ pool.fee,
1000
+ pool.tickSpacing,
1001
+ pool.hooks,
1002
+ ],
1003
+ ], config);
1004
+ const refreshed = v4Pools.getPool(pool.currency0, pool.currency1, pool.fee, pool.tickSpacing, pool.hooks);
1005
+ if (refreshed)
1006
+ refreshedPools.push(refreshed);
1007
+ else {
1008
+ // if the pool is not found, we need to log the error and add the original pool back in
1009
+ AlphaRouter.logV4PoolRefreshError(pool);
1010
+ refreshedPools.push(pool);
1011
+ }
1012
+ }
1013
+ else {
1014
+ throw new Error('Unknown pool type in mixed route');
1015
+ }
1016
+ }
1017
+ return (0, router_1.cloneMixedRouteWithNewPools)(route, refreshedPools);
1018
+ }
1019
+ static logV2PoolRefreshError(v2Pool) {
1020
+ log_1.log.error({
1021
+ token0: v2Pool.token0,
1022
+ token1: v2Pool.token1,
1023
+ }, 'Failed to refresh V2 pool');
1024
+ }
1025
+ static logV3PoolRefreshError(v3Pool) {
1026
+ log_1.log.error({
1027
+ token0: v3Pool.token0,
1028
+ token1: v3Pool.token1,
1029
+ fee: v3Pool.fee,
1030
+ }, 'Failed to refresh V3 pool');
1031
+ }
1032
+ static logV4PoolRefreshError(v4Pool) {
1033
+ log_1.log.error({
1034
+ token0: v4Pool.currency0,
1035
+ token1: v4Pool.currency1,
1036
+ fee: v4Pool.fee,
1037
+ tickSpacing: v4Pool.tickSpacing,
1038
+ hooks: v4Pool.hooks,
1039
+ }, 'Failed to refresh V4 pool');
1040
+ }
1041
+ async setCachedRoutesAndLog(amount, currencyIn, currencyOut, tradeType, metricsPrefix, routesToCache, cachedRoutesRouteIds) {
1042
+ var _a;
1043
+ if (routesToCache) {
1044
+ const cachedRoutesChanged = cachedRoutesRouteIds !== undefined &&
1045
+ // it's possible that top cached routes may be split routes,
1046
+ // so that we always serialize all the top 8 retrieved cached routes vs the top routes.
1047
+ !cachedRoutesRouteIds.startsWith((0, serializeRouteIds_1.serializeRouteIds)(routesToCache.routes.map((r) => r.routeId)));
1048
+ if (cachedRoutesChanged) {
1049
+ metric_1.metric.putMetric('cachedRoutesChanged', 1, metric_1.MetricLoggerUnit.Count);
1050
+ metric_1.metric.putMetric(`cachedRoutesChanged_chainId${currencyIn.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1051
+ metric_1.metric.putMetric(`cachedRoutesChanged_chainId${currencyOut.chainId}_pair${currencyIn.symbol}${currencyOut.symbol}`, 1, metric_1.MetricLoggerUnit.Count);
1052
+ }
1053
+ else {
1054
+ metric_1.metric.putMetric('cachedRoutesNotChanged', 1, metric_1.MetricLoggerUnit.Count);
1055
+ metric_1.metric.putMetric(`cachedRoutesNotChanged_chainId${currencyIn.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1056
+ metric_1.metric.putMetric(`cachedRoutesNotChanged_chainId${currencyOut.chainId}_pair${currencyIn.symbol}${currencyOut.symbol}`, 1, metric_1.MetricLoggerUnit.Count);
1057
+ }
1058
+ await ((_a = this.routeCachingProvider) === null || _a === void 0 ? void 0 : _a.setCachedRoute(routesToCache, amount).then((success) => {
1059
+ const status = success ? 'success' : 'rejected';
1060
+ metric_1.metric.putMetric(`${metricsPrefix}_${status}`, 1, metric_1.MetricLoggerUnit.Count);
1061
+ }).catch((reason) => {
1062
+ log_1.log.error({
1063
+ reason: reason,
1064
+ tokenPair: this.tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType),
1065
+ }, `SetCachedRoute failure`);
1066
+ metric_1.metric.putMetric(`${metricsPrefix}_failure`, 1, metric_1.MetricLoggerUnit.Count);
1067
+ }));
1068
+ }
1069
+ else {
1070
+ metric_1.metric.putMetric(`${metricsPrefix}_unnecessary`, 1, metric_1.MetricLoggerUnit.Count);
1071
+ }
1072
+ }
1073
+ async getSwapRouteFromCache(currencyIn, currencyOut, cachedRoutes, blockNumber, amount, quoteCurrency, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig) {
1074
+ var _a, _c, _d, _e, _f, _g;
1075
+ const tokenPairProperties = await this.tokenPropertiesProvider.getTokensProperties([currencyIn, currencyOut], providerConfig);
1076
+ const sellTokenIsFot = (_d = (_c = (_a = tokenPairProperties[(0, util_1.getAddressLowerCase)(currencyIn)]) === null || _a === void 0 ? void 0 : _a.tokenFeeResult) === null || _c === void 0 ? void 0 : _c.sellFeeBps) === null || _d === void 0 ? void 0 : _d.gt(0);
1077
+ const buyTokenIsFot = (_g = (_f = (_e = tokenPairProperties[(0, util_1.getAddressLowerCase)(currencyOut)]) === null || _e === void 0 ? void 0 : _e.tokenFeeResult) === null || _f === void 0 ? void 0 : _f.buyFeeBps) === null || _g === void 0 ? void 0 : _g.gt(0);
1078
+ const fotInDirectSwap = sellTokenIsFot || buyTokenIsFot;
1079
+ log_1.log.info({
1080
+ protocols: cachedRoutes.protocolsCovered,
1081
+ tradeType: cachedRoutes.tradeType,
1082
+ cachedBlockNumber: cachedRoutes.blockNumber,
1083
+ quoteBlockNumber: blockNumber,
1084
+ }, 'Routing across CachedRoute');
1085
+ const quotePromises = [];
1086
+ const v4Routes = cachedRoutes.routes.filter((route) => route.protocol === router_sdk_1.Protocol.V4);
1087
+ const v3Routes = cachedRoutes.routes.filter((route) => route.protocol === router_sdk_1.Protocol.V3);
1088
+ const v2Routes = cachedRoutes.routes.filter((route) => route.protocol === router_sdk_1.Protocol.V2);
1089
+ const mixedRoutes = cachedRoutes.routes.filter((route) => route.protocol === router_sdk_1.Protocol.MIXED);
1090
+ let percents;
1091
+ let amounts;
1092
+ if (cachedRoutes.routes.length > 1) {
1093
+ // If we have more than 1 route, we will quote the different percents for it, following the regular process
1094
+ [percents, amounts] = this.getAmountDistribution(amount, routingConfig);
1095
+ }
1096
+ else if (cachedRoutes.routes.length == 1) {
1097
+ [percents, amounts] = [[100], [amount]];
1098
+ }
1099
+ else {
1100
+ // In this case this means that there's no route, so we return null
1101
+ return Promise.resolve(null);
1102
+ }
1103
+ if (v4Routes.length > 0) {
1104
+ const v4RoutesFromCache = v4Routes.map((cachedRoute) => cachedRoute.route);
1105
+ metric_1.metric.putMetric('SwapRouteFromCache_V4_GetQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
1106
+ const beforeGetQuotes = Date.now();
1107
+ quotePromises.push(this.v4Quoter
1108
+ .getQuotes(v4RoutesFromCache, amounts, percents, quoteCurrency, tradeType, routingConfig, undefined, v4GasModel)
1109
+ .then((result) => {
1110
+ metric_1.metric.putMetric(`SwapRouteFromCache_V4_GetQuotes_Load`, Date.now() - beforeGetQuotes, metric_1.MetricLoggerUnit.Milliseconds);
1111
+ return result;
1112
+ }));
1113
+ }
1114
+ if (!fotInDirectSwap) {
1115
+ if (v3Routes.length > 0) {
1116
+ const v3RoutesFromCache = v3Routes.map((cachedRoute) => cachedRoute.route);
1117
+ metric_1.metric.putMetric('SwapRouteFromCache_V3_GetQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
1118
+ const beforeGetQuotes = Date.now();
1119
+ quotePromises.push(this.v3Quoter
1120
+ .getQuotes(v3RoutesFromCache, amounts, percents, quoteCurrency.wrapped, tradeType, routingConfig, undefined, v3GasModel)
1121
+ .then((result) => {
1122
+ metric_1.metric.putMetric(`SwapRouteFromCache_V3_GetQuotes_Load`, Date.now() - beforeGetQuotes, metric_1.MetricLoggerUnit.Milliseconds);
1123
+ return result;
1124
+ }));
1125
+ }
1126
+ }
1127
+ if (v2Routes.length > 0) {
1128
+ const v2RoutesFromCache = v2Routes.map((cachedRoute) => cachedRoute.route);
1129
+ metric_1.metric.putMetric('SwapRouteFromCache_V2_GetQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
1130
+ const beforeGetQuotes = Date.now();
1131
+ quotePromises.push(this.v2Quoter
1132
+ .refreshRoutesThenGetQuotes(cachedRoutes.currencyIn.wrapped, cachedRoutes.currencyOut.wrapped, v2RoutesFromCache, amounts, percents, quoteCurrency.wrapped, tradeType, routingConfig, gasPriceWei)
1133
+ .then((result) => {
1134
+ metric_1.metric.putMetric(`SwapRouteFromCache_V2_GetQuotes_Load`, Date.now() - beforeGetQuotes, metric_1.MetricLoggerUnit.Milliseconds);
1135
+ return result;
1136
+ }));
1137
+ }
1138
+ if (!fotInDirectSwap) {
1139
+ if (mixedRoutes.length > 0) {
1140
+ const mixedRoutesFromCache = mixedRoutes.map((cachedRoute) => cachedRoute.route);
1141
+ metric_1.metric.putMetric('SwapRouteFromCache_Mixed_GetQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
1142
+ const beforeGetQuotes = Date.now();
1143
+ quotePromises.push(this.mixedQuoter
1144
+ .getQuotes(mixedRoutesFromCache, amounts, percents, quoteCurrency.wrapped, tradeType, routingConfig, undefined, mixedRouteGasModel)
1145
+ .then((result) => {
1146
+ metric_1.metric.putMetric(`SwapRouteFromCache_Mixed_GetQuotes_Load`, Date.now() - beforeGetQuotes, metric_1.MetricLoggerUnit.Milliseconds);
1147
+ return result;
1148
+ }));
1149
+ }
1150
+ }
1151
+ const getQuotesResults = await Promise.all(quotePromises);
1152
+ const allRoutesWithValidQuotes = lodash_1.default.flatMap(getQuotesResults, (quoteResult) => quoteResult.routesWithValidQuotes);
1153
+ return (0, best_swap_route_1.getBestSwapRoute)(amount, percents, allRoutesWithValidQuotes, tradeType, this.chainId, routingConfig, this.portionProvider, v2GasModel, v3GasModel, v4GasModel, swapConfig, providerConfig);
1154
+ }
1155
+ async getSwapRouteFromChain(amount, currencyIn, currencyOut, protocols, quoteCurrency, tradeType, routingConfig, v3GasModel, v4GasModel, mixedRouteGasModel, gasPriceWei, v2GasModel, swapConfig, providerConfig) {
1156
+ var _a, _c, _d, _e, _f, _g, _h, _j, _k;
1157
+ const tokenPairProperties = await this.tokenPropertiesProvider.getTokensProperties([currencyIn, currencyOut], providerConfig);
1158
+ const sellTokenIsFot = (_d = (_c = (_a = tokenPairProperties[(0, util_1.getAddressLowerCase)(currencyIn)]) === null || _a === void 0 ? void 0 : _a.tokenFeeResult) === null || _c === void 0 ? void 0 : _c.sellFeeBps) === null || _d === void 0 ? void 0 : _d.gt(0);
1159
+ const buyTokenIsFot = (_g = (_f = (_e = tokenPairProperties[(0, util_1.getAddressLowerCase)(currencyOut)]) === null || _e === void 0 ? void 0 : _e.tokenFeeResult) === null || _f === void 0 ? void 0 : _f.buyFeeBps) === null || _g === void 0 ? void 0 : _g.gt(0);
1160
+ const fotInDirectSwap = sellTokenIsFot || buyTokenIsFot;
1161
+ // Generate our distribution of amounts, i.e. fractions of the input amount.
1162
+ // We will get quotes for fractions of the input amount for different routes, then
1163
+ // combine to generate split routes.
1164
+ const [percents, amounts] = this.getAmountDistribution(amount, routingConfig);
1165
+ const noProtocolsSpecified = protocols.length === 0;
1166
+ const v4ProtocolSpecified = protocols.includes(router_sdk_1.Protocol.V4);
1167
+ const v3ProtocolSpecified = protocols.includes(router_sdk_1.Protocol.V3);
1168
+ const v2ProtocolSpecified = protocols.includes(router_sdk_1.Protocol.V2);
1169
+ const v2SupportedInChain = (_h = this.v2Supported) === null || _h === void 0 ? void 0 : _h.includes(this.chainId);
1170
+ const v4SupportedInChain = (_j = this.v4Supported) === null || _j === void 0 ? void 0 : _j.includes(this.chainId);
1171
+ const shouldQueryMixedProtocol = protocols.includes(router_sdk_1.Protocol.MIXED) ||
1172
+ (noProtocolsSpecified && v2SupportedInChain && v4SupportedInChain);
1173
+ const mixedProtocolAllowed = ((_k = this.mixedSupported) === null || _k === void 0 ? void 0 : _k.includes(this.chainId)) &&
1174
+ tradeType === sdk_core_1.TradeType.EXACT_INPUT;
1175
+ const beforeGetCandidates = Date.now();
1176
+ let v4CandidatePoolsPromise = Promise.resolve(undefined);
1177
+ // we are explicitly requiring people to specify v4 for now
1178
+ if (v4SupportedInChain && (v4ProtocolSpecified || noProtocolsSpecified)) {
1179
+ // if (v4ProtocolSpecified || noProtocolsSpecified) {
1180
+ v4CandidatePoolsPromise = (0, get_candidate_pools_1.getV4CandidatePools)({
1181
+ currencyIn: currencyIn,
1182
+ currencyOut: currencyOut,
1183
+ tokenProvider: this.tokenProvider,
1184
+ blockedTokenListProvider: this.blockedTokenListProvider,
1185
+ poolProvider: this.v4PoolProvider,
1186
+ routeType: tradeType,
1187
+ subgraphProvider: this.v4SubgraphProvider,
1188
+ routingConfig,
1189
+ chainId: this.chainId,
1190
+ v4PoolParams: this.v4PoolParams,
1191
+ }).then((candidatePools) => {
1192
+ metric_1.metric.putMetric('GetV4CandidatePools', Date.now() - beforeGetCandidates, metric_1.MetricLoggerUnit.Milliseconds);
1193
+ return candidatePools;
1194
+ });
1195
+ }
1196
+ let v3CandidatePoolsPromise = Promise.resolve(undefined);
1197
+ if (!fotInDirectSwap) {
1198
+ if (v3ProtocolSpecified || noProtocolsSpecified) {
1199
+ const tokenIn = currencyIn.wrapped;
1200
+ const tokenOut = currencyOut.wrapped;
1201
+ v3CandidatePoolsPromise = (0, get_candidate_pools_1.getV3CandidatePools)({
1202
+ tokenIn,
1203
+ tokenOut,
1204
+ tokenProvider: this.tokenProvider,
1205
+ blockedTokenListProvider: this.blockedTokenListProvider,
1206
+ poolProvider: this.v3PoolProvider,
1207
+ routeType: tradeType,
1208
+ subgraphProvider: this.v3SubgraphProvider,
1209
+ routingConfig,
1210
+ chainId: this.chainId,
1211
+ }).then((candidatePools) => {
1212
+ metric_1.metric.putMetric('GetV3CandidatePools', Date.now() - beforeGetCandidates, metric_1.MetricLoggerUnit.Milliseconds);
1213
+ return candidatePools;
1214
+ });
1215
+ }
1216
+ }
1217
+ let v2CandidatePoolsPromise = Promise.resolve(undefined);
1218
+ if (v2SupportedInChain && (v2ProtocolSpecified || noProtocolsSpecified)) {
1219
+ const tokenIn = currencyIn.wrapped;
1220
+ const tokenOut = currencyOut.wrapped;
1221
+ // Fetch all the pools that we will consider routing via. There are thousands
1222
+ // of pools, so we filter them to a set of candidate pools that we expect will
1223
+ // result in good prices.
1224
+ v2CandidatePoolsPromise = (0, get_candidate_pools_1.getV2CandidatePools)({
1225
+ tokenIn,
1226
+ tokenOut,
1227
+ tokenProvider: this.tokenProvider,
1228
+ blockedTokenListProvider: this.blockedTokenListProvider,
1229
+ poolProvider: this.v2PoolProvider,
1230
+ routeType: tradeType,
1231
+ subgraphProvider: this.v2SubgraphProvider,
1232
+ routingConfig,
1233
+ chainId: this.chainId,
1234
+ }).then((candidatePools) => {
1235
+ metric_1.metric.putMetric('GetV2CandidatePools', Date.now() - beforeGetCandidates, metric_1.MetricLoggerUnit.Milliseconds);
1236
+ return candidatePools;
1237
+ });
1238
+ }
1239
+ const quotePromises = [];
1240
+ // for v4, for now we explicitly require people to specify
1241
+ if (v4SupportedInChain && v4ProtocolSpecified) {
1242
+ log_1.log.info({ protocols, tradeType }, 'Routing across V4');
1243
+ metric_1.metric.putMetric('SwapRouteFromChain_V4_GetRoutesThenQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
1244
+ const beforeGetRoutesThenQuotes = Date.now();
1245
+ quotePromises.push(v4CandidatePoolsPromise.then((v4CandidatePools) => this.v4Quoter
1246
+ .getRoutesThenQuotes(currencyIn, currencyOut, amount, amounts, percents, quoteCurrency, v4CandidatePools, tradeType, routingConfig, v4GasModel)
1247
+ .then((result) => {
1248
+ metric_1.metric.putMetric(`SwapRouteFromChain_V4_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, metric_1.MetricLoggerUnit.Milliseconds);
1249
+ return result;
1250
+ })));
1251
+ }
1252
+ if (!fotInDirectSwap) {
1253
+ // Maybe Quote V3 - if V3 is specified, or no protocol is specified
1254
+ if (v3ProtocolSpecified || noProtocolsSpecified) {
1255
+ log_1.log.info({ protocols, tradeType }, 'Routing across V3');
1256
+ metric_1.metric.putMetric('SwapRouteFromChain_V3_GetRoutesThenQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
1257
+ const beforeGetRoutesThenQuotes = Date.now();
1258
+ const tokenIn = currencyIn.wrapped;
1259
+ const tokenOut = currencyOut.wrapped;
1260
+ quotePromises.push(v3CandidatePoolsPromise.then((v3CandidatePools) => this.v3Quoter
1261
+ .getRoutesThenQuotes(tokenIn, tokenOut, amount, amounts, percents, quoteCurrency.wrapped, v3CandidatePools, tradeType, routingConfig, v3GasModel)
1262
+ .then((result) => {
1263
+ metric_1.metric.putMetric(`SwapRouteFromChain_V3_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, metric_1.MetricLoggerUnit.Milliseconds);
1264
+ return result;
1265
+ })));
1266
+ }
1267
+ }
1268
+ // Maybe Quote V2 - if V2 is specified, or no protocol is specified AND v2 is supported in this chain
1269
+ if (v2SupportedInChain && (v2ProtocolSpecified || noProtocolsSpecified)) {
1270
+ log_1.log.info({ protocols, tradeType }, 'Routing across V2');
1271
+ metric_1.metric.putMetric('SwapRouteFromChain_V2_GetRoutesThenQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
1272
+ const beforeGetRoutesThenQuotes = Date.now();
1273
+ const tokenIn = currencyIn.wrapped;
1274
+ const tokenOut = currencyOut.wrapped;
1275
+ quotePromises.push(v2CandidatePoolsPromise.then((v2CandidatePools) => this.v2Quoter
1276
+ .getRoutesThenQuotes(tokenIn, tokenOut, amount, amounts, percents, quoteCurrency.wrapped, v2CandidatePools, tradeType, routingConfig, v2GasModel, gasPriceWei)
1277
+ .then((result) => {
1278
+ metric_1.metric.putMetric(`SwapRouteFromChain_V2_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, metric_1.MetricLoggerUnit.Milliseconds);
1279
+ return result;
1280
+ })));
1281
+ }
1282
+ if (!fotInDirectSwap) {
1283
+ // Maybe Quote mixed routes
1284
+ // if MixedProtocol is specified or no protocol is specified and v2 is supported AND tradeType is ExactIn
1285
+ // AND is Mainnet or Gorli
1286
+ // Also make sure there are at least 2 protocols provided besides MIXED, before entering mixed quoter
1287
+ if (shouldQueryMixedProtocol &&
1288
+ mixedProtocolAllowed &&
1289
+ protocols.filter((protocol) => protocol !== router_sdk_1.Protocol.MIXED).length >= 2) {
1290
+ log_1.log.info({ protocols, tradeType }, 'Routing across MixedRoutes');
1291
+ metric_1.metric.putMetric('SwapRouteFromChain_Mixed_GetRoutesThenQuotes_Request', 1, metric_1.MetricLoggerUnit.Count);
1292
+ const beforeGetRoutesThenQuotes = Date.now();
1293
+ quotePromises.push(Promise.all([
1294
+ v4CandidatePoolsPromise,
1295
+ v3CandidatePoolsPromise,
1296
+ v2CandidatePoolsPromise,
1297
+ ]).then(async ([v4CandidatePools, v3CandidatePools, v2CandidatePools]) => {
1298
+ const tokenIn = currencyIn.wrapped;
1299
+ const tokenOut = currencyOut.wrapped;
1300
+ const crossLiquidityPools = await (0, get_candidate_pools_1.getMixedCrossLiquidityCandidatePools)({
1301
+ tokenIn,
1302
+ tokenOut,
1303
+ blockNumber: routingConfig.blockNumber,
1304
+ v2SubgraphProvider: this.v2SubgraphProvider,
1305
+ v3SubgraphProvider: this.v3SubgraphProvider,
1306
+ v4SubgraphProvider: this.v4SubgraphProvider,
1307
+ v2Candidates: v2CandidatePools,
1308
+ v3Candidates: v3CandidatePools,
1309
+ v4Candidates: v4CandidatePools,
1310
+ mixedCrossLiquidityV3AgainstV4Supported: this.mixedCrossLiquidityV3AgainstV4Supported,
1311
+ chainId: this.chainId,
1312
+ });
1313
+ return this.mixedQuoter
1314
+ .getRoutesThenQuotes(currencyIn, currencyOut, amount, amounts, percents, quoteCurrency.wrapped, [
1315
+ v4CandidatePools,
1316
+ v3CandidatePools,
1317
+ v2CandidatePools,
1318
+ crossLiquidityPools,
1319
+ ], tradeType, routingConfig, mixedRouteGasModel)
1320
+ .then((result) => {
1321
+ metric_1.metric.putMetric(`SwapRouteFromChain_Mixed_GetRoutesThenQuotes_Load`, Date.now() - beforeGetRoutesThenQuotes, metric_1.MetricLoggerUnit.Milliseconds);
1322
+ return result;
1323
+ });
1324
+ }));
1325
+ }
1326
+ }
1327
+ const getQuotesResults = await Promise.all(quotePromises);
1328
+ const allRoutesWithValidQuotes = [];
1329
+ const allCandidatePools = [];
1330
+ getQuotesResults.forEach((getQuoteResult) => {
1331
+ allRoutesWithValidQuotes.push(...getQuoteResult.routesWithValidQuotes);
1332
+ if (getQuoteResult.candidatePools) {
1333
+ allCandidatePools.push(getQuoteResult.candidatePools);
1334
+ }
1335
+ });
1336
+ if (allRoutesWithValidQuotes.length === 0) {
1337
+ log_1.log.info({ allRoutesWithValidQuotes }, 'Received no valid quotes');
1338
+ return null;
1339
+ }
1340
+ // Given all the quotes for all the amounts for all the routes, find the best combination.
1341
+ const bestSwapRoute = await (0, best_swap_route_1.getBestSwapRoute)(amount, percents, allRoutesWithValidQuotes, tradeType, this.chainId, routingConfig, this.portionProvider, v2GasModel, v3GasModel, v4GasModel, swapConfig, providerConfig);
1342
+ if (bestSwapRoute) {
1343
+ this.emitPoolSelectionMetrics(bestSwapRoute, allCandidatePools, currencyIn, currencyOut);
1344
+ }
1345
+ return bestSwapRoute;
1346
+ }
1347
+ tradeTypeStr(tradeType) {
1348
+ return tradeType === sdk_core_1.TradeType.EXACT_INPUT ? 'ExactIn' : 'ExactOut';
1349
+ }
1350
+ tokenPairSymbolTradeTypeChainId(currencyIn, currencyOut, tradeType) {
1351
+ return `${currencyIn.symbol}/${currencyOut.symbol}/${this.tradeTypeStr(tradeType)}/${this.chainId}`;
1352
+ }
1353
+ determineCurrencyInOutFromTradeType(tradeType, amount, quoteCurrency) {
1354
+ if (tradeType === sdk_core_1.TradeType.EXACT_INPUT) {
1355
+ return {
1356
+ currencyIn: amount.currency,
1357
+ currencyOut: quoteCurrency,
1358
+ };
1359
+ }
1360
+ else {
1361
+ return {
1362
+ currencyIn: quoteCurrency,
1363
+ currencyOut: amount.currency,
1364
+ };
1365
+ }
1366
+ }
1367
+ async getGasPriceWei(latestBlockNumber, requestBlockNumber) {
1368
+ // Track how long it takes to resolve this async call.
1369
+ const beforeGasTimestamp = Date.now();
1370
+ // Get an estimate of the gas price to use when estimating gas cost of different routes.
1371
+ const { gasPriceWei } = await this.gasPriceProvider.getGasPrice(latestBlockNumber, requestBlockNumber);
1372
+ metric_1.metric.putMetric('GasPriceLoad', Date.now() - beforeGasTimestamp, metric_1.MetricLoggerUnit.Milliseconds);
1373
+ return gasPriceWei;
1374
+ }
1375
+ async getGasModels(gasPriceWei, amountToken, quoteToken, providerConfig) {
1376
+ var _a;
1377
+ const beforeGasModel = Date.now();
1378
+ const usdPoolPromise = (0, gas_factory_helpers_1.getHighestLiquidityV3USDPool)(this.chainId, this.v3PoolProvider, providerConfig);
1379
+ const nativeCurrency = util_1.WRAPPED_NATIVE_CURRENCY[this.chainId];
1380
+ const nativeAndQuoteTokenV3PoolPromise = !quoteToken.equals(nativeCurrency)
1381
+ ? (0, gas_factory_helpers_1.getHighestLiquidityV3NativePool)(quoteToken, this.v3PoolProvider, providerConfig)
1382
+ : Promise.resolve(null);
1383
+ const nativeAndAmountTokenV3PoolPromise = !amountToken.equals(nativeCurrency)
1384
+ ? (0, gas_factory_helpers_1.getHighestLiquidityV3NativePool)(amountToken, this.v3PoolProvider, providerConfig)
1385
+ : Promise.resolve(null);
1386
+ // If a specific gas token is specified in the provider config
1387
+ // fetch the highest liq V3 pool with it and the native currency
1388
+ const nativeAndSpecifiedGasTokenV3PoolPromise = (providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken) &&
1389
+ !(providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken.equals(nativeCurrency))
1390
+ ? (0, gas_factory_helpers_1.getHighestLiquidityV3NativePool)(providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.gasToken, this.v3PoolProvider, providerConfig)
1391
+ : Promise.resolve(null);
1392
+ const [usdPool, nativeAndQuoteTokenV3Pool, nativeAndAmountTokenV3Pool, nativeAndSpecifiedGasTokenV3Pool,] = await Promise.all([
1393
+ usdPoolPromise,
1394
+ nativeAndQuoteTokenV3PoolPromise,
1395
+ nativeAndAmountTokenV3PoolPromise,
1396
+ nativeAndSpecifiedGasTokenV3PoolPromise,
1397
+ ]);
1398
+ const pools = {
1399
+ usdPool: usdPool,
1400
+ nativeAndQuoteTokenV3Pool: nativeAndQuoteTokenV3Pool,
1401
+ nativeAndAmountTokenV3Pool: nativeAndAmountTokenV3Pool,
1402
+ nativeAndSpecifiedGasTokenV3Pool: nativeAndSpecifiedGasTokenV3Pool,
1403
+ };
1404
+ const v2GasModelPromise = ((_a = this.v2Supported) === null || _a === void 0 ? void 0 : _a.includes(this.chainId))
1405
+ ? this.v2GasModelFactory
1406
+ .buildGasModel({
1407
+ chainId: this.chainId,
1408
+ gasPriceWei,
1409
+ poolProvider: this.v2PoolProvider,
1410
+ token: quoteToken,
1411
+ l2GasDataProvider: this.l2GasDataProvider,
1412
+ providerConfig: providerConfig,
1413
+ })
1414
+ .catch((_) => undefined) // If v2 model throws uncaught exception, we return undefined v2 gas model, so there's a chance v3 route can go through
1415
+ : Promise.resolve(undefined);
1416
+ const v3GasModelPromise = this.v3GasModelFactory.buildGasModel({
1417
+ chainId: this.chainId,
1418
+ gasPriceWei,
1419
+ pools,
1420
+ amountToken,
1421
+ quoteToken,
1422
+ v2poolProvider: this.v2PoolProvider,
1423
+ l2GasDataProvider: this.l2GasDataProvider,
1424
+ providerConfig: providerConfig,
1425
+ });
1426
+ const v4GasModelPromise = this.v4GasModelFactory.buildGasModel({
1427
+ chainId: this.chainId,
1428
+ gasPriceWei,
1429
+ pools,
1430
+ amountToken,
1431
+ quoteToken,
1432
+ v2poolProvider: this.v2PoolProvider,
1433
+ l2GasDataProvider: this.l2GasDataProvider,
1434
+ providerConfig: providerConfig,
1435
+ });
1436
+ const mixedRouteGasModelPromise = this.mixedRouteGasModelFactory.buildGasModel({
1437
+ chainId: this.chainId,
1438
+ gasPriceWei,
1439
+ pools,
1440
+ amountToken,
1441
+ quoteToken,
1442
+ v2poolProvider: this.v2PoolProvider,
1443
+ providerConfig: providerConfig,
1444
+ });
1445
+ const [v2GasModel, v3GasModel, V4GasModel, mixedRouteGasModel] = await Promise.all([
1446
+ v2GasModelPromise,
1447
+ v3GasModelPromise,
1448
+ v4GasModelPromise,
1449
+ mixedRouteGasModelPromise,
1450
+ ]);
1451
+ metric_1.metric.putMetric('GasModelCreation', Date.now() - beforeGasModel, metric_1.MetricLoggerUnit.Milliseconds);
1452
+ return {
1453
+ v2GasModel: v2GasModel,
1454
+ v3GasModel: v3GasModel,
1455
+ v4GasModel: V4GasModel,
1456
+ mixedRouteGasModel: mixedRouteGasModel,
1457
+ };
1458
+ }
1459
+ // Note multiplications here can result in a loss of precision in the amounts (e.g. taking 50% of 101)
1460
+ // This is reconcilled at the end of the algorithm by adding any lost precision to one of
1461
+ // the splits in the route.
1462
+ getAmountDistribution(amount, routingConfig) {
1463
+ const { distributionPercent } = routingConfig;
1464
+ const percents = [];
1465
+ const amounts = [];
1466
+ for (let i = 1; i <= 100 / distributionPercent; i++) {
1467
+ percents.push(i * distributionPercent);
1468
+ amounts.push(amount.multiply(new sdk_core_1.Fraction(i * distributionPercent, 100)));
1469
+ }
1470
+ return [percents, amounts];
1471
+ }
1472
+ async buildSwapAndAddMethodParameters(trade, swapAndAddOptions, swapAndAddParameters) {
1473
+ const { swapOptions: { recipient, slippageTolerance, deadline, inputTokenPermit }, addLiquidityOptions: addLiquidityConfig, } = swapAndAddOptions;
1474
+ const preLiquidityPosition = swapAndAddParameters.preLiquidityPosition;
1475
+ const finalBalanceTokenIn = swapAndAddParameters.initialBalanceTokenIn.subtract(trade.inputAmount);
1476
+ const finalBalanceTokenOut = swapAndAddParameters.initialBalanceTokenOut.add(trade.outputAmount);
1477
+ const approvalTypes = await this.swapRouterProvider.getApprovalType(finalBalanceTokenIn, finalBalanceTokenOut);
1478
+ const zeroForOne = finalBalanceTokenIn.currency.wrapped.sortsBefore(finalBalanceTokenOut.currency.wrapped);
1479
+ return Object.assign(Object.assign({}, router_sdk_1.SwapRouter.swapAndAddCallParameters(trade, {
1480
+ recipient,
1481
+ slippageTolerance,
1482
+ deadlineOrPreviousBlockhash: deadline,
1483
+ inputTokenPermit,
1484
+ }, v3_sdk_1.Position.fromAmounts({
1485
+ pool: preLiquidityPosition.pool,
1486
+ tickLower: preLiquidityPosition.tickLower,
1487
+ tickUpper: preLiquidityPosition.tickUpper,
1488
+ amount0: zeroForOne
1489
+ ? finalBalanceTokenIn.quotient.toString()
1490
+ : finalBalanceTokenOut.quotient.toString(),
1491
+ amount1: zeroForOne
1492
+ ? finalBalanceTokenOut.quotient.toString()
1493
+ : finalBalanceTokenIn.quotient.toString(),
1494
+ useFullPrecision: false,
1495
+ }), addLiquidityConfig, approvalTypes.approvalTokenIn, approvalTypes.approvalTokenOut)), { to: (0, util_1.SWAP_ROUTER_02_ADDRESSES)(this.chainId) });
1496
+ }
1497
+ emitPoolSelectionMetrics(swapRouteRaw, allPoolsBySelection, currencyIn, currencyOut) {
1498
+ const poolAddressesUsed = new Set();
1499
+ const { routes: routeAmounts } = swapRouteRaw;
1500
+ (0, lodash_1.default)(routeAmounts)
1501
+ .flatMap((routeAmount) => {
1502
+ const { poolIdentifiers: poolAddresses } = routeAmount;
1503
+ return poolAddresses;
1504
+ })
1505
+ .forEach((address) => {
1506
+ poolAddressesUsed.add(address.toLowerCase());
1507
+ });
1508
+ for (const poolsBySelection of allPoolsBySelection) {
1509
+ const { protocol } = poolsBySelection;
1510
+ lodash_1.default.forIn(poolsBySelection.selections, (pools, topNSelection) => {
1511
+ const topNUsed = lodash_1.default.findLastIndex(pools, (pool) => poolAddressesUsed.has(pool.id.toLowerCase())) + 1;
1512
+ metric_1.metric.putMetric(lodash_1.default.capitalize(`${protocol}${topNSelection}`), topNUsed, metric_1.MetricLoggerUnit.Count);
1513
+ });
1514
+ }
1515
+ let hasV4Route = false;
1516
+ let hasV3Route = false;
1517
+ let hasV2Route = false;
1518
+ let hasMixedRoute = false;
1519
+ for (const routeAmount of routeAmounts) {
1520
+ if (routeAmount.protocol === router_sdk_1.Protocol.V4) {
1521
+ hasV4Route = true;
1522
+ }
1523
+ if (routeAmount.protocol === router_sdk_1.Protocol.V3) {
1524
+ hasV3Route = true;
1525
+ }
1526
+ if (routeAmount.protocol === router_sdk_1.Protocol.V2) {
1527
+ hasV2Route = true;
1528
+ }
1529
+ if (routeAmount.protocol === router_sdk_1.Protocol.MIXED) {
1530
+ hasMixedRoute = true;
1531
+ }
1532
+ }
1533
+ if (hasMixedRoute && (hasV4Route || hasV3Route || hasV2Route)) {
1534
+ let metricsPrefix = 'Mixed';
1535
+ if (hasV4Route) {
1536
+ metricsPrefix += 'AndV4';
1537
+ }
1538
+ if (hasV3Route) {
1539
+ metricsPrefix += 'AndV3';
1540
+ }
1541
+ if (hasV2Route) {
1542
+ metricsPrefix += 'AndV2';
1543
+ }
1544
+ metric_1.metric.putMetric(`${metricsPrefix}SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1545
+ metric_1.metric.putMetric(`${metricsPrefix}SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1546
+ if (hasV4Route && (currencyIn.isNative || currencyOut.isNative)) {
1547
+ // Keep track of this edge case https://linear.app/uniswap/issue/ROUTE-303/tech-debt-split-route-can-have-different-ethweth-input-or-output#comment-bba53758
1548
+ metric_1.metric.putMetric(`${metricsPrefix}SplitRouteWithNativeToken`, 1, metric_1.MetricLoggerUnit.Count);
1549
+ metric_1.metric.putMetric(`${metricsPrefix}SplitRouteWithNativeTokenForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1550
+ }
1551
+ }
1552
+ else if (hasV4Route && hasV3Route && hasV2Route) {
1553
+ metric_1.metric.putMetric(`V4AndV3AndV2SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1554
+ metric_1.metric.putMetric(`V4AndV3AndV2SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1555
+ if (currencyIn.isNative || currencyOut.isNative) {
1556
+ // Keep track of this edge case https://linear.app/uniswap/issue/ROUTE-303/tech-debt-split-route-can-have-different-ethweth-input-or-output#comment-bba53758
1557
+ metric_1.metric.putMetric(`V4AndV3AndV2SplitRouteWithNativeToken`, 1, metric_1.MetricLoggerUnit.Count);
1558
+ metric_1.metric.putMetric(`V4AndV3AndV2SplitRouteWithNativeTokenForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1559
+ }
1560
+ }
1561
+ else if (hasMixedRoute) {
1562
+ if (routeAmounts.length > 1) {
1563
+ metric_1.metric.putMetric(`MixedSplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1564
+ metric_1.metric.putMetric(`MixedSplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1565
+ }
1566
+ else {
1567
+ metric_1.metric.putMetric(`MixedRoute`, 1, metric_1.MetricLoggerUnit.Count);
1568
+ metric_1.metric.putMetric(`MixedRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1569
+ }
1570
+ }
1571
+ else if (hasV4Route) {
1572
+ if (routeAmounts.length > 1) {
1573
+ metric_1.metric.putMetric(`V4SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1574
+ metric_1.metric.putMetric(`V4SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1575
+ }
1576
+ }
1577
+ else if (hasV3Route) {
1578
+ if (routeAmounts.length > 1) {
1579
+ metric_1.metric.putMetric(`V3SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1580
+ metric_1.metric.putMetric(`V3SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1581
+ }
1582
+ else {
1583
+ metric_1.metric.putMetric(`V3Route`, 1, metric_1.MetricLoggerUnit.Count);
1584
+ metric_1.metric.putMetric(`V3RouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1585
+ }
1586
+ }
1587
+ else if (hasV2Route) {
1588
+ if (routeAmounts.length > 1) {
1589
+ metric_1.metric.putMetric(`V2SplitRoute`, 1, metric_1.MetricLoggerUnit.Count);
1590
+ metric_1.metric.putMetric(`V2SplitRouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1591
+ }
1592
+ else {
1593
+ metric_1.metric.putMetric(`V2Route`, 1, metric_1.MetricLoggerUnit.Count);
1594
+ metric_1.metric.putMetric(`V2RouteForChain${this.chainId}`, 1, metric_1.MetricLoggerUnit.Count);
1595
+ }
1596
+ }
1597
+ }
1598
+ calculateOptimalRatio(position, sqrtRatioX96, zeroForOne) {
1599
+ const upperSqrtRatioX96 = v3_sdk_1.TickMath.getSqrtRatioAtTick(position.tickUpper);
1600
+ const lowerSqrtRatioX96 = v3_sdk_1.TickMath.getSqrtRatioAtTick(position.tickLower);
1601
+ // returns Fraction(0, 1) for any out of range position regardless of zeroForOne. Implication: function
1602
+ // cannot be used to determine the trading direction of out of range positions.
1603
+ if (jsbi_1.default.greaterThan(sqrtRatioX96, upperSqrtRatioX96) ||
1604
+ jsbi_1.default.lessThan(sqrtRatioX96, lowerSqrtRatioX96)) {
1605
+ return new sdk_core_1.Fraction(0, 1);
1606
+ }
1607
+ const precision = jsbi_1.default.BigInt('1' + '0'.repeat(18));
1608
+ let optimalRatio = new sdk_core_1.Fraction(v3_sdk_1.SqrtPriceMath.getAmount0Delta(sqrtRatioX96, upperSqrtRatioX96, precision, true), v3_sdk_1.SqrtPriceMath.getAmount1Delta(sqrtRatioX96, lowerSqrtRatioX96, precision, true));
1609
+ if (!zeroForOne)
1610
+ optimalRatio = optimalRatio.invert();
1611
+ return optimalRatio;
1612
+ }
1613
+ async userHasSufficientBalance(fromAddress, tradeType, amount, quote) {
1614
+ try {
1615
+ const neededBalance = tradeType === sdk_core_1.TradeType.EXACT_INPUT ? amount : quote;
1616
+ let balance;
1617
+ if (neededBalance.currency.isNative) {
1618
+ balance = await this.provider.getBalance(fromAddress);
1619
+ }
1620
+ else {
1621
+ const tokenContract = Erc20__factory_1.Erc20__factory.connect(neededBalance.currency.address, this.provider);
1622
+ balance = await tokenContract.balanceOf(fromAddress);
1623
+ }
1624
+ return balance.gte(bignumber_1.BigNumber.from(neededBalance.quotient.toString()));
1625
+ }
1626
+ catch (e) {
1627
+ log_1.log.error(e, 'Error while checking user balance');
1628
+ return false;
1629
+ }
1630
+ }
1631
+ absoluteValue(fraction) {
1632
+ const numeratorAbs = jsbi_1.default.lessThan(fraction.numerator, jsbi_1.default.BigInt(0))
1633
+ ? jsbi_1.default.unaryMinus(fraction.numerator)
1634
+ : fraction.numerator;
1635
+ const denominatorAbs = jsbi_1.default.lessThan(fraction.denominator, jsbi_1.default.BigInt(0))
1636
+ ? jsbi_1.default.unaryMinus(fraction.denominator)
1637
+ : fraction.denominator;
1638
+ return new sdk_core_1.Fraction(numeratorAbs, denominatorAbs);
1639
+ }
1640
+ getBlockNumberPromise() {
1641
+ return (0, async_retry_1.default)(async (_b, attempt) => {
1642
+ if (attempt > 1) {
1643
+ log_1.log.info(`Get block number attempt ${attempt}`);
1644
+ }
1645
+ return this.provider.getBlockNumber();
1646
+ }, {
1647
+ retries: 2,
1648
+ minTimeout: 100,
1649
+ maxTimeout: 1000,
1650
+ });
1651
+ }
1652
+ // If we are requesting URv1.2, we need to keep entering cache
1653
+ // We want to skip cached routes access whenever "intent === INTENT.CACHING" or "hooksOption !== HooksOption.HOOKS_INCLUSIVE"
1654
+ // We keep this method as we might want to add more conditions in the future.
1655
+ static isAllowedToEnterCachedRoutes(intent, hooksOptions, swapRouter) {
1656
+ // intent takes highest precedence, as we need to ensure during caching intent, we do not enter cache no matter what
1657
+ if (intent !== undefined && intent === intent_1.INTENT.CACHING) {
1658
+ return false;
1659
+ }
1660
+ // in case we have URv1.2 request during QUOTE intent, we assume cached routes correctly returns mixed route w/o v4, if mixed is best
1661
+ // or v2/v3 is the best.
1662
+ // implicitly it means hooksOptions no longer matters for URv1.2
1663
+ // swapRouter has higher precedence than hooksOptions, because in case of URv1.2, we set hooksOptions = NO_HOOKS as default,
1664
+ // but swapRouter does not have any v4 pool for routing, so swapRouter should always use caching during QUOTE intent.
1665
+ if (swapRouter) {
1666
+ return true;
1667
+ }
1668
+ // in case we have URv2.0, and we are in QUOTE intent, we only want to enter cache when hooksOptions is default, HOOKS_INCLUSIVE
1669
+ if (hooksOptions !== undefined &&
1670
+ hooksOptions !== util_1.HooksOptions.HOOKS_INCLUSIVE) {
1671
+ return false;
1672
+ }
1673
+ return true;
1674
+ }
1675
+ }
1676
+ exports.AlphaRouter = AlphaRouter;
1677
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxwaGEtcm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3JvdXRlcnMvYWxwaGEtcm91dGVyL2FscGhhLXJvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx3REFBcUQ7QUFDckQsd0RBQXlFO0FBQ3pFLHFGQUE2RDtBQUM3RCx5REFNa0M7QUFDbEMscURBTWdDO0FBRWhDLDZFQUE0RTtBQUM1RSxpREFBc0Q7QUFDdEQsaURBTThCO0FBQzlCLGlEQUFzRDtBQUN0RCw4REFBZ0M7QUFDaEMsZ0RBQXdCO0FBQ3hCLG9EQUF1QjtBQUN2Qiw0REFBbUM7QUFFbkMsK0NBb0N5QjtBQUN6Qiw2RkFHcUQ7QUFLckQsdUVBRzBDO0FBRTFDLHlFQUEyRTtBQUMzRSxtRUFBK0U7QUFDL0UsdUZBR2tEO0FBQ2xELG9FQUcwQztBQUMxQyw0RUFJOEM7QUFDOUMsb0VBRzBDO0FBRTFDLG9GQUFpRjtBQUNqRixvRUFHMEM7QUFDMUMsK0VBQTRFO0FBQzVFLHFDQVdvQjtBQUNwQixnREFBb0Q7QUFDcEQsOENBSTJCO0FBQzNCLHdFQUF3RTtBQUN4RSx3RUFHd0M7QUFDeEMsOENBQTJDO0FBQzNDLHdDQUFxQztBQUNyQyxrRUFHcUM7QUFDckMsOENBQTZEO0FBQzdELHdGQVdnRDtBQUNoRCxvRUFBaUU7QUFDakUsc0VBQW1FO0FBQ25FLHNDQW9CbUI7QUFFbkIscUNBR2tCO0FBUWxCLGlFQUE4RTtBQUM5RSxxRkFBK0U7QUFDL0UseUVBVXlDO0FBQ3pDLHNEQUF5RDtBQVN6RCw2R0FBNkc7QUFDN0csbUZBQW9GO0FBQ3BGLG1GQUFvRjtBQUNwRixtRkFBb0Y7QUFDcEYsdUNBQTZFO0FBQzdFLG1EQUErQztBQWlLL0MsTUFBYSxtQkFBdUIsU0FBUSxHQUFjO0lBQy9DLEdBQUcsQ0FBQyxHQUFXLEVBQUUsS0FBUTtRQUNoQyxPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzdDLENBQUM7Q0FDRjtBQUpELGtEQUlDO0FBRUQsTUFBYSxvQkFBcUIsU0FBUSxLQUFhO0lBQ3JELFlBQVksR0FBRyxLQUFlO1FBQzVCLHVFQUF1RTtRQUN2RSxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3BELENBQUM7Q0FDRjtBQUxELG9EQUtDO0FBOExELE1BQWEsV0FBVztJQTBDdEIsWUFBWSxFQUNWLE9BQU8sRUFDUCxRQUFRLEVBQ1Isa0JBQWtCLEVBQ2xCLGtCQUFrQixFQUNsQixjQUFjLEVBQ2QsY0FBYyxFQUNkLG9CQUFvQixFQUNwQixjQUFjLEVBQ2QsZUFBZSxFQUNmLGtCQUFrQixFQUNsQixhQUFhLEVBQ2Isd0JBQXdCLEVBQ3hCLGtCQUFrQixFQUNsQixnQkFBZ0IsRUFDaEIsaUJBQWlCLEVBQ2pCLGlCQUFpQixFQUNqQixpQkFBaUIsRUFDakIseUJBQXlCLEVBQ3pCLGtCQUFrQixFQUNsQixzQkFBc0IsRUFDdEIsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxvQkFBb0IsRUFDcEIsdUJBQXVCLEVBQ3ZCLGVBQWUsRUFDZixXQUFXLEVBQ1gsV0FBVyxFQUNYLGNBQWMsRUFDZCx1Q0FBdUMsRUFDdkMsWUFBWSxFQUNaLGlEQUFpRCxFQUNqRCx3QkFBd0IsR0FDTjtRQUNsQixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsa0JBQWtCO1lBQ3JCLGtCQUFrQixhQUFsQixrQkFBa0IsY0FBbEIsa0JBQWtCLEdBQ2xCLElBQUksb0NBQXdCLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFPLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsY0FBYztZQUNqQixjQUFjLGFBQWQsY0FBYyxjQUFkLGNBQWMsR0FDZCxJQUFJLDZDQUFxQixDQUN2QixJQUFJLENBQUMsT0FBTyxFQUNaLElBQUksOEJBQWMsQ0FBQyxJQUFBLHVCQUFjLEVBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQ3BFLElBQUksdUJBQVcsQ0FBQyxJQUFJLG9CQUFTLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQ2xFLENBQUM7UUFDSixJQUFJLENBQUMsY0FBYztZQUNqQixjQUFjLGFBQWQsY0FBYyxjQUFkLGNBQWMsR0FDZCxJQUFJLGlDQUFxQixDQUN2QixJQUFJLENBQUMsT0FBTyxFQUNaLElBQUksOEJBQWMsQ0FBQyxJQUFBLHVCQUFjLEVBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQ3BFLElBQUksdUJBQVcsQ0FBQyxJQUFJLG9CQUFTLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQ2xFLENBQUM7UUFDSixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixJQUFJLENBQUMsb0JBQW9CLEdBQUcsb0JBQW9CLENBQUM7UUFFakQsSUFBSSxvQkFBb0IsRUFBRTtZQUN4QixJQUFJLENBQUMsb0JBQW9CLEdBQUcsb0JBQW9CLENBQUM7U0FDbEQ7YUFBTTtZQUNMLFFBQVEsT0FBTyxFQUFFO2dCQUNmLEtBQUssa0JBQU8sQ0FBQyxRQUFRLENBQUM7Z0JBQ3RCLEtBQUssa0JBQU8sQ0FBQyxlQUFlLENBQUM7Z0JBQzdCLEtBQUssa0JBQU8sQ0FBQyxnQkFBZ0I7b0JBQzNCLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLGdDQUFvQixDQUNsRCxPQUFPLEVBQ1AsUUFBUSxFQUNSLElBQUksQ0FBQyxrQkFBa0IsRUFDdkI7d0JBQ0UsT0FBTyxFQUFFLENBQUM7d0JBQ1YsVUFBVSxFQUFFLEdBQUc7d0JBQ2YsVUFBVSxFQUFFLElBQUk7cUJBQ2pCLEVBQ0QsQ0FBQyxDQUFDLEVBQUUsRUFBRTt3QkFDSixPQUFPOzRCQUNMLGNBQWMsRUFBRSxHQUFHOzRCQUNuQixlQUFlLEVBQUUsT0FBUzs0QkFDMUIsbUJBQW1CLEVBQUUsR0FBRzt5QkFDekIsQ0FBQztvQkFDSixDQUFDLEVBQ0QsQ0FBQyxDQUFDLEVBQUUsRUFBRTt3QkFDSixPQUFPOzRCQUNMLGdCQUFnQixFQUFFLE9BQVM7NEJBQzNCLGNBQWMsRUFBRSxFQUFFO3lCQUNuQixDQUFDO29CQUNKLENBQUMsRUFDRCxDQUFDLENBQUMsRUFBRSxFQUFFO3dCQUNKLE9BQU87NEJBQ0wsZ0JBQWdCLEVBQUUsT0FBUzs0QkFDM0IsY0FBYyxFQUFFLEVBQUU7eUJBQ25CLENBQUM7b0JBQ0osQ0FBQyxFQUNELENBQUMsQ0FBQyxFQUFFLEVBQUU7d0JBQ0osT0FBTzs0QkFDTCxlQUFlLEVBQUUsQ0FBQyxFQUFFOzRCQUNwQixRQUFRLEVBQUU7Z0NBQ1IsT0FBTyxFQUFFLElBQUk7Z0NBQ2Isc0JBQXNCLEVBQUUsQ0FBQztnQ0FDekIsbUJBQW1CLEVBQUUsQ0FBQyxFQUFFOzZCQUN6Qjt5QkFDRixDQUFDO29CQUNKLENBQUMsQ0FDRixDQUFDO29CQUNGLE1BQU07Z0JBQ1IsS0FBSyxrQkFBTyxDQUFDLElBQUksQ0FBQztnQkFDbEIsS0FBSyxrQkFBTyxDQUFDLEtBQUssQ0FBQztnQkFDbkIsS0FBSyxrQkFBTyxDQUFDLElBQUksQ0FBQztnQkFDbEIsS0FBSyxrQkFBTyxDQUFDLFVBQVUsQ0FBQztnQkFDeEIsS0FBSyxrQkFBTyxDQUFDLGdCQUFnQixDQUFDO2dCQUM5QixLQUFLLGtCQUFPLENBQUMsYUFBYSxDQUFDO2dCQUMzQixLQUFLLGtCQUFPLENBQUMsWUFBWSxDQUFDO2dCQUMxQixLQUFLLGtCQUFPLENBQUMsUUFBUSxDQUFDO2dCQUN0QixLQUFLLGtCQUFPLENBQUMsV0FBVyxDQUFDO2dCQUN6QixLQUFLLGtCQUFPLENBQUMsT0FBTztvQkFDbEIsSUFBSSxDQUFDLG9CQUFvQixHQUFHLElBQUksZ0NBQW9CLENBQ2xELE9BQU8sRUFDUCxRQUFRLEVBQ1IsSUFBSSxDQUFDLGtCQUFrQixFQUN2Qjt3QkFDRSxPQUFPLEVBQUUsQ0FBQzt3QkFDVixVQUFVLEVBQUUsR0FBRzt3QkFDZixVQUFVLEVBQUUsSUFBSTtxQkFDakIsRUFDRCxDQUFDLENBQUMsRUFBRSxFQUFFO3dCQUNKLE9BQU87NEJBQ0wsY0FBYyxFQUFFLEVBQUU7NEJBQ2xCLGVBQWUsRUFBRSxPQUFTOzRCQUMxQixtQkFBbUIsRUFBRSxHQUFHO3lCQUN6QixDQUFDO29CQUNKLENBQUMsRUFDRCxDQUFDLENBQUMsRUFBRSxFQUFFO3dCQUNKLE9BQU87NEJBQ0wsZ0JBQWdCLEVBQUUsT0FBUzs0QkFDM0IsY0FBYyxFQUFFLEVBQUU7eUJBQ25CLENBQUM7b0JBQ0osQ0FBQyxFQUNELENBQUMsQ0FBQyxFQUFFLEVBQUU7d0JBQ0osT0FBTzs0QkFDTCxnQkFBZ0IsRUFBRSxPQUFTOzRCQUMzQixjQUFjLEVBQUUsRUFBRTt5QkFDbkIsQ0FBQztvQkFDSixDQUFDLEVBQ0QsQ0FBQyxDQUFDLEVBQUUsRUFBRTt3QkFDSixPQUFPOzRCQUNMLGVBQWUsRUFBRSxDQUFDLEVBQUU7NEJBQ3BCLFFBQVEsRUFBRTtnQ0FDUixPQUFPLEVBQUUsSUFBSTtnQ0FDYixzQkFBc0IsRUFBRSxDQUFDO2dDQUN6QixtQkFBbUIsRUFBRSxDQUFDLEVBQUU7NkJBQ3pCO3lCQUNGLENBQUM7b0JBQ0osQ0FBQyxDQUNGLENBQUM7b0JBQ0YsTUFBTTtnQkFDUixLQUFLLGtCQUFPLENBQUMsTUFBTTtvQkFDakIsSUFBSSxDQUFDLG9CQUFvQixHQUFHLElBQUksZ0NBQW9CLENBQ2xELE9BQU8sRUFDUCxRQUFRLEVBQ1IsSUFBSSxDQUFDLGtCQUFrQixFQUN2Qjt3QkFDRSxPQUFPLEVBQUUsQ0FBQzt3QkFDVixVQUFVLEVBQUUsR0FBRzt3QkFDZixVQUFVLEVBQUUsSUFBSTtxQkFDakIsRUFDRCxDQUFDLENBQUMsRUFBRSxFQUFFO3dCQUNKLE9BQU87NEJBQ0wsY0FBYyxFQUFFLEVBQUU7NEJBQ2xCLGVBQWUsRUFBRSxPQUFTOzRCQUMxQixtQkFBbUIsRUFBRSxHQUFHO3lCQUN6QixDQUFDO29CQUNKLENBQUMsRUFDRCxDQUFDLENBQUMsRUFBRSxFQUFFO3dCQUNKLE9BQU87NEJBQ0wsZ0JBQWdCLEVBQUUsT0FBUzs0QkFDM0IsY0FBYyxFQUFFLEVBQUU7eUJBQ25CLENBQUM7b0JBQ0osQ0FBQyxFQUNELENBQUMsQ0FBQyxFQUFFLEVBQUU7d0JBQ0osT0FBTzs0QkFDTCxnQkFBZ0IsRUFBRSxPQUFTOzRCQUMzQixjQUFjLEVBQUUsRUFBRTt5QkFDbkIsQ0FBQztvQkFDSixDQUFDLEVBQ0QsQ0FBQyxDQUFDLEVBQUUsRUFBRTt3QkFDSixPQUFPOzRCQUNMLGVBQWUsRUFBRSxDQUFDLEVBQUU7NEJBQ3BCLFFBQVEsRUFBRTtnQ0FDUixPQUFPLEVBQUUsSUFBSTtnQ0FDYixzQkFBc0IsRUFBRSxDQUFDO2dDQUN6QixtQkFBbUIsRUFBRSxDQUFDLEVBQUU7NkJBQ3pCO3lCQUNGLENBQUM7b0JBQ0osQ0FBQyxDQUNGLENBQUM7b0JBQ0YsTUFBTTtnQkFDUixLQUFLLGtCQUFPLENBQUMsWUFBWSxDQUFDO2dCQUMxQixLQUFLLGtCQUFPLENBQUMsZUFBZSxDQUFDO2dCQUM3QixLQUFLLGtCQUFPLENBQUMsZ0JBQWdCO29CQUMzQixJQUFJLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxnQ0FBb0IsQ0FDbEQsT0FBTyxFQUNQLFFBQVEsRUFDUixJQUFJLENBQUMsa0JBQWtCLEVBQ3ZCO3dCQUNFLE9BQU8sRUFBRSxDQUFDO3dCQUNWLFVBQVUsRUFBRSxHQUFHO3dCQUNmLFVBQVUsRUFBRSxJQUFJO3FCQUNqQixFQUNELENBQUMsQ0FBQyxFQUFFLEVBQUU7d0JBQ0osT0FBTzs0QkFDTCxjQUFjLEVBQUUsRUFBRTs0QkFDbEIsZUFBZSxFQUFFLFFBQVU7NEJBQzNCLG1CQUFtQixFQUFFLEdBQUc7eUJBQ3pCLENBQUM7b0JBQ0osQ0FBQyxFQUNELENBQUMsQ0FBQyxFQUFFLEVBQUU7d0JBQ0osT0FBTzs0QkFDTCxnQkFBZ0IsRUFBRSxRQUFVOzRCQUM1QixjQUFjLEVBQUUsQ0FBQzt5QkFDbEIsQ0FBQztvQkFDSixDQUFDLEVBQ0QsQ0FBQyxDQUFDLEVBQUUsRUFBRTt3QkFDSixPQUFPOzRCQUNMLGdCQUFnQixFQUFFLFFBQVU7NEJBQzVCLGNBQWMsRUFBRSxDQUFDO3lCQUNsQixDQUFDO29CQUNKLENBQUMsQ0FDRixDQUFDO29CQUNGLE1BQU07Z0JBQ1IsS0FBSyxrQkFBTyxDQUFDLElBQUksQ0FBQztnQkFDbEIsS0FBSyxrQkFBTyxDQUFDLGNBQWM7b0JBQ3pCLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLGdDQUFvQixDQUNsRCxPQUFPLEVBQ1AsUUFBUSxFQUNSLElBQUksQ0FBQyxrQkFBa0IsRUFDdkI7d0JBQ0UsT0FBTyxFQUFFLENBQUM7d0JBQ1YsVUFBVSxFQUFFLEdBQUc7d0JBQ2YsVUFBVSxFQUFFLElBQUk7cUJBQ2pCLEVBQ0QsQ0FBQyxDQUFDLEVBQUUsRUFBRTt3QkFDSixPQUFPOzRCQUNMLGNBQWMsRUFBRSxFQUFFOzRCQUNsQixlQUFlLEVBQUUsT0FBUzs0QkFDMUIsbUJBQW1CLEVBQUUsR0FBRzt5QkFDekIsQ0FBQztvQkFDSixDQUFDLEVBQ0QsQ0FBQyxDQUFDLEVBQUUsRUFBRTt3QkFDSixPQUFPOzRCQUNMLGdCQUFnQixFQUFFLE9BQVM7NEJBQzNCLGNBQWMsRUFBRSxDQUFDO3lCQUNsQixDQUFDO29CQUNKLENBQUMsRUFDRCxDQUFDLENBQUMsRUFBRSxFQUFFO3dCQUNKLE9BQU87NEJBQ0wsZ0JBQWdCLEVBQUUsT0FBUzs0QkFDM0IsY0FBYyxFQUFFLENBQUM7eUJBQ2xCLENBQUM7b0JBQ0osQ0FBQyxDQUNGLENBQUM7b0JBQ0YsTUFBTTtnQkFDUixLQUFLLGtCQUFPLENBQUMsY0FBYyxDQUFDO2dCQUM1QixLQUFLLGtCQUFPLENBQUMsT0FBTyxDQUFDO2dCQUNyQixLQUFLLGtCQUFPLENBQUMsT0FBTyxDQUFDO2dCQUNyQixLQUFLLGtCQUFPLENBQUMsT0FBTztvQkFDbEIsSUFBSSxDQUFDLG9CQUFvQixHQUFHLElBQUksZ0NBQW9CLENBQ2xELE9BQU8sRUFDUCxRQUFRLEVBQ1IsSUFBSSxDQUFDLGtCQUFrQixFQUN2QiwyQ0FBYSxDQUFDLE9BQU8sQ0FBQyxFQUN0QixDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsMENBQVksQ0FBQyxPQUFPLENBQUUsRUFDN0IsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLHlEQUEyQixDQUFDLE9BQU8sQ0FBRSxFQUM1QyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsNERBQThCLENBQUMsT0FBTyxDQUFFLEVBQy9DLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxrREFBb0IsQ0FBQyxPQUFPLENBQUUsQ0FDdEMsQ0FBQztvQkFDRixNQUFNO2dCQUNSO29CQUNFLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLGdDQUFvQixDQUNsRCxPQUFPLEVBQ1AsUUFBUSxFQUNSLElBQUksQ0FBQyxrQkFBa0IsRUFDdkIsbURBQXFCLEVBQ3JCLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxrREFBb0IsRUFDM0IsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGlFQUFtQyxFQUMxQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsb0VBQXNDLEVBQzdDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQywwREFBNEIsQ0FDcEMsQ0FBQztvQkFDRixNQUFNO2FBQ1Q7U0FDRjtRQUVELElBQUksc0JBQXNCLEVBQUU7WUFDMUIsSUFBSSxDQUFDLHNCQUFzQixHQUFHLHNCQUFzQixDQUFDO1NBQ3REO2FBQU0sSUFBSSxJQUFJLENBQUMsT0FBTyxLQUFLLGtCQUFPLENBQUMsT0FBTyxFQUFFO1lBQzNDLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLGlEQUFzQixDQUN0RCxJQUFJLENBQUMsT0FBTyxFQUNaLElBQUksQ0FBQyxrQkFBa0IsRUFDdkIsSUFBSSx1QkFBVyxDQUFDLElBQUksb0JBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FDcEUsQ0FBQztTQUNIO1FBQ0QsSUFBSSx1QkFBdUIsRUFBRTtZQUMzQixJQUFJLENBQUMsdUJBQXVCLEdBQUcsdUJBQXVCLENBQUM7U0FDeEQ7YUFBTTtZQUNMLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxJQUFJLG1DQUF1QixDQUN4RCxJQUFJLENBQUMsT0FBTyxFQUNaLElBQUksdUJBQVcsQ0FBQyxJQUFJLG9CQUFTLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQ25FLElBQUksMENBQXNCLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FDbkQsQ0FBQztTQUNIO1FBQ0QsSUFBSSxDQUFDLGNBQWM7WUFDakIsY0FBYyxhQUFkLGNBQWMsY0FBZCxjQUFjLEdBQ2QsSUFBSSxpQ0FBcUIsQ0FDdkIsT0FBTyxFQUNQLElBQUksOEJBQWMsQ0FDaEIsT0FBTyxFQUNQLElBQUksQ0FBQyxrQkFBa0IsRUFDdkIsSUFBSSxDQUFDLHVCQUF1QixDQUM3QixFQUNELElBQUksdUJBQVcsQ0FBQyxJQUFJLG9CQUFTLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQ2pFLENBQUM7UUFFSixJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsYUFBZixlQUFlLGNBQWYsZUFBZSxHQUFJLElBQUksMkJBQWUsRUFBRSxDQUFDO1FBRWhFLElBQUksQ0FBQyx3QkFBd0I7WUFDM0Isd0JBQXdCLGFBQXhCLHdCQUF3QixjQUF4Qix3QkFBd0IsR0FDeEIsSUFBSSxzREFBd0IsQ0FDMUIsT0FBTyxFQUNQLHVDQUErQixFQUMvQixJQUFJLHVCQUFXLENBQUMsSUFBSSxvQkFBUyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUNuRSxDQUFDO1FBQ0osSUFBSSxDQUFDLGFBQWE7WUFDaEIsYUFBYSxhQUFiLGFBQWEsY0FBYixhQUFhLEdBQ2IsSUFBSSw0Q0FBZ0MsQ0FDbEMsT0FBTyxFQUNQLElBQUksdUJBQVcsQ0FBQyxJQUFJLG9CQUFTLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQ2xFLElBQUksc0RBQXdCLENBQzFCLE9BQU8sRUFDUCw0QkFBa0IsRUFDbEIsSUFBSSx1QkFBVyxDQUFDLElBQUksb0JBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FDbkUsRUFDRCxJQUFJLDhCQUFhLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUNwRCxDQUFDO1FBQ0osSUFBSSxDQUFDLGVBQWUsR0FBRyxlQUFlLGFBQWYsZUFBZSxjQUFmLGVBQWUsR0FBSSxJQUFJLGtDQUFlLEVBQUUsQ0FBQztRQUVoRSxNQUFNLFNBQVMsR0FBRyxJQUFBLDJCQUFrQixFQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTlDLGdJQUFnSTtRQUNoSSxJQUFJLGtCQUFrQixFQUFFO1lBQ3RCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztTQUM5QzthQUFNO1lBQ0wsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksMkNBQStCLENBQUM7Z0JBQzVELElBQUkscUNBQXlCLENBQzNCLE9BQU8sRUFDUCxJQUFJLCtCQUFtQixDQUNyQixPQUFPLEVBQ1AsZ0VBQWdFLFNBQVMsT0FBTyxFQUNoRixTQUFTLEVBQ1QsQ0FBQyxDQUNGLEVBQ0QsSUFBSSx1QkFBVyxDQUFDLElBQUksb0JBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FDbEU7Z0JBQ0QsSUFBSSxvQ0FBd0IsQ0FBQyxPQUFPLENBQUM7YUFDdEMsQ0FBQyxDQUFDO1NBQ0o7UUFFRCxJQUFJLGtCQUFrQixFQUFFO1lBQ3RCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztTQUM5QzthQUFNO1lBQ0wsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksMkNBQStCLENBQUM7Z0JBQzVELElBQUkscUNBQXlCLENBQzNCLE9BQU8sRUFDUCxJQUFJLCtCQUFtQixDQUNyQixPQUFPLEVBQ1AsZ0VBQWdFLFNBQVMsT0FBTyxFQUNoRixTQUFTLEVBQ1QsQ0FBQyxDQUNGLEVBQ0QsSUFBSSx1QkFBVyxDQUFDLElBQUksb0JBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FDbEU7Z0JBQ0QsSUFBSSxvQ0FBd0IsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQzthQUMzRCxDQUFDLENBQUM7U0FDSjtRQUVELElBQUksQ0FBQyxZQUFZO1lBQ2YsWUFBWSxhQUFaLFlBQVksY0FBWixZQUFZLEdBQUksSUFBQSwyQ0FBb0MsRUFBQyxPQUFPLENBQUMsQ0FBQztRQUNoRSxJQUFJLGtCQUFrQixFQUFFO1lBQ3RCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztTQUM5QzthQUFNO1lBQ0wsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksMkNBQStCLENBQUM7Z0JBQzVELElBQUkscUNBQXlCLENBQzNCLE9BQU8sRUFDUCxJQUFJLCtCQUFtQixDQUNyQixPQUFPLEVBQ1AsZ0VBQWdFLFNBQVMsT0FBTyxFQUNoRixTQUFTLEVBQ1QsQ0FBQyxDQUNGLEVBQ0QsSUFBSSx1QkFBVyxDQUFDLElBQUksb0JBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FDbEU7Z0JBQ0QsSUFBSSxvQ0FBd0IsQ0FDMUIsT0FBTyxFQUNQLElBQUksQ0FBQyxjQUFjLEVBQ25CLElBQUksQ0FBQyxZQUFZLENBQ2xCO2FBQ0YsQ0FBQyxDQUFDO1NBQ0o7UUFFRCxJQUFJLHdCQUEyQyxDQUFDO1FBQ2hELElBQUksMkJBQWUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQzdDLHdCQUF3QixHQUFHLElBQUksbUNBQXVCLENBQ3BELE9BQU8sRUFDUCxJQUFJLG1DQUF1QixDQUFDLElBQUksQ0FBQyxRQUEyQixDQUFDLEVBQzdELElBQUksa0NBQXNCLENBQUMsSUFBSSxDQUFDLFFBQTJCLENBQUMsQ0FDN0QsQ0FBQztTQUNIO2FBQU07WUFDTCx3QkFBd0IsR0FBRyxJQUFJLHFDQUF5QixDQUN0RCxnQ0FBdUIsQ0FDeEIsQ0FBQztTQUNIO1FBRUQsSUFBSSxDQUFDLGdCQUFnQjtZQUNuQixnQkFBZ0IsYUFBaEIsZ0JBQWdCLGNBQWhCLGdCQUFnQixHQUNoQixJQUFJLHFDQUF5QixDQUMzQixPQUFPLEVBQ1Asd0JBQXdCLEVBQ3hCLElBQUksdUJBQVcsQ0FDYixJQUFJLG9CQUFTLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUMvQyxDQUNGLENBQUM7UUFDSixJQUFJLENBQUMsaUJBQWlCO1lBQ3BCLGlCQUFpQixhQUFqQixpQkFBaUIsY0FBakIsaUJBQWlCLEdBQUksSUFBSSxtREFBMEIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGlCQUFpQjtZQUNwQixpQkFBaUIsYUFBakIsaUJBQWlCLGNBQWpCLGlCQUFpQixHQUFJLElBQUksbURBQTBCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JFLElBQUksQ0FBQyxpQkFBaUI7WUFDcEIsaUJBQWlCLGFBQWpCLGlCQUFpQixjQUFqQixpQkFBaUIsR0FBSSxJQUFJLG1EQUEwQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNyRSxJQUFJLENBQUMseUJBQXlCO1lBQzVCLHlCQUF5QixhQUF6Qix5QkFBeUIsY0FBekIseUJBQXlCLEdBQUksSUFBSSxvRUFBa0MsRUFBRSxDQUFDO1FBRXhFLElBQUksQ0FBQyxrQkFBa0I7WUFDckIsa0JBQWtCLGFBQWxCLGtCQUFrQixjQUFsQixrQkFBa0IsR0FDbEIsSUFBSSw4QkFBa0IsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRWhFLElBQ0UsT0FBTyxLQUFLLGtCQUFPLENBQUMsWUFBWTtZQUNoQyxPQUFPLEtBQUssa0JBQU8sQ0FBQyxlQUFlLEVBQ25DO1lBQ0EsSUFBSSxDQUFDLGlCQUFpQjtnQkFDcEIsdUJBQXVCLGFBQXZCLHVCQUF1QixjQUF2Qix1QkFBdUIsR0FDdkIsSUFBSSwyQ0FBdUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ3ZEO1FBRUQsMEJBQTBCO1FBQzFCLDZGQUE2RjtRQUM3RixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksa0JBQVEsQ0FDMUIsSUFBSSxDQUFDLGtCQUFrQixFQUN2QixJQUFJLENBQUMsY0FBYyxFQUNuQixJQUFJLENBQUMsZUFBZSxFQUNwQixJQUFJLENBQUMsaUJBQWlCLEVBQ3RCLElBQUksQ0FBQyxhQUFhLEVBQ2xCLElBQUksQ0FBQyxPQUFPLEVBQ1osSUFBSSxDQUFDLHdCQUF3QixFQUM3QixJQUFJLENBQUMsc0JBQXNCLEVBQzNCLElBQUksQ0FBQyxpQkFBaUIsQ0FDdkIsQ0FBQztRQUVGLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxrQkFBUSxDQUMxQixJQUFJLENBQUMsa0JBQWtCLEVBQ3ZCLElBQUksQ0FBQyxjQUFjLEVBQ25CLElBQUksQ0FBQyxvQkFBb0IsRUFDekIsSUFBSSxDQUFDLGFBQWEsRUFDbEIsSUFBSSxDQUFDLE9BQU8sRUFDWixJQUFJLENBQUMsd0JBQXdCLEVBQzdCLElBQUksQ0FBQyxzQkFBc0IsQ0FDNUIsQ0FBQztRQUVGLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxvQkFBUSxDQUMxQixJQUFJLENBQUMsa0JBQWtCLEVBQ3ZCLElBQUksQ0FBQyxjQUFjLEVBQ25CLElBQUksQ0FBQyxvQkFBb0IsRUFDekIsSUFBSSxDQUFDLGFBQWEsRUFDbEIsSUFBSSxDQUFDLE9BQU8sRUFDWixJQUFJLENBQUMsd0JBQXdCLEVBQzdCLElBQUksQ0FBQyxzQkFBc0IsQ0FDNUIsQ0FBQztRQUVGLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxxQkFBVyxDQUNoQyxJQUFJLENBQUMsa0JBQWtCLEVBQ3ZCLElBQUksQ0FBQyxjQUFjLEVBQ25CLElBQUksQ0FBQyxrQkFBa0IsRUFDdkIsSUFBSSxDQUFDLGNBQWMsRUFDbkIsSUFBSSxDQUFDLGtCQUFrQixFQUN2QixJQUFJLENBQUMsY0FBYyxFQUNuQixJQUFJLENBQUMsb0JBQW9CLEVBQ3pCLElBQUksQ0FBQyxhQUFhLEVBQ2xCLElBQUksQ0FBQyxPQUFPLEVBQ1osSUFBSSxDQUFDLHdCQUF3QixFQUM3QixJQUFJLENBQUMsc0JBQXNCLENBQzVCLENBQUM7UUFFRixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsYUFBWCxXQUFXLGNBQVgsV0FBVyxHQUFJLHFCQUFZLENBQUM7UUFDL0MsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLGFBQVgsV0FBVyxjQUFYLFdBQVcsR0FBSSxtQkFBWSxDQUFDO1FBQy9DLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxhQUFkLGNBQWMsY0FBZCxjQUFjLEdBQUksc0JBQWUsQ0FBQztRQUN4RCxJQUFJLENBQUMsdUNBQXVDO1lBQzFDLHVDQUF1QyxhQUF2Qyx1Q0FBdUMsY0FBdkMsdUNBQXVDLEdBQ3ZDLG9EQUE2QyxDQUFDO1FBRWhELElBQUksQ0FBQyxpREFBaUQ7WUFDcEQsaURBQWlELENBQUM7UUFFcEQsdUZBQXVGO1FBQ3ZGLElBQUksQ0FBQyx3QkFBd0IsR0FBRyx3QkFBd0IsQ0FBQztJQUMzRCxDQUFDO0lBRU0sS0FBSyxDQUFDLFlBQVksQ0FDdkIsYUFBNkIsRUFDN0IsYUFBNkIsRUFDN0IsUUFBa0IsRUFDbEIsZ0JBQWtDLEVBQ2xDLGlCQUFxQyxFQUNyQyxnQkFBNEMsSUFBQSx3Q0FBK0IsRUFDekUsSUFBSSxDQUFDLE9BQU8sQ0FDYjtRQUVELElBQ0UsYUFBYSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQzFFO1lBQ0EsQ0FBQyxhQUFhLEVBQUUsYUFBYSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsYUFBYSxDQUFDLENBQUM7U0FDakU7UUFFRCxJQUFJLG1CQUFtQixHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FDbEQsUUFBUSxFQUNSLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUMxQixJQUFJLENBQ0wsQ0FBQztRQUNGLDZEQUE2RDtRQUM3RCxJQUFJLFVBQW1CLENBQUM7UUFDeEIsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUMsU0FBUyxFQUFFO1lBQ2xELFVBQVUsR0FBRyxJQUFJLENBQUM7U0FDbkI7YUFBTSxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQyxTQUFTLEVBQUU7WUFDekQsVUFBVSxHQUFHLEtBQUssQ0FBQztTQUNwQjthQUFNO1lBQ0wsVUFBVSxHQUFHLElBQUksbUJBQVEsQ0FDdkIsYUFBYSxDQUFDLFFBQVEsRUFDdEIsYUFBYSxDQUFDLFFBQVEsQ0FDdkIsQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUNuQyxJQUFJLENBQUMsVUFBVTtnQkFBRSxtQkFBbUIsR0FBRyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQztTQUNyRTtRQUVELE1BQU0sQ0FBQyxZQUFZLEVBQUUsYUFBYSxDQUFDLEdBQUcsVUFBVTtZQUM5QyxDQUFDLENBQUMsQ0FBQyxhQUFhLEVBQUUsYUFBYSxDQUFDO1lBQ2hDLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUVuQyxJQUFJLFlBQVksR0FBRyxtQkFBbUIsQ0FBQztRQUN2QyxJQUFJLGtCQUFrQixHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUM7UUFDdkMsSUFBSSxZQUFZLEdBQWEsVUFBVTtZQUNyQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXO1lBQzNCLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUM5QixJQUFJLElBQUksR0FBcUIsSUFBSSxDQUFDO1FBQ2xDLElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMxQixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDVixzRUFBc0U7UUFDdEUsT0FBTyxDQUFDLGFBQWEsRUFBRTtZQUNyQixDQUFDLEVBQUUsQ0FBQztZQUNKLElBQUksQ0FBQyxHQUFHLGdCQUFnQixDQUFDLGFBQWEsRUFBRTtnQkFDdEMsU0FBRyxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO2dCQUNwQyxPQUFPO29CQUNMLE1BQU0sRUFBRSwwQkFBaUIsQ0FBQyxjQUFjO29CQUN4QyxLQUFLLEVBQUUseUJBQXlCO2lCQUNqQyxDQUFDO2FBQ0g7WUFFRCxNQUFNLFlBQVksR0FBRyxJQUFBLGtEQUFzQixFQUN6QyxZQUFZLEVBQ1osWUFBWSxFQUNaLFlBQVksRUFDWixhQUFhLENBQ2QsQ0FBQztZQUNGLElBQUksWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDM0IsU0FBRyxDQUFDLElBQUksQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO2dCQUM3QyxPQUFPO29CQUNMLE1BQU0sRUFBRSwwQkFBaUIsQ0FBQyxjQUFjO2lCQUN6QyxDQUFDO2FBQ0g7WUFDRCxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUNyQixZQUFZLEVBQ1osYUFBYSxDQUFDLFFBQVEsRUFDdEIsb0JBQVMsQ0FBQyxXQUFXLEVBQ3JCLFNBQVMsZ0RBRUosSUFBQSx3Q0FBK0IsRUFBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQzdDLGFBQWE7Z0JBQ2hCLDJGQUEyRjtnQkFDM0YseUVBQXlFO2dCQUN6RSxTQUFTLEVBQUUsQ0FBQyxxQkFBUSxDQUFDLEVBQUUsRUFBRSxxQkFBUSxDQUFDLEVBQUUsQ0FBQyxJQUV4QyxDQUFDO1lBQ0YsSUFBSSxDQUFDLElBQUksRUFBRTtnQkFDVCxTQUFHLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLENBQUM7Z0JBQzdDLE9BQU87b0JBQ0wsTUFBTSxFQUFFLDBCQUFpQixDQUFDLGNBQWM7b0JBQ3hDLEtBQUssRUFBRSxnQkFBZ0I7aUJBQ3hCLENBQUM7YUFDSDtZQUVELE1BQU0sbUJBQW1CLEdBQUcsWUFBWSxDQUFDLFFBQVEsQ0FDL0MsSUFBSSxDQUFDLEtBQU0sQ0FBQyxXQUFXLENBQ3hCLENBQUM7WUFDRixNQUFNLG9CQUFvQixHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN6RSxNQUFNLFFBQVEsR0FBRyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQztZQUVsRSxJQUFJLHFCQUFxQixDQUFDO1lBQzFCLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7Z0JBQzNCLElBQUksS0FBSyxDQUFDLFFBQVEsS0FBSyxxQkFBUSxDQUFDLEVBQUUsRUFBRTtvQkFDbEMsTUFBTSxPQUFPLEdBQUcsS0FBOEIsQ0FBQztvQkFDL0MsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFO3dCQUN0QyxJQUNFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDOzRCQUN4QyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQzs0QkFDeEMsSUFBSSxDQUFDLEdBQUcsS0FBSyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFDOUI7NEJBQ0EscUJBQXFCLEdBQUcsY0FBSSxDQUFDLE1BQU0sQ0FDakMsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBRSxDQUFDLFFBQVEsRUFBRSxDQUM3QyxDQUFDOzRCQUNGLFlBQVksR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQ3ZDLFFBQVEsRUFDUixjQUFJLENBQUMsTUFBTSxDQUFDLHFCQUFzQixDQUFDLFFBQVEsRUFBRSxDQUFDLEVBQzlDLFVBQVUsQ0FDWCxDQUFDO3lCQUNIO29CQUNILENBQUMsQ0FBQyxDQUFDO2lCQUNKO1lBQ0gsQ0FBQyxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMscUJBQXFCLEVBQUU7Z0JBQzFCLFlBQVksR0FBRyxtQkFBbUIsQ0FBQzthQUNwQztZQUNELGFBQWE7Z0JBQ1gsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUM7b0JBQzlCLElBQUksQ0FBQyxhQUFhLENBQ2hCLFFBQVEsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FDckQsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUVuRCxJQUFJLGFBQWEsSUFBSSxxQkFBcUIsRUFBRTtnQkFDMUMsa0JBQWtCLEdBQUcsSUFBSSxhQUFJLENBQzNCLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUNwQixRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFDcEIsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQ2pCLHFCQUFxQixFQUNyQixRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFDdkIsaUJBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxxQkFBcUIsQ0FBQyxFQUNsRCxRQUFRLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUMvQixDQUFDO2FBQ0g7WUFDRCxZQUFZLEdBQUcsSUFBSSxDQUFDLEtBQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFeEUsU0FBRyxDQUFDLElBQUksQ0FDTjtnQkFDRSxZQUFZLEVBQUUsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNqRCxZQUFZLEVBQUUsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNqRCxRQUFRLEVBQUUsUUFBUSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUN6QyxtQkFBbUIsRUFBRSxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDL0Qsb0JBQW9CLEVBQUUsb0JBQW9CLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ2pFLG1CQUFtQixFQUFFLGdCQUFnQixDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ3JFLFVBQVUsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFO2FBQ3pCLEVBQ0QsbUNBQW1DLENBQ3BDLENBQUM7WUFFRixJQUFJLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQzNCLFNBQUcsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztnQkFDOUIsT0FBTztvQkFDTCxNQUFNLEVBQUUsMEJBQWlCLENBQUMsY0FBYztvQkFDeEMsS0FBSyxFQUFFLGlEQUFpRDtpQkFDekQsQ0FBQzthQUNIO1NBQ0Y7UUFFRCxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ1QsT0FBTztnQkFDTCxNQUFNLEVBQUUsMEJBQWlCLENBQUMsY0FBYztnQkFDeEMsS0FBSyxFQUFFLGdCQUFnQjthQUN4QixDQUFDO1NBQ0g7UUFDRCxJQUFJLGdCQUE4QyxDQUFDO1FBQ25ELElBQUksaUJBQWlCLEVBQUU7WUFDckIsZ0JBQWdCLEdBQUcsTUFBTSxJQUFJLENBQUMsK0JBQStCLENBQzNELElBQUksQ0FBQyxLQUFLLEVBQ1YsaUJBQWlCLEVBQ2pCO2dCQUNFLHFCQUFxQixFQUFFLFlBQVk7Z0JBQ25DLHNCQUFzQixFQUFFLGFBQWE7Z0JBQ3JDLG9CQUFvQixFQUFFLFFBQVE7YUFDL0IsQ0FDRixDQUFDO1NBQ0g7UUFFRCxPQUFPO1lBQ0wsTUFBTSxFQUFFLDBCQUFpQixDQUFDLE9BQU87WUFDakMsTUFBTSxrQ0FBTyxJQUFJLEtBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLGtCQUFrQixHQUFFO1NBQ3hFLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsS0FBSyxDQUNoQixNQUFzQixFQUN0QixhQUF1QixFQUN2QixTQUFvQixFQUNwQixVQUF3QixFQUN4Qix1QkFBbUQsRUFBRTs7UUFFckQsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDO1FBRTlCLE1BQU0sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLEdBQy9CLElBQUksQ0FBQyxtQ0FBbUMsQ0FDdEMsU0FBUyxFQUNULE1BQU0sRUFDTixhQUFhLENBQ2QsQ0FBQztRQUVKLE1BQU0sa0JBQWtCLEdBQ3RCLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixDQUFDLG1CQUFtQixDQUNwRCxDQUFDLFdBQVcsQ0FBQyxFQUNiLG9CQUFvQixDQUNyQixDQUFDO1FBRUosTUFBTSxrQkFBa0IsR0FDdEIsTUFBQSxNQUFBLGtCQUFrQixDQUFDLElBQUEsMEJBQW1CLEVBQUMsV0FBVyxDQUFDLENBQUMsMENBQUUsY0FBYywwQ0FDaEUsa0JBQWtCLENBQUM7UUFDekIsTUFBTSxzQkFBc0IsR0FDMUIsTUFBQSxNQUFBLGtCQUFrQixDQUFDLElBQUEsMEJBQW1CLEVBQUMsV0FBVyxDQUFDLENBQUMsMENBQUUsY0FBYywwQ0FDaEUsc0JBQXNCLENBQUM7UUFFN0IsaUZBQWlGO1FBQ2pGLDZIQUE2SDtRQUM3SCx5RUFBeUU7UUFDekUsSUFDRSxDQUFBLE1BQUEsTUFBQSxNQUFBLGtCQUFrQixDQUNoQixJQUFBLDBCQUFtQixFQUFDLFdBQVcsQ0FBQyxDQUNqQywwQ0FBRSxjQUFjLDBDQUFFLFNBQVMsMENBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQzthQUNuQyxNQUFBLE1BQUEsTUFBQSxrQkFBa0IsQ0FDaEIsSUFBQSwwQkFBbUIsRUFBQyxXQUFXLENBQUMsQ0FDakMsMENBQUUsY0FBYywwQ0FBRSxVQUFVLDBDQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQSxFQUNwQztZQUNBLElBQUksa0JBQWtCLElBQUksc0JBQXNCLEVBQUU7Z0JBQ2hELDJGQUEyRjtnQkFDM0YsaUVBQWlFO2dCQUNqRSxvRkFBb0Y7Z0JBQ3BGLElBQUksQ0FBQSxVQUFVLGFBQVYsVUFBVSx1QkFBVixVQUFVLENBQUUsSUFBSSxNQUFLLGlCQUFRLENBQUMsZ0JBQWdCLEVBQUU7b0JBQ2xELFVBQVUsQ0FBQyxHQUFHLEdBQUcsU0FBUyxDQUFDO29CQUMzQixVQUFVLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQztpQkFDaEM7Z0JBRUQsZUFBTSxDQUFDLFNBQVMsQ0FDZCxtQ0FBbUMsRUFDbkMsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQzthQUNIO2lCQUFNO2dCQUNMLGVBQU0sQ0FBQyxTQUFTLENBQ2QsZ0NBQWdDLEVBQ2hDLENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7YUFDSDtTQUNGO1FBRUQsSUFBSSxTQUFTLEtBQUssb0JBQVMsQ0FBQyxZQUFZLEVBQUU7WUFDeEMsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxnQkFBZ0IsQ0FDekQsTUFBTSxFQUNOLFNBQVMsRUFDVCxrQkFBa0IsRUFDbEIsc0JBQXNCLEVBQ3RCLFVBQVUsQ0FDWCxDQUFDO1lBQ0YsSUFBSSxhQUFhLElBQUksYUFBYSxDQUFDLFdBQVcsQ0FBQyxpQkFBSSxDQUFDLEVBQUU7Z0JBQ3BELDRFQUE0RTtnQkFDNUUseUlBQXlJO2dCQUN6SSw0SEFBNEg7Z0JBQzVILDRFQUE0RTtnQkFDNUUscURBQXFEO2dCQUNyRCw0Q0FBNEM7Z0JBQzVDLE1BQU0sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2FBQ3BDO1NBQ0Y7UUFFRCxlQUFNLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUMsZUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsR0FBRyxVQUFVLENBQUMsTUFBTSxJQUFJLFdBQVcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3pFLGVBQU0sQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLElBQUEsaUJBQVUsRUFBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQ3RELGVBQU0sQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLElBQUEsaUJBQVUsRUFBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ3hELGVBQU0sQ0FBQyxXQUFXLENBQ2hCLFdBQVcsRUFDWCxTQUFTLEtBQUssb0JBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUM3RCxDQUFDO1FBRUYsZUFBTSxDQUFDLFNBQVMsQ0FDZCx5QkFBeUIsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUN2QyxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO1FBRUYsc0ZBQXNGO1FBQ3RGLHVCQUF1QjtRQUN2QixNQUFNLFdBQVcsR0FDZixNQUFBLG9CQUFvQixDQUFDLFdBQVcsbUNBQUksSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFFbkUsTUFBTSxhQUFhLEdBQXNCLGdCQUFDLENBQUMsS0FBSyxDQUM5QztZQUNFLDhEQUE4RDtZQUM5RCxlQUFlLEVBQUUsSUFBSTtZQUNyQixtQkFBbUIsRUFBRSxJQUFJO1lBQ3pCLHNCQUFzQixFQUFFLEtBQUs7U0FDOUIsRUFDRCxJQUFBLHdDQUErQixFQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFDN0Msb0JBQW9CLEVBQ3BCLEVBQUUsV0FBVyxFQUFFLENBQ2hCLENBQUM7UUFFRixJQUFJLGFBQWEsQ0FBQyxZQUFZLEVBQUU7WUFDOUIsU0FBRyxDQUFDLElBQUksQ0FBQywrQkFBK0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDMUU7UUFFRCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQzNDLE1BQU0sV0FBVyxFQUNqQixNQUFNLG9CQUFvQixDQUFDLFdBQVcsQ0FDdkMsQ0FBQztRQUVGLDBGQUEwRjtRQUMxRixNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMsUUFBUTtZQUNyQyxDQUFDLENBQUMsQ0FDQSxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQzdELENBQUMsaUJBQWlCLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQztZQUMzQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBRWQsTUFBTSxjQUFjLG1DQUNmLGFBQWEsS0FDaEIsV0FBVyxFQUNYLHFCQUFxQixFQUFFLElBQUEsMkJBQWUsRUFDcEMsSUFBSSxDQUFDLE9BQU8sRUFDWixNQUFNLENBQUMsUUFBUSxFQUNmLGFBQWEsQ0FDZCxFQUNELFFBQVE7WUFDUixzQkFBc0I7WUFDdEIsa0JBQWtCLEdBQ25CLENBQUM7UUFFRixNQUFNLEVBQ0osVUFBVSxFQUFFLFVBQVUsRUFDdEIsVUFBVSxFQUFFLFVBQVUsRUFDdEIsVUFBVSxFQUFFLFVBQVUsRUFDdEIsa0JBQWtCLEVBQUUsa0JBQWtCLEdBQ3ZDLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUN6QixXQUFXLEVBQ1gsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQ3ZCLGFBQWEsQ0FBQyxPQUFPLEVBQ3JCLGNBQWMsQ0FDZixDQUFDO1FBRUYseUZBQXlGO1FBQ3pGLG9EQUFvRDtRQUNwRCxNQUFNLFNBQVMsR0FBZSxLQUFLLENBQUMsSUFBSSxDQUN0QyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQzFDLENBQUM7UUFFRixNQUFNLFNBQVMsR0FDYixNQUFBLGFBQWEsQ0FBQyxrQkFBa0IsbUNBQ2hDLENBQUMsTUFBTSxDQUFBLE1BQUEsSUFBSSxDQUFDLG9CQUFvQiwwQ0FBRSxZQUFZLENBQzVDLElBQUksQ0FBQyxPQUFPLEVBQ1osTUFBTSxFQUNOLGFBQWEsRUFDYixTQUFTLEVBQ1QsU0FBUyxDQUNWLENBQUEsQ0FBQyxDQUFDO1FBRUwscUJBQXFCO1FBQ3JCLElBQUksWUFBc0MsQ0FBQztRQUUzQyxnSUFBZ0k7UUFDaEksaUdBQWlHO1FBQ2pHLHdGQUF3RjtRQUN4Rix3SUFBd0k7UUFDeEksa0ZBQWtGO1FBQ2xGLDZIQUE2SDtRQUM3SCwrRUFBK0U7UUFDL0UsdUdBQXVHO1FBQ3ZHLE1BQU0scUJBQXFCLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxxQkFBUSxDQUFDLENBQUMsQ0FBQztRQUMvRCxNQUFNLHFCQUFxQixHQUFHLElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ2pELE1BQU0sVUFBVSxHQUNkLENBQUMsVUFBVTtZQUNYLFVBQVUsQ0FBQyxJQUFJLEtBQUssaUJBQVEsQ0FBQyxjQUFjO1lBQzNDLENBQUMsVUFBVSxDQUFDLElBQUksS0FBSyxpQkFBUSxDQUFDLGdCQUFnQjtnQkFDNUMsVUFBVSxDQUFDLE9BQU8sS0FBSyw2Q0FBc0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4RCxJQUFJLFVBQVUsRUFBRTtZQUNkLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxxQkFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzFDLElBQUkscUJBQXFCLENBQUMsR0FBRyxDQUFDLHFCQUFRLENBQUMsRUFBRSxDQUFDLEVBQUU7Z0JBQzFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxxQkFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2FBQzNDO1NBQ0Y7UUFDRCxNQUFNLGlDQUFpQyxHQUNyQyxxQkFBcUIsQ0FBQyxJQUFJLEtBQUsscUJBQXFCLENBQUMsSUFBSTtZQUN6RCxDQUFDLEdBQUcscUJBQXFCLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUM1QyxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQ3BDLENBQUM7UUFFSiwrR0FBK0c7UUFDL0csSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxxQkFBUSxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQzNDLGFBQWEsQ0FBQyxZQUFZLEdBQUcsbUJBQVksQ0FBQyxRQUFRLENBQUM7U0FDcEQ7UUFFRCx5RkFBeUY7UUFDekYsbUdBQW1HO1FBQ25HLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFO1lBQy9CLGFBQWEsQ0FBQyxZQUFZLEdBQUcsbUJBQVksQ0FBQyxlQUFlLENBQUM7U0FDM0Q7UUFFRCxTQUFHLENBQUMsS0FBSyxDQUFDLHdDQUF3QyxFQUFFO1lBQ2xELHFCQUFxQixFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUM7WUFDeEQscUJBQXFCLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQztZQUN4RCxpQ0FBaUM7WUFDakMsY0FBYyxFQUFFLFVBQVUsYUFBVixVQUFVLHVCQUFWLFVBQVUsQ0FBRSxJQUFJO1lBQ2hDLGdDQUFnQyxFQUM5QixDQUFBLFVBQVUsYUFBVixVQUFVLHVCQUFWLFVBQVUsQ0FBRSxJQUFJLE1BQUssaUJBQVEsQ0FBQyxnQkFBZ0I7Z0JBQzVDLENBQUMsQ0FBQyxVQUFVLGFBQVYsVUFBVSx1QkFBVixVQUFVLENBQUUsT0FBTztnQkFDckIsQ0FBQyxDQUFDLEtBQUs7U0FDWixDQUFDLENBQUM7UUFFSCxJQUNFLGFBQWEsQ0FBQyxlQUFlO1lBQzdCLFNBQVMsS0FBSyxxQkFBUyxDQUFDLFFBQVE7WUFDaEMsV0FBVyxDQUFDLDRCQUE0QixDQUN0QyxhQUFhLENBQUMsTUFBTSxFQUNwQixhQUFhLENBQUMsWUFBWSxFQUMxQixVQUFVLENBQ1gsRUFDRDtZQUNBLElBQUksaUNBQWlDLEVBQUU7Z0JBQ3JDLElBQ0UsU0FBUyxDQUFDLFFBQVEsQ0FBQyxxQkFBUSxDQUFDLEVBQUUsQ0FBQztvQkFDL0IsQ0FBQyxVQUFVLENBQUMsUUFBUSxJQUFJLFdBQVcsQ0FBQyxRQUFRLENBQUMsRUFDN0M7b0JBQ0EsTUFBTSxDQUFDLHlCQUF5QixFQUFFLGtCQUFrQixDQUFDLEdBQ25ELE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQzt3QkFDaEIsTUFBQSxJQUFJLENBQUMsb0JBQW9CLDBDQUFFLGNBQWMsQ0FDdkMsSUFBSSxDQUFDLE9BQU8sRUFDWix3QkFBYyxDQUFDLGFBQWEsQ0FDMUIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQ3ZCLE1BQU0sQ0FBQyxRQUFRLENBQ2hCLEVBQ0QsYUFBYSxDQUFDLE9BQU8sRUFDckIsU0FBUyxFQUNULFNBQVMsRUFDVCxNQUFNLFdBQVcsRUFDakIsYUFBYSxDQUFDLHNCQUFzQixFQUNwQyxhQUFhLEVBQ2IsVUFBVSxDQUNYO3dCQUNELE1BQUEsSUFBSSxDQUFDLG9CQUFvQiwwQ0FBRSxjQUFjLENBQ3ZDLElBQUksQ0FBQyxPQUFPLEVBQ1osTUFBTSxFQUNOLGFBQWEsRUFDYixTQUFTLEVBQ1QsQ0FBQyxxQkFBUSxDQUFDLEVBQUUsQ0FBQyxFQUNiLE1BQU0sV0FBVyxFQUNqQixhQUFhLENBQUMsc0JBQXNCLEVBQ3BDLGFBQWEsRUFDYixVQUFVLENBQ1g7cUJBQ0YsQ0FBQyxDQUFDO29CQUVMLElBQ0UsQ0FBQyx5QkFBeUI7d0JBQ3hCLENBQUEseUJBQXlCLGFBQXpCLHlCQUF5Qix1QkFBekIseUJBQXlCLENBQUUsTUFBTSxDQUFDLE1BQU0sSUFBRyxDQUFDLENBQUM7d0JBQy9DLENBQUMsa0JBQWtCLElBQUksQ0FBQSxrQkFBa0IsYUFBbEIsa0JBQWtCLHVCQUFsQixrQkFBa0IsQ0FBRSxNQUFNLENBQUMsTUFBTSxJQUFHLENBQUMsQ0FBQyxFQUM3RDt3QkFDQSxZQUFZLEdBQUcsSUFBSSx3QkFBWSxDQUFDOzRCQUM5QixNQUFNLEVBQUU7Z0NBQ04sR0FBRyxDQUFDLE1BQUEsa0JBQWtCLGFBQWxCLGtCQUFrQix1QkFBbEIsa0JBQWtCLENBQUUsTUFBTSxtQ0FBSSxFQUFFLENBQUM7Z0NBQ3JDLEdBQUcsQ0FBQyxNQUFBLHlCQUF5QixhQUF6Qix5QkFBeUIsdUJBQXpCLHlCQUF5QixDQUFFLE1BQU0sbUNBQUksRUFBRSxDQUFDOzZCQUM3Qzs0QkFDRCxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87NEJBQ3JCLFVBQVUsRUFBRSxVQUFVOzRCQUN0QixXQUFXLEVBQUUsV0FBVzs0QkFDeEIsZ0JBQWdCLEVBQUUsU0FBUzs0QkFDM0IsV0FBVyxFQUFFLE1BQU0sV0FBVzs0QkFDOUIsU0FBUyxFQUFFLFNBQVM7NEJBQ3BCLGNBQWMsRUFDWixNQUFBLE1BQUEseUJBQXlCLGFBQXpCLHlCQUF5Qix1QkFBekIseUJBQXlCLENBQUUsY0FBYyxtQ0FDekMsa0JBQWtCLGFBQWxCLGtCQUFrQix1QkFBbEIsa0JBQWtCLENBQUUsY0FBYyxtQ0FDbEMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUU7NEJBQzVCLFlBQVksRUFDVixNQUFBLE1BQUEseUJBQXlCLGFBQXpCLHlCQUF5Qix1QkFBekIseUJBQXlCLENBQUUsWUFBWSxtQ0FDdkMsa0JBQWtCLGFBQWxCLGtCQUFrQix1QkFBbEIsa0JBQWtCLENBQUUsWUFBWSxtQ0FDaEMsNENBQXNCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQzt5QkFDdkMsQ0FBQyxDQUFDO3FCQUNKO2lCQUNGO3FCQUFNO29CQUNMLFlBQVksR0FBRyxNQUFNLENBQUEsTUFBQSxJQUFJLENBQUMsb0JBQW9CLDBDQUFFLGNBQWMsQ0FDNUQsSUFBSSxDQUFDLE9BQU8sRUFDWixNQUFNLEVBQ04sYUFBYSxFQUNiLFNBQVMsRUFDVCxTQUFTLEVBQ1QsTUFBTSxXQUFXLEVBQ2pCLGFBQWEsQ0FBQyxzQkFBc0IsRUFDcEMsYUFBYSxFQUNiLFVBQVUsQ0FDWCxDQUFBLENBQUM7aUJBQ0g7YUFDRjtTQUNGO1FBRUQsSUFBSSxJQUFBLGdDQUF5QixFQUFDLFlBQVksRUFBRSxhQUFhLENBQUMsRUFBRTtZQUMxRCxZQUFZLEdBQUcsU0FBUyxDQUFDO1NBQzFCO1FBRUQsZUFBTSxDQUFDLFNBQVMsQ0FDZCxhQUFhLENBQUMsZUFBZTtZQUMzQixDQUFDLENBQUMsMkJBQTJCO1lBQzdCLENBQUMsQ0FBQyw4QkFBOEIsRUFDbEMsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQztRQUVGLElBQ0UsU0FBUztZQUNULGFBQWEsQ0FBQyxlQUFlO1lBQzdCLFNBQVMsS0FBSyxxQkFBUyxDQUFDLFFBQVE7WUFDaEMsQ0FBQyxZQUFZLEVBQ2I7WUFDQSxlQUFNLENBQUMsU0FBUyxDQUNkLHVCQUF1QixTQUFTLEVBQUUsRUFDbEMsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQztZQUNGLFNBQUcsQ0FBQyxJQUFJLENBQ047Z0JBQ0UsVUFBVSxFQUFFLFVBQVUsQ0FBQyxNQUFNO2dCQUM3QixpQkFBaUIsRUFBRSxJQUFBLGlCQUFVLEVBQUMsVUFBVSxDQUFDO2dCQUN6QyxXQUFXLEVBQUUsV0FBVyxDQUFDLE1BQU07Z0JBQy9CLGtCQUFrQixFQUFFLElBQUEsaUJBQVUsRUFBQyxXQUFXLENBQUM7Z0JBQzNDLFNBQVM7Z0JBQ1QsTUFBTSxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUU7Z0JBQ3hCLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztnQkFDckIsU0FBUyxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDO2FBQ3hDLEVBQ0QsdUJBQXVCLFNBQVMsUUFBUSxJQUFJLENBQUMsK0JBQStCLENBQzFFLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxDQUNWLEVBQUUsQ0FDSixDQUFDO1NBQ0g7YUFBTSxJQUFJLFlBQVksSUFBSSxhQUFhLENBQUMsZUFBZSxFQUFFO1lBQ3hELGVBQU0sQ0FBQyxTQUFTLENBQ2Qsc0JBQXNCLFNBQVMsRUFBRSxFQUNqQyxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO1lBQ0YsU0FBRyxDQUFDLElBQUksQ0FDTjtnQkFDRSxVQUFVLEVBQUUsVUFBVSxDQUFDLE1BQU07Z0JBQzdCLGlCQUFpQixFQUFFLElBQUEsaUJBQVUsRUFBQyxVQUFVLENBQUM7Z0JBQ3pDLFdBQVcsRUFBRSxXQUFXLENBQUMsTUFBTTtnQkFDL0Isa0JBQWtCLEVBQUUsSUFBQSxpQkFBVSxFQUFDLFdBQVcsQ0FBQztnQkFDM0MsU0FBUztnQkFDVCxNQUFNLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRTtnQkFDeEIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO2dCQUNyQixTQUFTLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUM7YUFDeEMsRUFDRCxzQkFBc0IsU0FBUyxRQUFRLElBQUksQ0FBQywrQkFBK0IsQ0FDekUsVUFBVSxFQUNWLFdBQVcsRUFDWCxTQUFTLENBQ1YsRUFBRSxDQUNKLENBQUM7U0FDSDtRQUVELElBQUkseUJBQXlCLEdBQzNCLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEIsSUFBSSxZQUFZLEVBQUU7WUFDaEIseUJBQXlCLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUNwRCxVQUFVLEVBQ1YsV0FBVyxFQUNYLFlBQVksRUFDWixNQUFNLFdBQVcsRUFDakIsTUFBTSxFQUNOLGFBQWEsRUFDYixTQUFTLEVBQ1QsYUFBYSxFQUNiLFVBQVUsRUFDVixVQUFVLEVBQ1Ysa0JBQWtCLEVBQ2xCLFdBQVcsRUFDWCxVQUFVLEVBQ1YsVUFBVSxFQUNWLGNBQWMsQ0FDZixDQUFDO1NBQ0g7UUFFRCxJQUFJLHlCQUF5QixHQUMzQixPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxZQUFZLElBQUksU0FBUyxLQUFLLHFCQUFTLENBQUMsUUFBUSxFQUFFO1lBQ3JELHlCQUF5QixHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FDcEQsTUFBTSxFQUNOLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxFQUNULGFBQWEsRUFDYixTQUFTLEVBQ1QsYUFBYSxFQUNiLFVBQVUsRUFDVixVQUFVLEVBQ1Ysa0JBQWtCLEVBQ2xCLFdBQVcsRUFDWCxVQUFVLEVBQ1YsVUFBVSxFQUNWLGNBQWMsQ0FDZixDQUFDO1NBQ0g7UUFFRCxNQUFNLENBQUMsa0JBQWtCLEVBQUUsa0JBQWtCLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDakUseUJBQXlCO1lBQ3pCLHlCQUF5QjtTQUMxQixDQUFDLENBQUM7UUFFSCxJQUFJLFlBQWtDLENBQUM7UUFDdkMsSUFBSSxlQUFlLEdBQUcsS0FBSyxDQUFDO1FBQzVCLElBQUksU0FBUyxLQUFLLHFCQUFTLENBQUMsUUFBUSxJQUFJLGtCQUFrQixFQUFFO1lBQzFELHdDQUF3QztZQUN4QyxvQ0FBb0M7WUFDcEMsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFFdEMsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUNyQixrQkFBa0IsQ0FBQyxNQUFNLEVBQ3pCLGFBQWEsRUFDYixJQUFJLENBQUMsY0FBYyxFQUNuQixJQUFJLENBQUMsY0FBYyxFQUNuQixJQUFJLENBQUMsY0FBYyxDQUNwQixDQUFDO1lBRUYsZUFBTSxDQUFDLFNBQVMsQ0FDZCw0QkFBNEIsRUFDNUIsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLGtCQUFrQixFQUMvQix5QkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7WUFFRixTQUFHLENBQUMsSUFBSSxDQUNOLGdCQUFnQixTQUFTLHlDQUF5QyxDQUNuRSxDQUFDO1lBQ0YsZUFBZSxHQUFHLElBQUksQ0FBQztZQUN2QixZQUFZLEdBQUcsa0JBQWtCLENBQUM7U0FDbkM7YUFBTTtZQUNMLFNBQUcsQ0FBQyxJQUFJLENBQ04sZ0JBQWdCLFNBQVMsMkNBQTJDLENBQ3JFLENBQUM7WUFDRixZQUFZLEdBQUcsa0JBQWtCLENBQUM7U0FDbkM7UUFFRCxJQUNFLFNBQVMsS0FBSyxxQkFBUyxDQUFDLFVBQVU7WUFDbEMsa0JBQWtCO1lBQ2xCLGtCQUFrQixFQUNsQjtZQUNBLE1BQU0sU0FBUyxHQUFHLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxRQUFRLENBQ2pELGtCQUFrQixDQUFDLEtBQUssQ0FDekIsQ0FBQztZQUNGLE1BQU0sb0JBQW9CLEdBQUcsa0JBQWtCLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUN2RSxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FDcEMsQ0FBQztZQUNGLE1BQU0sV0FBVyxHQUFHLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FDekQsa0JBQWtCLENBQUMsZ0JBQWdCLENBQ3BDLENBQUM7WUFFRixrSEFBa0g7WUFDbEgsSUFDRSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUNyQixDQUFDLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFDdkQ7Z0JBQ0EsSUFBSTtvQkFDRixrR0FBa0c7b0JBQ2xHLE1BQU0sZUFBZSxHQUFHLG9CQUFvQjt5QkFDekMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDO3lCQUMzQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBRWpCLGVBQU0sQ0FBQyxTQUFTLENBQ2QsbURBQW1ELEVBQ25ELE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLENBQUMsRUFDakMseUJBQWdCLENBQUMsT0FBTyxDQUN6QixDQUFDO29CQUVGLFNBQUcsQ0FBQyxJQUFJLENBQ047d0JBQ0UsY0FBYyxFQUFFLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUU7d0JBQ2xELGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFO3dCQUNsRCxTQUFTLEVBQUUsU0FBUyxDQUFDLE9BQU8sRUFBRTt3QkFDOUIseUJBQXlCLEVBQ3ZCLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRTt3QkFDL0MseUJBQXlCLEVBQ3ZCLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRTt3QkFDL0Msb0JBQW9CLEVBQUUsb0JBQW9CLENBQUMsT0FBTyxFQUFFO3dCQUNwRCxnQkFBZ0IsRUFBRSxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUU7d0JBQ2hFLGdCQUFnQixFQUFFLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRTt3QkFDaEUsV0FBVyxFQUFFLFdBQVcsQ0FBQyxRQUFRLEVBQUU7d0JBQ25DLGVBQWUsRUFBRSxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO3dCQUNyRCxlQUFlLEVBQUUsa0JBQWtCLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTt3QkFDckQsTUFBTSxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUU7d0JBQ3hCLGNBQWMsRUFBRSxZQUFZLGFBQVosWUFBWSx1QkFBWixZQUFZLENBQUUsY0FBYzt3QkFDNUMsSUFBSSxFQUFFLElBQUksQ0FBQywrQkFBK0IsQ0FDeEMsVUFBVSxFQUNWLFdBQVcsRUFDWCxTQUFTLENBQ1Y7d0JBQ0QsV0FBVztxQkFDWixFQUNELGdEQUFnRCxJQUFJLENBQUMsK0JBQStCLENBQ2xGLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxDQUNWLEVBQUUsQ0FDSixDQUFDO2lCQUNIO2dCQUFDLE9BQU8sS0FBSyxFQUFFO29CQUNkLHNEQUFzRDtvQkFDdEQsOEVBQThFO29CQUM5RSxJQUNFLEtBQUssWUFBWSxVQUFVO3dCQUMzQixLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxFQUMxQzt3QkFDQSxTQUFHLENBQUMsS0FBSyxDQUNQOzRCQUNFLG9CQUFvQixFQUFFLG9CQUFvQixDQUFDLE9BQU8sRUFBRTs0QkFDcEQsa0NBQWtDLEVBQ2hDLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRTt5QkFDaEQsRUFDRCxvQ0FBb0MsQ0FDckMsQ0FBQzt3QkFFRixlQUFNLENBQUMsU0FBUyxDQUNkLDJEQUEyRCxFQUMzRCxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO3FCQUNIO29CQUVELHVEQUF1RDtpQkFDeEQ7YUFDRjtTQUNGO1FBRUQsSUFBSSxzQkFBc0IsR0FBRyxLQUFLLENBQUM7UUFDbkMsTUFBTSw0Q0FBNEMsR0FDaEQsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUc7WUFDbkIsQ0FBQyxNQUFBLElBQUksQ0FBQyxpREFBaUQsbUNBQUksQ0FBQyxDQUFDLENBQUM7UUFFaEUsbUZBQW1GO1FBQ25GLCtHQUErRztRQUMvRywrSkFBK0o7UUFDL0oscURBQXFEO1FBQ3JELElBQUksNENBQTRDLEVBQUU7WUFDaEQsc0dBQXNHO1lBQ3RHLG1IQUFtSDtZQUNuSCxxR0FBcUc7WUFDckcsc0VBQXNFO1lBQ3RFLElBQUksQ0FBQyxDQUFBLFlBQVksYUFBWixZQUFZLHVCQUFaLFlBQVksQ0FBRSxVQUFVLENBQUMsTUFBTSxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUEsRUFBRTtnQkFDdEQseUlBQXlJO2dCQUN6SSxzRkFBc0Y7Z0JBQ3RGLElBQUksYUFBYSxDQUFDLE1BQU0sS0FBSyxlQUFNLENBQUMsT0FBTyxFQUFFO29CQUMzQywrR0FBK0c7b0JBQy9HLHNCQUFzQixHQUFHLElBQUksQ0FBQztvQkFDOUIsZUFBTSxDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLEVBQUUseUJBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBRXRFLHVFQUF1RTtvQkFDdkUsaURBQWlEO29CQUNqRCw0REFBNEQ7b0JBQzVELE1BQU0sdUJBQXVCLEdBQzNCLGtCQUFrQixhQUFsQixrQkFBa0IsY0FBbEIsa0JBQWtCO29CQUNsQiwrSEFBK0g7b0JBQy9ILDZIQUE2SDtvQkFDN0gsQ0FBQyxNQUFNLElBQUksQ0FBQyxxQkFBcUIsQ0FDL0IsTUFBTSxFQUNOLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxFQUNULGFBQWEsRUFDYixTQUFTLEVBQ1QsYUFBYSxFQUNiLFVBQVUsRUFDVixVQUFVLEVBQ1Ysa0JBQWtCLEVBQ2xCLFdBQVcsRUFDWCxVQUFVLEVBQ1YsVUFBVSxFQUNWLGNBQWMsQ0FDZixDQUFDLENBQUM7b0JBRUwsSUFBSSx1QkFBdUIsRUFBRTt3QkFDM0IsTUFBTSxhQUFhLEdBQUcsd0JBQVksQ0FBQyx5QkFBeUIsQ0FDMUQsdUJBQXVCLENBQUMsTUFBTSxFQUM5QixJQUFJLENBQUMsT0FBTyxFQUNaLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxDQUFDLElBQUksRUFBRSxFQUNoQixNQUFNLFdBQVcsRUFDakIsU0FBUyxFQUNULE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FDakIsQ0FBQzt3QkFFRixNQUFNLElBQUksQ0FBQyxxQkFBcUIsQ0FDOUIsTUFBTSxFQUNOLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxFQUNULHdCQUF3QixFQUN4QixhQUFhLEVBQ2IsYUFBYSxDQUFDLG9CQUFvQixDQUNuQyxDQUFDO3FCQUNIO2lCQUNGO2FBQ0Y7U0FDRjtRQUVELElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDakIsT0FBTyxJQUFJLENBQUM7U0FDYjtRQUVELE1BQU0sRUFDSixLQUFLLEVBQ0wsZ0JBQWdCLEVBQ2hCLGdCQUFnQixFQUNoQixNQUFNLEVBQUUsWUFBWSxFQUNwQiwwQkFBMEIsRUFDMUIsbUJBQW1CLEVBQ25CLHdCQUF3QixHQUN6QixHQUFHLFlBQVksQ0FBQztRQUVqQiwrRkFBK0Y7UUFDL0Ysc0VBQXNFO1FBQ3RFLDJFQUEyRTtRQUMzRSx5R0FBeUc7UUFDekcsSUFDRSxJQUFJLENBQUMsb0JBQW9CO1lBQ3pCLGFBQWEsQ0FBQyxtQkFBbUI7WUFDakMsU0FBUyxLQUFLLHFCQUFTLENBQUMsUUFBUTtZQUNoQyxrQkFBa0IsRUFDbEI7WUFDQSxJQUFJLHNCQUFzQixFQUFFO2dCQUMxQixzR0FBc0c7Z0JBQ3RHLGdGQUFnRjtnQkFDaEYsMkNBQTJDO2dCQUMzQyx1TEFBdUw7Z0JBQ3ZMLDJKQUEySjtnQkFDM0osZUFBTSxDQUFDLFNBQVMsQ0FDZCxpQ0FBaUMsYUFBYSxDQUFDLE1BQU0sRUFBRSxFQUN2RCxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO2FBQ0g7WUFFRCxtQ0FBbUM7WUFDbkMsTUFBTSxhQUFhLEdBQUcsd0JBQVksQ0FBQyx5QkFBeUIsQ0FDMUQsa0JBQWtCLENBQUMsTUFBTSxFQUN6QixJQUFJLENBQUMsT0FBTyxFQUNaLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxDQUFDLElBQUksRUFBRSxFQUNoQixNQUFNLFdBQVcsRUFDakIsU0FBUyxFQUNULE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FDakIsQ0FBQztZQUVGLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUM5QixNQUFNLEVBQ04sVUFBVSxFQUNWLFdBQVcsRUFDWCxTQUFTLEVBQ1Qsd0JBQXdCLEVBQ3hCLGFBQWEsRUFDYixhQUFhLENBQUMsb0JBQW9CLENBQ25DLENBQUM7U0FDSDtRQUVELGVBQU0sQ0FBQyxTQUFTLENBQ2QscUJBQXFCLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFDbkMsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQztRQUVGLHVEQUF1RDtRQUN2RCxNQUFNLEtBQUssR0FBRyxJQUFBLDZCQUFVLEVBQ3RCLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxFQUNULFlBQVksQ0FDYixDQUFDO1FBRUYsSUFBSSxnQkFBOEMsQ0FBQztRQUVuRCw4RkFBOEY7UUFDOUYsOEJBQThCO1FBQzlCLElBQUksVUFBVSxFQUFFO1lBQ2QsZ0JBQWdCLEdBQUcsSUFBQSw0Q0FBeUIsRUFDMUMsS0FBSyxFQUNMLFVBQVUsRUFDVixJQUFJLENBQUMsT0FBTyxDQUNiLENBQUM7U0FDSDtRQUVELE1BQU0sY0FBYyxHQUNsQixTQUFTLEtBQUssb0JBQVMsQ0FBQyxZQUFZO1lBQ2xDLENBQUMsQ0FBQyxjQUFjLENBQUMsNEhBQTRIO1lBQzdJLENBQUMsQ0FBQyxLQUFLLENBQUM7UUFDWixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLGdCQUFnQixDQUN6RCxjQUFjLEVBQ2QsU0FBUyxFQUNULGtCQUFrQixFQUNsQixzQkFBc0IsRUFDdEIsVUFBVSxDQUNYLENBQUM7UUFDRixNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMscUJBQXFCLENBQ25FLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUFFLHVIQUF1SDtRQUMvSCxhQUFhLENBQ2QsQ0FBQztRQUVGLDhHQUE4RztRQUM5RyxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FDbEQsU0FBUyxFQUNULEtBQUssRUFDTCxrQkFBa0IsQ0FDbkIsQ0FBQztRQUVGLE1BQU0seUJBQXlCLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxtQkFBbUIsQ0FDeEUsU0FBUyxFQUNULGdCQUFnQixFQUNoQixrQkFBa0IsQ0FDbkIsQ0FBQztRQUNGLE1BQU0sMEJBQTBCLEdBQzlCLElBQUksQ0FBQyxlQUFlLENBQUMsNkJBQTZCLENBQ2hELFNBQVMsRUFDVCxnQkFBZ0IsRUFDaEIsYUFBYSxDQUNkLENBQUM7UUFDSixNQUFNLFNBQVMsR0FBYztZQUMzQixLQUFLLEVBQUUsY0FBYztZQUNyQixnQkFBZ0IsRUFBRSx5QkFBeUI7WUFDM0MsZ0JBQWdCO1lBQ2hCLDBCQUEwQjtZQUMxQixtQkFBbUI7WUFDbkIsd0JBQXdCO1lBQ3hCLFdBQVc7WUFDWCxLQUFLLEVBQUUsWUFBWTtZQUNuQixLQUFLO1lBQ0wsZ0JBQWdCO1lBQ2hCLFdBQVcsRUFBRSxxQkFBUyxDQUFDLElBQUksQ0FBQyxNQUFNLFdBQVcsQ0FBQztZQUM5QyxlQUFlLEVBQUUsZUFBZTtZQUNoQyxhQUFhLEVBQUUsYUFBYTtZQUM1QiwwQkFBMEIsRUFBRSwwQkFBMEI7U0FDdkQsQ0FBQztRQUVGLElBQ0UsVUFBVTtZQUNWLFVBQVUsQ0FBQyxRQUFRO1lBQ25CLGdCQUFnQjtZQUNoQixnQkFBZ0IsQ0FBQyxRQUFRLEVBQ3pCO1lBQ0EsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ25CLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLENBQUMsQ0FBQzthQUMvQztZQUVELFNBQUcsQ0FBQyxJQUFJLENBQ04sSUFBSSxDQUFDLFNBQVMsQ0FDWixFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsRUFDaEQsSUFBSSxFQUNKLENBQUMsQ0FDRixFQUNELHFCQUFxQixDQUN0QixDQUFDO1lBQ0YsTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUM7WUFDcEQsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2xDLE1BQU0sdUJBQXVCLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FDM0QsV0FBVyxFQUNYLFVBQVUsRUFDVixTQUFTLEVBQ1QsTUFBTTtZQUNOLHFEQUFxRDtZQUNyRCw4Q0FBOEM7WUFDOUMsd0JBQWMsQ0FBQyxhQUFhLENBQUMsYUFBYSxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsRUFDdEUsY0FBYyxDQUNmLENBQUM7WUFFRixJQUNFLENBQUEsTUFBQSxJQUFJLENBQUMsd0JBQXdCLDBDQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO2dCQUNyRCx1QkFBdUIsQ0FBQyxnQkFBZ0IsS0FBSyw0QkFBZ0IsQ0FBQyxNQUFNLEVBQ3BFO2dCQUNBLCtDQUErQztnQkFDL0MsU0FBRyxDQUFDLElBQUksQ0FDTjtvQkFDRSxnQkFBZ0IsRUFBRSx1QkFBdUIsQ0FBQyxnQkFBZ0I7b0JBQzFELFNBQVMsRUFBRSx1QkFBdUI7aUJBQ25DLEVBQ0QsNEVBQTRFLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FDM0YsQ0FBQztnQkFDRixlQUFNLENBQUMsU0FBUyxDQUNkLDBCQUEwQixJQUFJLENBQUMsT0FBTyxFQUFFLEVBQ3hDLENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7Z0JBRUYsbUNBQW1DO2dCQUNuQyxNQUFNLGFBQWEsR0FBRyx3QkFBWSxDQUFDLHlCQUF5QixDQUMxRCx1QkFBdUIsQ0FBQyxLQUFLLEVBQzdCLElBQUksQ0FBQyxPQUFPLEVBQ1osVUFBVSxFQUNWLFdBQVcsRUFDWCxTQUFTLENBQUMsSUFBSSxFQUFFLEVBQ2hCLE1BQU0sV0FBVyxFQUNqQixTQUFTLEVBQ1QsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUNqQixDQUFDO2dCQUVGLElBQUksQ0FBQyxhQUFhLEVBQUU7b0JBQ2xCLFNBQUcsQ0FBQyxLQUFLLENBQ1AsRUFBRSx1QkFBdUIsRUFBRSxFQUMzQiwyREFBMkQsQ0FDNUQsQ0FBQztpQkFDSDtxQkFBTTtvQkFDTCxJQUFJO3dCQUNGLE1BQU0sQ0FBQSxNQUFBLElBQUksQ0FBQyxvQkFBb0IsMENBQUUsaUJBQWlCLENBQUMsYUFBYSxDQUFDLENBQUEsQ0FBQztxQkFDbkU7b0JBQUMsT0FBTyxHQUFHLEVBQUU7d0JBQ1osU0FBRyxDQUFDLEtBQUssQ0FDUCxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsRUFDdEIsd0RBQXdELENBQ3pELENBQUM7cUJBQ0g7aUJBQ0Y7YUFDRjtZQUVELGVBQU0sQ0FBQyxTQUFTLENBQ2QscUJBQXFCLEVBQ3JCLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxjQUFjLEVBQzNCLHlCQUFnQixDQUFDLFlBQVksQ0FDOUIsQ0FBQztZQUNGLE9BQU8sdUJBQXVCLENBQUM7U0FDaEM7UUFFRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDTyxLQUFLLENBQUMsWUFBWSxDQUMxQixNQUE2QixFQUM3QixhQUFnQyxFQUNoQyxjQUErQixFQUMvQixjQUErQixFQUMvQixjQUErQjtRQUUvQixLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sRUFBRTtZQUMxQixRQUFRLEtBQUssQ0FBQyxRQUFRLEVBQUU7Z0JBQ3RCLEtBQUsscUJBQVEsQ0FBQyxFQUFFO29CQUNkLEtBQUssQ0FBQyxLQUFLLEdBQUcsTUFBTSxXQUFXLENBQUMsY0FBYyxDQUM1QyxLQUFLLENBQUMsS0FBZ0IsRUFDdEIsYUFBYSxFQUNiLGNBQWMsQ0FDZixDQUFDO29CQUNGLE1BQU07Z0JBQ1IsS0FBSyxxQkFBUSxDQUFDLEVBQUU7b0JBQ2QsS0FBSyxDQUFDLEtBQUssR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLENBQzVDLEtBQUssQ0FBQyxLQUFnQixFQUN0QixhQUFhLEVBQ2IsY0FBYyxDQUNmLENBQUM7b0JBQ0YsTUFBTTtnQkFDUixLQUFLLHFCQUFRLENBQUMsRUFBRTtvQkFDZCxLQUFLLENBQUMsS0FBSyxHQUFHLE1BQU0sV0FBVyxDQUFDLGNBQWMsQ0FDNUMsS0FBSyxDQUFDLEtBQWdCLEVBQ3RCLGFBQWEsRUFDYixjQUFjLENBQ2YsQ0FBQztvQkFDRixNQUFNO2dCQUNSLEtBQUsscUJBQVEsQ0FBQyxLQUFLO29CQUNqQixLQUFLLENBQUMsS0FBSyxHQUFHLE1BQU0sV0FBVyxDQUFDLGlCQUFpQixDQUMvQyxLQUFLLENBQUMsS0FBbUIsRUFDekIsYUFBYSxFQUNiLGNBQWMsRUFDZCxjQUFjLEVBQ2QsY0FBYyxDQUNmLENBQUM7b0JBQ0YsTUFBTTtnQkFDUjtvQkFDRSxNQUFNLElBQUksS0FBSyxDQUNiLHFCQUFzQixLQUFnQyxDQUFDLFFBQVEsRUFBRSxDQUNsRSxDQUFDO2FBQ0w7U0FDRjtJQUNILENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ08sTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQ25DLEtBQWMsRUFDZCxNQUF5QixFQUN6QixjQUErQjtRQUUvQixNQUFNLGNBQWMsR0FBYSxFQUFFLENBQUM7UUFDcEMsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFO1lBQzlCLE1BQU0sT0FBTyxHQUFHLE1BQU0sY0FBYyxDQUFDLFFBQVEsQ0FDM0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQzVCLE1BQU0sQ0FDUCxDQUFDO1lBQ0YsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUM1RCxJQUFJLFNBQVM7Z0JBQUUsY0FBYyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztpQkFDekM7Z0JBQ0gsdUZBQXVGO2dCQUN2RixXQUFXLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3hDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDM0I7U0FDRjtRQUVELE9BQU8sSUFBQSxpQ0FBd0IsRUFBQyxLQUFLLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDTyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FDbkMsS0FBYyxFQUNkLE1BQXlCLEVBQ3pCLGNBQStCO1FBRS9CLE1BQU0sY0FBYyxHQUFhLEVBQUUsQ0FBQztRQUNwQyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssQ0FBQyxLQUFLLEVBQUU7WUFDOUIsTUFBTSxPQUFPLEdBQUcsTUFBTSxjQUFjLENBQUMsUUFBUSxDQUMzQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUN0QyxNQUFNLENBQ1AsQ0FBQztZQUNGLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN0RSxJQUFJLFNBQVM7Z0JBQUUsY0FBYyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztpQkFDekM7Z0JBQ0gsdUZBQXVGO2dCQUN2RixXQUFXLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3hDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDM0I7U0FDRjtRQUVELE9BQU8sSUFBQSxpQ0FBd0IsRUFBQyxLQUFLLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDTyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FDbkMsS0FBYyxFQUNkLE1BQXlCLEVBQ3pCLGNBQStCO1FBRS9CLE1BQU0sY0FBYyxHQUFhLEVBQUUsQ0FBQztRQUNwQyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssQ0FBQyxLQUFLLEVBQUU7WUFDOUIsTUFBTSxPQUFPLEdBQUcsTUFBTSxjQUFjLENBQUMsUUFBUSxDQUMzQztnQkFDRTtvQkFDRSxJQUFJLENBQUMsU0FBUztvQkFDZCxJQUFJLENBQUMsU0FBUztvQkFDZCxJQUFJLENBQUMsR0FBRztvQkFDUixJQUFJLENBQUMsV0FBVztvQkFDaEIsSUFBSSxDQUFDLEtBQUs7aUJBQ1g7YUFDRixFQUNELE1BQU0sQ0FDUCxDQUFDO1lBQ0YsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FDL0IsSUFBSSxDQUFDLFNBQVMsRUFDZCxJQUFJLENBQUMsU0FBUyxFQUNkLElBQUksQ0FBQyxHQUFHLEVBQ1IsSUFBSSxDQUFDLFdBQVcsRUFDaEIsSUFBSSxDQUFDLEtBQUssQ0FDWCxDQUFDO1lBQ0YsSUFBSSxTQUFTO2dCQUFFLGNBQWMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7aUJBQ3pDO2dCQUNILHVGQUF1RjtnQkFDdkYsV0FBVyxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN4QyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2FBQzNCO1NBQ0Y7UUFFRCxPQUFPLElBQUEsaUNBQXdCLEVBQUMsS0FBSyxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDTyxNQUFNLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUN0QyxLQUFpQixFQUNqQixNQUF5QixFQUN6QixjQUErQixFQUMvQixjQUErQixFQUMvQixjQUErQjtRQUUvQixNQUFNLGNBQWMsR0FBZ0IsRUFBRSxDQUFDO1FBQ3ZDLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUssRUFBRTtZQUM5QixJQUFJLElBQUksWUFBWSxhQUFNLEVBQUU7Z0JBQzFCLE1BQU0sT0FBTyxHQUFHLE1BQU0sY0FBYyxDQUFDLFFBQVEsQ0FDM0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQzVCLE1BQU0sQ0FDUCxDQUFDO2dCQUNGLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzVELElBQUksU0FBUztvQkFBRSxjQUFjLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO3FCQUN6QztvQkFDSCx1RkFBdUY7b0JBQ3ZGLFdBQVcsQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDeEMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztpQkFDM0I7YUFDRjtpQkFBTSxJQUFJLElBQUksWUFBWSxhQUFNLEVBQUU7Z0JBQ2pDLE1BQU0sT0FBTyxHQUFHLE1BQU0sY0FBYyxDQUFDLFFBQVEsQ0FDM0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFDdEMsTUFBTSxDQUNQLENBQUM7Z0JBQ0YsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN0RSxJQUFJLFNBQVM7b0JBQUUsY0FBYyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztxQkFDekM7b0JBQ0gsdUZBQXVGO29CQUN2RixXQUFXLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQ3hDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7aUJBQzNCO2FBQ0Y7aUJBQU0sSUFBSSxJQUFJLFlBQVksYUFBTSxFQUFFO2dCQUNqQyxNQUFNLE9BQU8sR0FBRyxNQUFNLGNBQWMsQ0FBQyxRQUFRLENBQzNDO29CQUNFO3dCQUNFLElBQUksQ0FBQyxTQUFTO3dCQUNkLElBQUksQ0FBQyxTQUFTO3dCQUNkLElBQUksQ0FBQyxHQUFHO3dCQUNSLElBQUksQ0FBQyxXQUFXO3dCQUNoQixJQUFJLENBQUMsS0FBSztxQkFDWDtpQkFDRixFQUNELE1BQU0sQ0FDUCxDQUFDO2dCQUNGLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQy9CLElBQUksQ0FBQyxTQUFTLEVBQ2QsSUFBSSxDQUFDLFNBQVMsRUFDZCxJQUFJLENBQUMsR0FBRyxFQUNSLElBQUksQ0FBQyxXQUFXLEVBQ2hCLElBQUksQ0FBQyxLQUFLLENBQ1gsQ0FBQztnQkFDRixJQUFJLFNBQVM7b0JBQUUsY0FBYyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztxQkFDekM7b0JBQ0gsdUZBQXVGO29CQUN2RixXQUFXLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQ3hDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7aUJBQzNCO2FBQ0Y7aUJBQU07Z0JBQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO2FBQ3JEO1NBQ0Y7UUFFRCxPQUFPLElBQUEsb0NBQTJCLEVBQUMsS0FBSyxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFTyxNQUFNLENBQUMscUJBQXFCLENBQUMsTUFBYztRQUNqRCxTQUFHLENBQUMsS0FBSyxDQUNQO1lBQ0UsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO1lBQ3JCLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTTtTQUN0QixFQUNELDJCQUEyQixDQUM1QixDQUFDO0lBQ0osQ0FBQztJQUVPLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxNQUFjO1FBQ2pELFNBQUcsQ0FBQyxLQUFLLENBQ1A7WUFDRSxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU07WUFDckIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO1lBQ3JCLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRztTQUNoQixFQUNELDJCQUEyQixDQUM1QixDQUFDO0lBQ0osQ0FBQztJQUVPLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxNQUFjO1FBQ2pELFNBQUcsQ0FBQyxLQUFLLENBQ1A7WUFDRSxNQUFNLEVBQUUsTUFBTSxDQUFDLFNBQVM7WUFDeEIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxTQUFTO1lBQ3hCLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRztZQUNmLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVztZQUMvQixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7U0FDcEIsRUFDRCwyQkFBMkIsQ0FDNUIsQ0FBQztJQUNKLENBQUM7SUFFTyxLQUFLLENBQUMscUJBQXFCLENBQ2pDLE1BQXNCLEVBQ3RCLFVBQW9CLEVBQ3BCLFdBQXFCLEVBQ3JCLFNBQW9CLEVBQ3BCLGFBQXFCLEVBQ3JCLGFBQTRCLEVBQzVCLG9CQUE2Qjs7UUFFN0IsSUFBSSxhQUFhLEVBQUU7WUFDakIsTUFBTSxtQkFBbUIsR0FDdkIsb0JBQW9CLEtBQUssU0FBUztnQkFDbEMsNERBQTREO2dCQUM1RCx1RkFBdUY7Z0JBQ3ZGLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUM5QixJQUFBLHFDQUFpQixFQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FDOUQsQ0FBQztZQUVKLElBQUksbUJBQW1CLEVBQUU7Z0JBQ3ZCLGVBQU0sQ0FBQyxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxFQUFFLHlCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNuRSxlQUFNLENBQUMsU0FBUyxDQUNkLDhCQUE4QixVQUFVLENBQUMsT0FBTyxFQUFFLEVBQ2xELENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7Z0JBQ0YsZUFBTSxDQUFDLFNBQVMsQ0FDZCw4QkFBOEIsV0FBVyxDQUFDLE9BQU8sUUFBUSxVQUFVLENBQUMsTUFBTSxHQUFHLFdBQVcsQ0FBQyxNQUFNLEVBQUUsRUFDakcsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQzthQUNIO2lCQUFNO2dCQUNMLGVBQU0sQ0FBQyxTQUFTLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxFQUFFLHlCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUN0RSxlQUFNLENBQUMsU0FBUyxDQUNkLGlDQUFpQyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQ3JELENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7Z0JBQ0YsZUFBTSxDQUFDLFNBQVMsQ0FDZCxpQ0FBaUMsV0FBVyxDQUFDLE9BQU8sUUFBUSxVQUFVLENBQUMsTUFBTSxHQUFHLFdBQVcsQ0FBQyxNQUFNLEVBQUUsRUFDcEcsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQzthQUNIO1lBRUQsTUFBTSxDQUFBLE1BQUEsSUFBSSxDQUFDLG9CQUFvQiwwQ0FDM0IsY0FBYyxDQUFDLGFBQWEsRUFBRSxNQUFNLEVBQ3JDLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUNoQixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO2dCQUNoRCxlQUFNLENBQUMsU0FBUyxDQUNkLEdBQUcsYUFBYSxJQUFJLE1BQU0sRUFBRSxFQUM1QixDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO1lBQ0osQ0FBQyxFQUNBLEtBQUssQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO2dCQUNoQixTQUFHLENBQUMsS0FBSyxDQUNQO29CQUNFLE1BQU0sRUFBRSxNQUFNO29CQUNkLFNBQVMsRUFBRSxJQUFJLENBQUMsK0JBQStCLENBQzdDLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxDQUNWO2lCQUNGLEVBQ0Qsd0JBQXdCLENBQ3pCLENBQUM7Z0JBRUYsZUFBTSxDQUFDLFNBQVMsQ0FDZCxHQUFHLGFBQWEsVUFBVSxFQUMxQixDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO1lBQ0osQ0FBQyxDQUFDLENBQUEsQ0FBQztTQUNOO2FBQU07WUFDTCxlQUFNLENBQUMsU0FBUyxDQUNkLEdBQUcsYUFBYSxjQUFjLEVBQzlCLENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7U0FDSDtJQUNILENBQUM7SUFFTyxLQUFLLENBQUMscUJBQXFCLENBQ2pDLFVBQW9CLEVBQ3BCLFdBQXFCLEVBQ3JCLFlBQTBCLEVBQzFCLFdBQW1CLEVBQ25CLE1BQXNCLEVBQ3RCLGFBQXVCLEVBQ3ZCLFNBQW9CLEVBQ3BCLGFBQWdDLEVBQ2hDLFVBQTRDLEVBQzVDLFVBQTRDLEVBQzVDLGtCQUF1RCxFQUN2RCxXQUFzQixFQUN0QixVQUE2QyxFQUM3QyxVQUF3QixFQUN4QixjQUErQjs7UUFFL0IsTUFBTSxtQkFBbUIsR0FDdkIsTUFBTSxJQUFJLENBQUMsdUJBQXVCLENBQUMsbUJBQW1CLENBQ3BELENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxFQUN6QixjQUFjLENBQ2YsQ0FBQztRQUVKLE1BQU0sY0FBYyxHQUNsQixNQUFBLE1BQUEsTUFBQSxtQkFBbUIsQ0FDakIsSUFBQSwwQkFBbUIsRUFBQyxVQUFVLENBQUMsQ0FDaEMsMENBQUUsY0FBYywwQ0FBRSxVQUFVLDBDQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QyxNQUFNLGFBQWEsR0FDakIsTUFBQSxNQUFBLE1BQUEsbUJBQW1CLENBQ2pCLElBQUEsMEJBQW1CLEVBQUMsV0FBVyxDQUFDLENBQ2pDLDBDQUFFLGNBQWMsMENBQUUsU0FBUywwQ0FBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEMsTUFBTSxlQUFlLEdBQUcsY0FBYyxJQUFJLGFBQWEsQ0FBQztRQUV4RCxTQUFHLENBQUMsSUFBSSxDQUNOO1lBQ0UsU0FBUyxFQUFFLFlBQVksQ0FBQyxnQkFBZ0I7WUFDeEMsU0FBUyxFQUFFLFlBQVksQ0FBQyxTQUFTO1lBQ2pDLGlCQUFpQixFQUFFLFlBQVksQ0FBQyxXQUFXO1lBQzNDLGdCQUFnQixFQUFFLFdBQVc7U0FDOUIsRUFDRCw0QkFBNEIsQ0FDN0IsQ0FBQztRQUNGLE1BQU0sYUFBYSxHQUErQixFQUFFLENBQUM7UUFFckQsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQ3pDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxLQUFLLHFCQUFRLENBQUMsRUFBRSxDQUMxQyxDQUFDO1FBQ0YsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQ3pDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxLQUFLLHFCQUFRLENBQUMsRUFBRSxDQUMxQyxDQUFDO1FBQ0YsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQ3pDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxLQUFLLHFCQUFRLENBQUMsRUFBRSxDQUMxQyxDQUFDO1FBQ0YsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQzVDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxLQUFLLHFCQUFRLENBQUMsS0FBSyxDQUM3QyxDQUFDO1FBRUYsSUFBSSxRQUFrQixDQUFDO1FBQ3ZCLElBQUksT0FBeUIsQ0FBQztRQUM5QixJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUNsQywyR0FBMkc7WUFDM0csQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxhQUFhLENBQUMsQ0FBQztTQUN6RTthQUFNLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxFQUFFO1lBQzFDLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7U0FDekM7YUFBTTtZQUNMLG1FQUFtRTtZQUNuRSxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDOUI7UUFFRCxJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQ3ZCLE1BQU0saUJBQWlCLEdBQWMsUUFBUSxDQUFDLEdBQUcsQ0FDL0MsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxLQUFnQixDQUM5QyxDQUFDO1lBQ0YsZUFBTSxDQUFDLFNBQVMsQ0FDZCx5Q0FBeUMsRUFDekMsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQztZQUVGLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUVuQyxhQUFhLENBQUMsSUFBSSxDQUNoQixJQUFJLENBQUMsUUFBUTtpQkFDVixTQUFTLENBQ1IsaUJBQWlCLEVBQ2pCLE9BQU8sRUFDUCxRQUFRLEVBQ1IsYUFBYSxFQUNiLFNBQVMsRUFDVCxhQUFhLEVBQ2IsU0FBUyxFQUNULFVBQVUsQ0FDWDtpQkFDQSxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtnQkFDZixlQUFNLENBQUMsU0FBUyxDQUNkLHNDQUFzQyxFQUN0QyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsZUFBZSxFQUM1Qix5QkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7Z0JBRUYsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQyxDQUFDLENBQ0wsQ0FBQztTQUNIO1FBRUQsSUFBSSxDQUFDLGVBQWUsRUFBRTtZQUNwQixJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUN2QixNQUFNLGlCQUFpQixHQUFjLFFBQVEsQ0FBQyxHQUFHLENBQy9DLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxXQUFXLENBQUMsS0FBZ0IsQ0FDOUMsQ0FBQztnQkFDRixlQUFNLENBQUMsU0FBUyxDQUNkLHlDQUF5QyxFQUN6QyxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO2dCQUVGLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFFbkMsYUFBYSxDQUFDLElBQUksQ0FDaEIsSUFBSSxDQUFDLFFBQVE7cUJBQ1YsU0FBUyxDQUNSLGlCQUFpQixFQUNqQixPQUFPLEVBQ1AsUUFBUSxFQUNSLGFBQWEsQ0FBQyxPQUFPLEVBQ3JCLFNBQVMsRUFDVCxhQUFhLEVBQ2IsU0FBUyxFQUNULFVBQVUsQ0FDWDtxQkFDQSxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtvQkFDZixlQUFNLENBQUMsU0FBUyxDQUNkLHNDQUFzQyxFQUN0QyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsZUFBZSxFQUM1Qix5QkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7b0JBRUYsT0FBTyxNQUFNLENBQUM7Z0JBQ2hCLENBQUMsQ0FBQyxDQUNMLENBQUM7YUFDSDtTQUNGO1FBRUQsSUFBSSxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN2QixNQUFNLGlCQUFpQixHQUFjLFFBQVEsQ0FBQyxHQUFHLENBQy9DLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxXQUFXLENBQUMsS0FBZ0IsQ0FDOUMsQ0FBQztZQUNGLGVBQU0sQ0FBQyxTQUFTLENBQ2QseUNBQXlDLEVBQ3pDLENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7WUFFRixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFFbkMsYUFBYSxDQUFDLElBQUksQ0FDaEIsSUFBSSxDQUFDLFFBQVE7aUJBQ1YsMEJBQTBCLENBQ3pCLFlBQVksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUMvQixZQUFZLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFDaEMsaUJBQWlCLEVBQ2pCLE9BQU8sRUFDUCxRQUFRLEVBQ1IsYUFBYSxDQUFDLE9BQU8sRUFDckIsU0FBUyxFQUNULGFBQWEsRUFDYixXQUFXLENBQ1o7aUJBQ0EsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7Z0JBQ2YsZUFBTSxDQUFDLFNBQVMsQ0FDZCxzQ0FBc0MsRUFDdEMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLGVBQWUsRUFDNUIseUJBQWdCLENBQUMsWUFBWSxDQUM5QixDQUFDO2dCQUVGLE9BQU8sTUFBTSxDQUFDO1lBQ2hCLENBQUMsQ0FBQyxDQUNMLENBQUM7U0FDSDtRQUVELElBQUksQ0FBQyxlQUFlLEVBQUU7WUFDcEIsSUFBSSxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDMUIsTUFBTSxvQkFBb0IsR0FBaUIsV0FBVyxDQUFDLEdBQUcsQ0FDeEQsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxLQUFtQixDQUNqRCxDQUFDO2dCQUNGLGVBQU0sQ0FBQyxTQUFTLENBQ2QsNENBQTRDLEVBQzVDLENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7Z0JBRUYsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUVuQyxhQUFhLENBQUMsSUFBSSxDQUNoQixJQUFJLENBQUMsV0FBVztxQkFDYixTQUFTLENBQ1Isb0JBQW9CLEVBQ3BCLE9BQU8sRUFDUCxRQUFRLEVBQ1IsYUFBYSxDQUFDLE9BQU8sRUFDckIsU0FBUyxFQUNULGFBQWEsRUFDYixTQUFTLEVBQ1Qsa0JBQWtCLENBQ25CO3FCQUNBLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO29CQUNmLGVBQU0sQ0FBQyxTQUFTLENBQ2QseUNBQXlDLEVBQ3pDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxlQUFlLEVBQzVCLHlCQUFnQixDQUFDLFlBQVksQ0FDOUIsQ0FBQztvQkFFRixPQUFPLE1BQU0sQ0FBQztnQkFDaEIsQ0FBQyxDQUFDLENBQ0wsQ0FBQzthQUNIO1NBQ0Y7UUFFRCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUMxRCxNQUFNLHdCQUF3QixHQUFHLGdCQUFDLENBQUMsT0FBTyxDQUN4QyxnQkFBZ0IsRUFDaEIsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxxQkFBcUIsQ0FDbkQsQ0FBQztRQUVGLE9BQU8sSUFBQSxrQ0FBZ0IsRUFDckIsTUFBTSxFQUNOLFFBQVEsRUFDUix3QkFBd0IsRUFDeEIsU0FBUyxFQUNULElBQUksQ0FBQyxPQUFPLEVBQ1osYUFBYSxFQUNiLElBQUksQ0FBQyxlQUFlLEVBQ3BCLFVBQVUsRUFDVixVQUFVLEVBQ1YsVUFBVSxFQUNWLFVBQVUsRUFDVixjQUFjLENBQ2YsQ0FBQztJQUNKLENBQUM7SUFFTyxLQUFLLENBQUMscUJBQXFCLENBQ2pDLE1BQXNCLEVBQ3RCLFVBQW9CLEVBQ3BCLFdBQXFCLEVBQ3JCLFNBQXFCLEVBQ3JCLGFBQXVCLEVBQ3ZCLFNBQW9CLEVBQ3BCLGFBQWdDLEVBQ2hDLFVBQTRDLEVBQzVDLFVBQTRDLEVBQzVDLGtCQUF1RCxFQUN2RCxXQUFzQixFQUN0QixVQUE2QyxFQUM3QyxVQUF3QixFQUN4QixjQUErQjs7UUFFL0IsTUFBTSxtQkFBbUIsR0FDdkIsTUFBTSxJQUFJLENBQUMsdUJBQXVCLENBQUMsbUJBQW1CLENBQ3BELENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxFQUN6QixjQUFjLENBQ2YsQ0FBQztRQUVKLE1BQU0sY0FBYyxHQUNsQixNQUFBLE1BQUEsTUFBQSxtQkFBbUIsQ0FDakIsSUFBQSwwQkFBbUIsRUFBQyxVQUFVLENBQUMsQ0FDaEMsMENBQUUsY0FBYywwQ0FBRSxVQUFVLDBDQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QyxNQUFNLGFBQWEsR0FDakIsTUFBQSxNQUFBLE1BQUEsbUJBQW1CLENBQ2pCLElBQUEsMEJBQW1CLEVBQUMsV0FBVyxDQUFDLENBQ2pDLDBDQUFFLGNBQWMsMENBQUUsU0FBUywwQ0FBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEMsTUFBTSxlQUFlLEdBQUcsY0FBYyxJQUFJLGFBQWEsQ0FBQztRQUV4RCw0RUFBNEU7UUFDNUUsa0ZBQWtGO1FBQ2xGLG9DQUFvQztRQUNwQyxNQUFNLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FDcEQsTUFBTSxFQUNOLGFBQWEsQ0FDZCxDQUFDO1FBRUYsTUFBTSxvQkFBb0IsR0FBRyxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztRQUNwRCxNQUFNLG1CQUFtQixHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMscUJBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM1RCxNQUFNLG1CQUFtQixHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMscUJBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM1RCxNQUFNLG1CQUFtQixHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMscUJBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM1RCxNQUFNLGtCQUFrQixHQUFHLE1BQUEsSUFBSSxDQUFDLFdBQVcsMENBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNwRSxNQUFNLGtCQUFrQixHQUFHLE1BQUEsSUFBSSxDQUFDLFdBQVcsMENBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNwRSxNQUFNLHdCQUF3QixHQUM1QixTQUFTLENBQUMsUUFBUSxDQUFDLHFCQUFRLENBQUMsS0FBSyxDQUFDO1lBQ2xDLENBQUMsb0JBQW9CLElBQUksa0JBQWtCLElBQUksa0JBQWtCLENBQUMsQ0FBQztRQUNyRSxNQUFNLG9CQUFvQixHQUN4QixDQUFBLE1BQUEsSUFBSSxDQUFDLGNBQWMsMENBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDM0MsU0FBUyxLQUFLLG9CQUFTLENBQUMsV0FBVyxDQUFDO1FBRXRDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRXZDLElBQUksdUJBQXVCLEdBQ3pCLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFN0IsMkRBQTJEO1FBQzNELElBQUksa0JBQWtCLElBQUksQ0FBQyxtQkFBbUIsSUFBSSxvQkFBb0IsQ0FBQyxFQUFFO1lBQ3ZFLHFEQUFxRDtZQUNyRCx1QkFBdUIsR0FBRyxJQUFBLHlDQUFtQixFQUFDO2dCQUM1QyxVQUFVLEVBQUUsVUFBVTtnQkFDdEIsV0FBVyxFQUFFLFdBQVc7Z0JBQ3hCLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTtnQkFDakMsd0JBQXdCLEVBQUUsSUFBSSxDQUFDLHdCQUF3QjtnQkFDdkQsWUFBWSxFQUFFLElBQUksQ0FBQyxjQUFjO2dCQUNqQyxTQUFTLEVBQUUsU0FBUztnQkFDcEIsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQjtnQkFDekMsYUFBYTtnQkFDYixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87Z0JBQ3JCLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTthQUNoQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsY0FBYyxFQUFFLEVBQUU7Z0JBQ3pCLGVBQU0sQ0FBQyxTQUFTLENBQ2QscUJBQXFCLEVBQ3JCLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxtQkFBbUIsRUFDaEMseUJBQWdCLENBQUMsWUFBWSxDQUM5QixDQUFDO2dCQUNGLE9BQU8sY0FBYyxDQUFDO1lBQ3hCLENBQUMsQ0FBQyxDQUFDO1NBQ0o7UUFFRCxJQUFJLHVCQUF1QixHQUN6QixPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxlQUFlLEVBQUU7WUFDcEIsSUFBSSxtQkFBbUIsSUFBSSxvQkFBb0IsRUFBRTtnQkFDL0MsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQztnQkFDbkMsTUFBTSxRQUFRLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQztnQkFFckMsdUJBQXVCLEdBQUcsSUFBQSx5Q0FBbUIsRUFBQztvQkFDNUMsT0FBTztvQkFDUCxRQUFRO29CQUNSLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTtvQkFDakMsd0JBQXdCLEVBQUUsSUFBSSxDQUFDLHdCQUF3QjtvQkFDdkQsWUFBWSxFQUFFLElBQUksQ0FBQyxjQUFjO29CQUNqQyxTQUFTLEVBQUUsU0FBUztvQkFDcEIsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQjtvQkFDekMsYUFBYTtvQkFDYixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87aUJBQ3RCLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxjQUFjLEVBQUUsRUFBRTtvQkFDekIsZUFBTSxDQUFDLFNBQVMsQ0FDZCxxQkFBcUIsRUFDckIsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLG1CQUFtQixFQUNoQyx5QkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7b0JBQ0YsT0FBTyxjQUFjLENBQUM7Z0JBQ3hCLENBQUMsQ0FBQyxDQUFDO2FBQ0o7U0FDRjtRQUVELElBQUksdUJBQXVCLEdBQ3pCLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDN0IsSUFBSSxrQkFBa0IsSUFBSSxDQUFDLG1CQUFtQixJQUFJLG9CQUFvQixDQUFDLEVBQUU7WUFDdkUsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQztZQUNuQyxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDO1lBRXJDLDZFQUE2RTtZQUM3RSw4RUFBOEU7WUFDOUUseUJBQXlCO1lBQ3pCLHVCQUF1QixHQUFHLElBQUEseUNBQW1CLEVBQUM7Z0JBQzVDLE9BQU87Z0JBQ1AsUUFBUTtnQkFDUixhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWE7Z0JBQ2pDLHdCQUF3QixFQUFFLElBQUksQ0FBQyx3QkFBd0I7Z0JBQ3ZELFlBQVksRUFBRSxJQUFJLENBQUMsY0FBYztnQkFDakMsU0FBUyxFQUFFLFNBQVM7Z0JBQ3BCLGdCQUFnQixFQUFFLElBQUksQ0FBQyxrQkFBa0I7Z0JBQ3pDLGFBQWE7Z0JBQ2IsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO2FBQ3RCLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxjQUFjLEVBQUUsRUFBRTtnQkFDekIsZUFBTSxDQUFDLFNBQVMsQ0FDZCxxQkFBcUIsRUFDckIsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLG1CQUFtQixFQUNoQyx5QkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7Z0JBQ0YsT0FBTyxjQUFjLENBQUM7WUFDeEIsQ0FBQyxDQUFDLENBQUM7U0FDSjtRQUVELE1BQU0sYUFBYSxHQUErQixFQUFFLENBQUM7UUFFckQsMERBQTBEO1FBQzFELElBQUksa0JBQWtCLElBQUksbUJBQW1CLEVBQUU7WUFDN0MsU0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1lBRXhELGVBQU0sQ0FBQyxTQUFTLENBQ2QsbURBQW1ELEVBQ25ELENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7WUFDRixNQUFNLHlCQUF5QixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUU3QyxhQUFhLENBQUMsSUFBSSxDQUNoQix1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLENBQ2hELElBQUksQ0FBQyxRQUFRO2lCQUNWLG1CQUFtQixDQUNsQixVQUFVLEVBQ1YsV0FBVyxFQUNYLE1BQU0sRUFDTixPQUFPLEVBQ1AsUUFBUSxFQUNSLGFBQWEsRUFDYixnQkFBaUIsRUFDakIsU0FBUyxFQUNULGFBQWEsRUFDYixVQUFVLENBQ1g7aUJBQ0EsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7Z0JBQ2YsZUFBTSxDQUFDLFNBQVMsQ0FDZCxnREFBZ0QsRUFDaEQsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLHlCQUF5QixFQUN0Qyx5QkFBZ0IsQ0FBQyxZQUFZLENBQzlCLENBQUM7Z0JBRUYsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQyxDQUFDLENBQ0wsQ0FDRixDQUFDO1NBQ0g7UUFFRCxJQUFJLENBQUMsZUFBZSxFQUFFO1lBQ3BCLG1FQUFtRTtZQUNuRSxJQUFJLG1CQUFtQixJQUFJLG9CQUFvQixFQUFFO2dCQUMvQyxTQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxFQUFFLG1CQUFtQixDQUFDLENBQUM7Z0JBRXhELGVBQU0sQ0FBQyxTQUFTLENBQ2QsbURBQW1ELEVBQ25ELENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7Z0JBQ0YsTUFBTSx5QkFBeUIsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQzdDLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUM7Z0JBQ25DLE1BQU0sUUFBUSxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUM7Z0JBRXJDLGFBQWEsQ0FBQyxJQUFJLENBQ2hCLHVCQUF1QixDQUFDLElBQUksQ0FBQyxDQUFDLGdCQUFnQixFQUFFLEVBQUUsQ0FDaEQsSUFBSSxDQUFDLFFBQVE7cUJBQ1YsbUJBQW1CLENBQ2xCLE9BQU8sRUFDUCxRQUFRLEVBQ1IsTUFBTSxFQUNOLE9BQU8sRUFDUCxRQUFRLEVBQ1IsYUFBYSxDQUFDLE9BQU8sRUFDckIsZ0JBQWlCLEVBQ2pCLFNBQVMsRUFDVCxhQUFhLEVBQ2IsVUFBVSxDQUNYO3FCQUNBLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO29CQUNmLGVBQU0sQ0FBQyxTQUFTLENBQ2QsZ0RBQWdELEVBQ2hELElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyx5QkFBeUIsRUFDdEMseUJBQWdCLENBQUMsWUFBWSxDQUM5QixDQUFDO29CQUVGLE9BQU8sTUFBTSxDQUFDO2dCQUNoQixDQUFDLENBQUMsQ0FDTCxDQUNGLENBQUM7YUFDSDtTQUNGO1FBRUQscUdBQXFHO1FBQ3JHLElBQUksa0JBQWtCLElBQUksQ0FBQyxtQkFBbUIsSUFBSSxvQkFBb0IsQ0FBQyxFQUFFO1lBQ3ZFLFNBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztZQUV4RCxlQUFNLENBQUMsU0FBUyxDQUNkLG1EQUFtRCxFQUNuRCxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO1lBQ0YsTUFBTSx5QkFBeUIsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDN0MsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQztZQUNuQyxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDO1lBRXJDLGFBQWEsQ0FBQyxJQUFJLENBQ2hCLHVCQUF1QixDQUFDLElBQUksQ0FBQyxDQUFDLGdCQUFnQixFQUFFLEVBQUUsQ0FDaEQsSUFBSSxDQUFDLFFBQVE7aUJBQ1YsbUJBQW1CLENBQ2xCLE9BQU8sRUFDUCxRQUFRLEVBQ1IsTUFBTSxFQUNOLE9BQU8sRUFDUCxRQUFRLEVBQ1IsYUFBYSxDQUFDLE9BQU8sRUFDckIsZ0JBQWlCLEVBQ2pCLFNBQVMsRUFDVCxhQUFhLEVBQ2IsVUFBVSxFQUNWLFdBQVcsQ0FDWjtpQkFDQSxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtnQkFDZixlQUFNLENBQUMsU0FBUyxDQUNkLGdEQUFnRCxFQUNoRCxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcseUJBQXlCLEVBQ3RDLHlCQUFnQixDQUFDLFlBQVksQ0FDOUIsQ0FBQztnQkFFRixPQUFPLE1BQU0sQ0FBQztZQUNoQixDQUFDLENBQUMsQ0FDTCxDQUNGLENBQUM7U0FDSDtRQUVELElBQUksQ0FBQyxlQUFlLEVBQUU7WUFDcEIsMkJBQTJCO1lBQzNCLHlHQUF5RztZQUN6RywwQkFBMEI7WUFDMUIscUdBQXFHO1lBQ3JHLElBQ0Usd0JBQXdCO2dCQUN4QixvQkFBb0I7Z0JBQ3BCLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsS0FBSyxxQkFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQ3ZFO2dCQUNBLFNBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEVBQUUsNEJBQTRCLENBQUMsQ0FBQztnQkFFakUsZUFBTSxDQUFDLFNBQVMsQ0FDZCxzREFBc0QsRUFDdEQsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQztnQkFDRixNQUFNLHlCQUF5QixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFFN0MsYUFBYSxDQUFDLElBQUksQ0FDaEIsT0FBTyxDQUFDLEdBQUcsQ0FBQztvQkFDVix1QkFBdUI7b0JBQ3ZCLHVCQUF1QjtvQkFDdkIsdUJBQXVCO2lCQUN4QixDQUFDLENBQUMsSUFBSSxDQUNMLEtBQUssRUFBRSxDQUFDLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixDQUFDLEVBQUUsRUFBRTtvQkFDL0QsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQztvQkFDbkMsTUFBTSxRQUFRLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQztvQkFFckMsTUFBTSxtQkFBbUIsR0FDdkIsTUFBTSxJQUFBLDBEQUFvQyxFQUFDO3dCQUN6QyxPQUFPO3dCQUNQLFFBQVE7d0JBQ1IsV0FBVyxFQUFFLGFBQWEsQ0FBQyxXQUFXO3dCQUN0QyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsa0JBQWtCO3dCQUMzQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsa0JBQWtCO3dCQUMzQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsa0JBQWtCO3dCQUMzQyxZQUFZLEVBQUUsZ0JBQWdCO3dCQUM5QixZQUFZLEVBQUUsZ0JBQWdCO3dCQUM5QixZQUFZLEVBQUUsZ0JBQWdCO3dCQUM5Qix1Q0FBdUMsRUFDckMsSUFBSSxDQUFDLHVDQUF1Qzt3QkFDOUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO3FCQUN0QixDQUFDLENBQUM7b0JBRUwsT0FBTyxJQUFJLENBQUMsV0FBVzt5QkFDcEIsbUJBQW1CLENBQ2xCLFVBQVUsRUFDVixXQUFXLEVBQ1gsTUFBTSxFQUNOLE9BQU8sRUFDUCxRQUFRLEVBQ1IsYUFBYSxDQUFDLE9BQU8sRUFDckI7d0JBQ0UsZ0JBQWdCO3dCQUNoQixnQkFBZ0I7d0JBQ2hCLGdCQUFnQjt3QkFDaEIsbUJBQW1CO3FCQUNwQixFQUNELFNBQVMsRUFDVCxhQUFhLEVBQ2Isa0JBQWtCLENBQ25CO3lCQUNBLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO3dCQUNmLGVBQU0sQ0FBQyxTQUFTLENBQ2QsbURBQW1ELEVBQ25ELElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyx5QkFBeUIsRUFDdEMseUJBQWdCLENBQUMsWUFBWSxDQUM5QixDQUFDO3dCQUVGLE9BQU8sTUFBTSxDQUFDO29CQUNoQixDQUFDLENBQUMsQ0FBQztnQkFDUCxDQUFDLENBQ0YsQ0FDRixDQUFDO2FBQ0g7U0FDRjtRQUVELE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRTFELE1BQU0sd0JBQXdCLEdBQTBCLEVBQUUsQ0FBQztRQUMzRCxNQUFNLGlCQUFpQixHQUF3QyxFQUFFLENBQUM7UUFDbEUsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUMsY0FBYyxFQUFFLEVBQUU7WUFDMUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLEdBQUcsY0FBYyxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDdkUsSUFBSSxjQUFjLENBQUMsY0FBYyxFQUFFO2dCQUNqQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxDQUFDO2FBQ3ZEO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLHdCQUF3QixDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDekMsU0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLHdCQUF3QixFQUFFLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztZQUNuRSxPQUFPLElBQUksQ0FBQztTQUNiO1FBRUQsMEZBQTBGO1FBQzFGLE1BQU0sYUFBYSxHQUFHLE1BQU0sSUFBQSxrQ0FBZ0IsRUFDMUMsTUFBTSxFQUNOLFFBQVEsRUFDUix3QkFBd0IsRUFDeEIsU0FBUyxFQUNULElBQUksQ0FBQyxPQUFPLEVBQ1osYUFBYSxFQUNiLElBQUksQ0FBQyxlQUFlLEVBQ3BCLFVBQVUsRUFDVixVQUFVLEVBQ1YsVUFBVSxFQUNWLFVBQVUsRUFDVixjQUFjLENBQ2YsQ0FBQztRQUVGLElBQUksYUFBYSxFQUFFO1lBQ2pCLElBQUksQ0FBQyx3QkFBd0IsQ0FDM0IsYUFBYSxFQUNiLGlCQUFpQixFQUNqQixVQUFVLEVBQ1YsV0FBVyxDQUNaLENBQUM7U0FDSDtRQUVELE9BQU8sYUFBYSxDQUFDO0lBQ3ZCLENBQUM7SUFFTyxZQUFZLENBQUMsU0FBb0I7UUFDdkMsT0FBTyxTQUFTLEtBQUssb0JBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO0lBQ3RFLENBQUM7SUFFTywrQkFBK0IsQ0FDckMsVUFBb0IsRUFDcEIsV0FBcUIsRUFDckIsU0FBb0I7UUFFcEIsT0FBTyxHQUFHLFVBQVUsQ0FBQyxNQUFNLElBQUksV0FBVyxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsWUFBWSxDQUNwRSxTQUFTLENBQ1YsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVPLG1DQUFtQyxDQUN6QyxTQUFvQixFQUNwQixNQUFzQixFQUN0QixhQUF1QjtRQUV2QixJQUFJLFNBQVMsS0FBSyxvQkFBUyxDQUFDLFdBQVcsRUFBRTtZQUN2QyxPQUFPO2dCQUNMLFVBQVUsRUFBRSxNQUFNLENBQUMsUUFBUTtnQkFDM0IsV0FBVyxFQUFFLGFBQWE7YUFDM0IsQ0FBQztTQUNIO2FBQU07WUFDTCxPQUFPO2dCQUNMLFVBQVUsRUFBRSxhQUFhO2dCQUN6QixXQUFXLEVBQUUsTUFBTSxDQUFDLFFBQVE7YUFDN0IsQ0FBQztTQUNIO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxjQUFjLENBQzFCLGlCQUF5QixFQUN6QixrQkFBMkI7UUFFM0Isc0RBQXNEO1FBQ3RELE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRXRDLHdGQUF3RjtRQUN4RixNQUFNLEVBQUUsV0FBVyxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUM3RCxpQkFBaUIsRUFDakIsa0JBQWtCLENBQ25CLENBQUM7UUFFRixlQUFNLENBQUMsU0FBUyxDQUNkLGNBQWMsRUFDZCxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsa0JBQWtCLEVBQy9CLHlCQUFnQixDQUFDLFlBQVksQ0FDOUIsQ0FBQztRQUVGLE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7SUFFTyxLQUFLLENBQUMsWUFBWSxDQUN4QixXQUFzQixFQUN0QixXQUFrQixFQUNsQixVQUFpQixFQUNqQixjQUF1Qzs7UUFFdkMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRWxDLE1BQU0sY0FBYyxHQUFHLElBQUEsa0RBQTRCLEVBQ2pELElBQUksQ0FBQyxPQUFPLEVBQ1osSUFBSSxDQUFDLGNBQWMsRUFDbkIsY0FBYyxDQUNmLENBQUM7UUFDRixNQUFNLGNBQWMsR0FBRyw4QkFBdUIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDN0QsTUFBTSxnQ0FBZ0MsR0FBRyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDO1lBQ3pFLENBQUMsQ0FBQyxJQUFBLHFEQUErQixFQUMvQixVQUFVLEVBQ1YsSUFBSSxDQUFDLGNBQWMsRUFDbkIsY0FBYyxDQUNmO1lBQ0QsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDMUIsTUFBTSxpQ0FBaUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQzNELGNBQWMsQ0FDZjtZQUNDLENBQUMsQ0FBQyxJQUFBLHFEQUErQixFQUMvQixXQUFXLEVBQ1gsSUFBSSxDQUFDLGNBQWMsRUFDbkIsY0FBYyxDQUNmO1lBQ0QsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFMUIsOERBQThEO1FBQzlELGdFQUFnRTtRQUNoRSxNQUFNLHVDQUF1QyxHQUMzQyxDQUFBLGNBQWMsYUFBZCxjQUFjLHVCQUFkLGNBQWMsQ0FBRSxRQUFRO1lBQ3RCLENBQUMsQ0FBQSxjQUFjLGFBQWQsY0FBYyx1QkFBZCxjQUFjLENBQUUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQTtZQUNoRCxDQUFDLENBQUMsSUFBQSxxREFBK0IsRUFDL0IsY0FBYyxhQUFkLGNBQWMsdUJBQWQsY0FBYyxDQUFFLFFBQVEsRUFDeEIsSUFBSSxDQUFDLGNBQWMsRUFDbkIsY0FBYyxDQUNmO1lBQ0QsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFNUIsTUFBTSxDQUNKLE9BQU8sRUFDUCx5QkFBeUIsRUFDekIsMEJBQTBCLEVBQzFCLGdDQUFnQyxFQUNqQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztZQUNwQixjQUFjO1lBQ2QsZ0NBQWdDO1lBQ2hDLGlDQUFpQztZQUNqQyx1Q0FBdUM7U0FDeEMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxLQUFLLEdBQThCO1lBQ3ZDLE9BQU8sRUFBRSxPQUFPO1lBQ2hCLHlCQUF5QixFQUFFLHlCQUF5QjtZQUNwRCwwQkFBMEIsRUFBRSwwQkFBMEI7WUFDdEQsZ0NBQWdDLEVBQUUsZ0NBQWdDO1NBQ25FLENBQUM7UUFFRixNQUFNLGlCQUFpQixHQUFHLENBQUEsTUFBQSxJQUFJLENBQUMsV0FBVywwQ0FBRSxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztZQUNoRSxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQjtpQkFDckIsYUFBYSxDQUFDO2dCQUNiLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztnQkFDckIsV0FBVztnQkFDWCxZQUFZLEVBQUUsSUFBSSxDQUFDLGNBQWM7Z0JBQ2pDLEtBQUssRUFBRSxVQUFVO2dCQUNqQixpQkFBaUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCO2dCQUN6QyxjQUFjLEVBQUUsY0FBYzthQUMvQixDQUFDO2lCQUNELEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsdUhBQXVIO1lBQ2xKLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRS9CLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsQ0FBQztZQUM3RCxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDckIsV0FBVztZQUNYLEtBQUs7WUFDTCxXQUFXO1lBQ1gsVUFBVTtZQUNWLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYztZQUNuQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCO1lBQ3pDLGNBQWMsRUFBRSxjQUFjO1NBQy9CLENBQUMsQ0FBQztRQUVILE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsQ0FBQztZQUM3RCxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDckIsV0FBVztZQUNYLEtBQUs7WUFDTCxXQUFXO1lBQ1gsVUFBVTtZQUNWLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYztZQUNuQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCO1lBQ3pDLGNBQWMsRUFBRSxjQUFjO1NBQy9CLENBQUMsQ0FBQztRQUVILE1BQU0seUJBQXlCLEdBQzdCLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxhQUFhLENBQUM7WUFDM0MsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1lBQ3JCLFdBQVc7WUFDWCxLQUFLO1lBQ0wsV0FBVztZQUNYLFVBQVU7WUFDVixjQUFjLEVBQUUsSUFBSSxDQUFDLGNBQWM7WUFDbkMsY0FBYyxFQUFFLGNBQWM7U0FDL0IsQ0FBQyxDQUFDO1FBRUwsTUFBTSxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLGtCQUFrQixDQUFDLEdBQzVELE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztZQUNoQixpQkFBaUI7WUFDakIsaUJBQWlCO1lBQ2pCLGlCQUFpQjtZQUNqQix5QkFBeUI7U0FDMUIsQ0FBQyxDQUFDO1FBRUwsZUFBTSxDQUFDLFNBQVMsQ0FDZCxrQkFBa0IsRUFDbEIsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLGNBQWMsRUFDM0IseUJBQWdCLENBQUMsWUFBWSxDQUM5QixDQUFDO1FBRUYsT0FBTztZQUNMLFVBQVUsRUFBRSxVQUFVO1lBQ3RCLFVBQVUsRUFBRSxVQUFVO1lBQ3RCLFVBQVUsRUFBRSxVQUFVO1lBQ3RCLGtCQUFrQixFQUFFLGtCQUFrQjtTQUN2QixDQUFDO0lBQ3BCLENBQUM7SUFFRCxzR0FBc0c7SUFDdEcseUZBQXlGO0lBQ3pGLDJCQUEyQjtJQUNuQixxQkFBcUIsQ0FDM0IsTUFBc0IsRUFDdEIsYUFBZ0M7UUFFaEMsTUFBTSxFQUFFLG1CQUFtQixFQUFFLEdBQUcsYUFBYSxDQUFDO1FBQzlDLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNwQixNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFFbkIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsR0FBRyxtQkFBbUIsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNuRCxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDO1lBQ3ZDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLG1CQUFRLENBQUMsQ0FBQyxHQUFHLG1CQUFtQixFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUMzRTtRQUVELE9BQU8sQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVPLEtBQUssQ0FBQywrQkFBK0IsQ0FDM0MsS0FBMkMsRUFDM0MsaUJBQW9DLEVBQ3BDLG9CQUEwQztRQUUxQyxNQUFNLEVBQ0osV0FBVyxFQUFFLEVBQUUsU0FBUyxFQUFFLGlCQUFpQixFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxFQUN6RSxtQkFBbUIsRUFBRSxrQkFBa0IsR0FDeEMsR0FBRyxpQkFBaUIsQ0FBQztRQUV0QixNQUFNLG9CQUFvQixHQUFHLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDO1FBQ3ZFLE1BQU0sbUJBQW1CLEdBQ3ZCLG9CQUFvQixDQUFDLHFCQUFxQixDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDekUsTUFBTSxvQkFBb0IsR0FDeEIsb0JBQW9CLENBQUMsc0JBQXNCLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN0RSxNQUFNLGFBQWEsR0FBRyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxlQUFlLENBQ2pFLG1CQUFtQixFQUNuQixvQkFBb0IsQ0FDckIsQ0FBQztRQUNGLE1BQU0sVUFBVSxHQUFHLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUNqRSxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUN0QyxDQUFDO1FBQ0YsdUNBQ0ssdUJBQVUsQ0FBQyx3QkFBd0IsQ0FDcEMsS0FBSyxFQUNMO1lBQ0UsU0FBUztZQUNULGlCQUFpQjtZQUNqQiwyQkFBMkIsRUFBRSxRQUFRO1lBQ3JDLGdCQUFnQjtTQUNqQixFQUNELGlCQUFRLENBQUMsV0FBVyxDQUFDO1lBQ25CLElBQUksRUFBRSxvQkFBb0IsQ0FBQyxJQUFJO1lBQy9CLFNBQVMsRUFBRSxvQkFBb0IsQ0FBQyxTQUFTO1lBQ3pDLFNBQVMsRUFBRSxvQkFBb0IsQ0FBQyxTQUFTO1lBQ3pDLE9BQU8sRUFBRSxVQUFVO2dCQUNqQixDQUFDLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRTtnQkFDekMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUU7WUFDNUMsT0FBTyxFQUFFLFVBQVU7Z0JBQ2pCLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFO2dCQUMxQyxDQUFDLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRTtZQUMzQyxnQkFBZ0IsRUFBRSxLQUFLO1NBQ3hCLENBQUMsRUFDRixrQkFBa0IsRUFDbEIsYUFBYSxDQUFDLGVBQWUsRUFDN0IsYUFBYSxDQUFDLGdCQUFnQixDQUMvQixLQUNELEVBQUUsRUFBRSxJQUFBLCtCQUF3QixFQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFDMUM7SUFDSixDQUFDO0lBRU8sd0JBQXdCLENBQzlCLFlBS0MsRUFDRCxtQkFBd0QsRUFDeEQsVUFBb0IsRUFDcEIsV0FBcUI7UUFFckIsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQzVDLE1BQU0sRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLEdBQUcsWUFBWSxDQUFDO1FBQzlDLElBQUEsZ0JBQUMsRUFBQyxZQUFZLENBQUM7YUFDWixPQUFPLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRTtZQUN2QixNQUFNLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBRSxHQUFHLFdBQVcsQ0FBQztZQUN2RCxPQUFPLGFBQWEsQ0FBQztRQUN2QixDQUFDLENBQUM7YUFDRCxPQUFPLENBQUMsQ0FBQyxPQUFlLEVBQUUsRUFBRTtZQUMzQixpQkFBaUIsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDL0MsQ0FBQyxDQUFDLENBQUM7UUFFTCxLQUFLLE1BQU0sZ0JBQWdCLElBQUksbUJBQW1CLEVBQUU7WUFDbEQsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLGdCQUFnQixDQUFDO1lBQ3RDLGdCQUFDLENBQUMsS0FBSyxDQUNMLGdCQUFnQixDQUFDLFVBQVUsRUFDM0IsQ0FBQyxLQUFxQixFQUFFLGFBQXFCLEVBQUUsRUFBRTtnQkFDL0MsTUFBTSxRQUFRLEdBQ1osZ0JBQUMsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FDOUIsaUJBQWlCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FDN0MsR0FBRyxDQUFDLENBQUM7Z0JBQ1IsZUFBTSxDQUFDLFNBQVMsQ0FDZCxnQkFBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLFFBQVEsR0FBRyxhQUFhLEVBQUUsQ0FBQyxFQUMzQyxRQUFRLEVBQ1IseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO1lBQ0osQ0FBQyxDQUNGLENBQUM7U0FDSDtRQUVELElBQUksVUFBVSxHQUFHLEtBQUssQ0FBQztRQUN2QixJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMxQixLQUFLLE1BQU0sV0FBVyxJQUFJLFlBQVksRUFBRTtZQUN0QyxJQUFJLFdBQVcsQ0FBQyxRQUFRLEtBQUsscUJBQVEsQ0FBQyxFQUFFLEVBQUU7Z0JBQ3hDLFVBQVUsR0FBRyxJQUFJLENBQUM7YUFDbkI7WUFDRCxJQUFJLFdBQVcsQ0FBQyxRQUFRLEtBQUsscUJBQVEsQ0FBQyxFQUFFLEVBQUU7Z0JBQ3hDLFVBQVUsR0FBRyxJQUFJLENBQUM7YUFDbkI7WUFDRCxJQUFJLFdBQVcsQ0FBQyxRQUFRLEtBQUsscUJBQVEsQ0FBQyxFQUFFLEVBQUU7Z0JBQ3hDLFVBQVUsR0FBRyxJQUFJLENBQUM7YUFDbkI7WUFDRCxJQUFJLFdBQVcsQ0FBQyxRQUFRLEtBQUsscUJBQVEsQ0FBQyxLQUFLLEVBQUU7Z0JBQzNDLGFBQWEsR0FBRyxJQUFJLENBQUM7YUFDdEI7U0FDRjtRQUVELElBQUksYUFBYSxJQUFJLENBQUMsVUFBVSxJQUFJLFVBQVUsSUFBSSxVQUFVLENBQUMsRUFBRTtZQUM3RCxJQUFJLGFBQWEsR0FBRyxPQUFPLENBQUM7WUFFNUIsSUFBSSxVQUFVLEVBQUU7Z0JBQ2QsYUFBYSxJQUFJLE9BQU8sQ0FBQzthQUMxQjtZQUVELElBQUksVUFBVSxFQUFFO2dCQUNkLGFBQWEsSUFBSSxPQUFPLENBQUM7YUFDMUI7WUFFRCxJQUFJLFVBQVUsRUFBRTtnQkFDZCxhQUFhLElBQUksT0FBTyxDQUFDO2FBQzFCO1lBRUQsZUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLGFBQWEsWUFBWSxFQUFFLENBQUMsRUFBRSx5QkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMxRSxlQUFNLENBQUMsU0FBUyxDQUNkLEdBQUcsYUFBYSxxQkFBcUIsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUNuRCxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO1lBRUYsSUFBSSxVQUFVLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxJQUFJLFdBQVcsQ0FBQyxRQUFRLENBQUMsRUFBRTtnQkFDL0QsNEpBQTRKO2dCQUM1SixlQUFNLENBQUMsU0FBUyxDQUNkLEdBQUcsYUFBYSwyQkFBMkIsRUFDM0MsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQztnQkFDRixlQUFNLENBQUMsU0FBUyxDQUNkLEdBQUcsYUFBYSxvQ0FBb0MsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUNsRSxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO2FBQ0g7U0FDRjthQUFNLElBQUksVUFBVSxJQUFJLFVBQVUsSUFBSSxVQUFVLEVBQUU7WUFDakQsZUFBTSxDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLEVBQUUseUJBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdEUsZUFBTSxDQUFDLFNBQVMsQ0FDZCxpQ0FBaUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUMvQyxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO1lBRUYsSUFBSSxVQUFVLENBQUMsUUFBUSxJQUFJLFdBQVcsQ0FBQyxRQUFRLEVBQUU7Z0JBQy9DLDRKQUE0SjtnQkFDNUosZUFBTSxDQUFDLFNBQVMsQ0FDZCx1Q0FBdUMsRUFDdkMsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQztnQkFDRixlQUFNLENBQUMsU0FBUyxDQUNkLGdEQUFnRCxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQzlELENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7YUFDSDtTQUNGO2FBQU0sSUFBSSxhQUFhLEVBQUU7WUFDeEIsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDM0IsZUFBTSxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLEVBQUUseUJBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQy9ELGVBQU0sQ0FBQyxTQUFTLENBQ2QsMEJBQTBCLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFDeEMsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQzthQUNIO2lCQUFNO2dCQUNMLGVBQU0sQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFLENBQUMsRUFBRSx5QkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDMUQsZUFBTSxDQUFDLFNBQVMsQ0FDZCxxQkFBcUIsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUNuQyxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO2FBQ0g7U0FDRjthQUFNLElBQUksVUFBVSxFQUFFO1lBQ3JCLElBQUksWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQzNCLGVBQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLENBQUMsRUFBRSx5QkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDNUQsZUFBTSxDQUFDLFNBQVMsQ0FDZCx1QkFBdUIsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUNyQyxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO2FBQ0g7U0FDRjthQUFNLElBQUksVUFBVSxFQUFFO1lBQ3JCLElBQUksWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQzNCLGVBQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLENBQUMsRUFBRSx5QkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDNUQsZUFBTSxDQUFDLFNBQVMsQ0FDZCx1QkFBdUIsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUNyQyxDQUFDLEVBQ0QseUJBQWdCLENBQUMsS0FBSyxDQUN2QixDQUFDO2FBQ0g7aUJBQU07Z0JBQ0wsZUFBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLHlCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUN2RCxlQUFNLENBQUMsU0FBUyxDQUNkLGtCQUFrQixJQUFJLENBQUMsT0FBTyxFQUFFLEVBQ2hDLENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7YUFDSDtTQUNGO2FBQU0sSUFBSSxVQUFVLEVBQUU7WUFDckIsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDM0IsZUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxFQUFFLHlCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUM1RCxlQUFNLENBQUMsU0FBUyxDQUNkLHVCQUF1QixJQUFJLENBQUMsT0FBTyxFQUFFLEVBQ3JDLENBQUMsRUFDRCx5QkFBZ0IsQ0FBQyxLQUFLLENBQ3ZCLENBQUM7YUFDSDtpQkFBTTtnQkFDTCxlQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQUUseUJBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3ZELGVBQU0sQ0FBQyxTQUFTLENBQ2Qsa0JBQWtCLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFDaEMsQ0FBQyxFQUNELHlCQUFnQixDQUFDLEtBQUssQ0FDdkIsQ0FBQzthQUNIO1NBQ0Y7SUFDSCxDQUFDO0lBRU8scUJBQXFCLENBQzNCLFFBQWtCLEVBQ2xCLFlBQWtCLEVBQ2xCLFVBQW1CO1FBRW5CLE1BQU0saUJBQWlCLEdBQUcsaUJBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDMUUsTUFBTSxpQkFBaUIsR0FBRyxpQkFBUSxDQUFDLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUUxRSx1R0FBdUc7UUFDdkcsK0VBQStFO1FBQy9FLElBQ0UsY0FBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLEVBQUUsaUJBQWlCLENBQUM7WUFDakQsY0FBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsaUJBQWlCLENBQUMsRUFDOUM7WUFDQSxPQUFPLElBQUksbUJBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDM0I7UUFFRCxNQUFNLFNBQVMsR0FBRyxjQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDcEQsSUFBSSxZQUFZLEdBQUcsSUFBSSxtQkFBUSxDQUM3QixzQkFBYSxDQUFDLGVBQWUsQ0FDM0IsWUFBWSxFQUNaLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsSUFBSSxDQUNMLEVBQ0Qsc0JBQWEsQ0FBQyxlQUFlLENBQzNCLFlBQVksRUFDWixpQkFBaUIsRUFDakIsU0FBUyxFQUNULElBQUksQ0FDTCxDQUNGLENBQUM7UUFDRixJQUFJLENBQUMsVUFBVTtZQUFFLFlBQVksR0FBRyxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDdEQsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQztJQUVNLEtBQUssQ0FBQyx3QkFBd0IsQ0FDbkMsV0FBbUIsRUFDbkIsU0FBb0IsRUFDcEIsTUFBc0IsRUFDdEIsS0FBcUI7UUFFckIsSUFBSTtZQUNGLE1BQU0sYUFBYSxHQUNqQixTQUFTLEtBQUssb0JBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO1lBQ3ZELElBQUksT0FBTyxDQUFDO1lBQ1osSUFBSSxhQUFhLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRTtnQkFDbkMsT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7YUFDdkQ7aUJBQU07Z0JBQ0wsTUFBTSxhQUFhLEdBQUcsK0JBQWMsQ0FBQyxPQUFPLENBQzFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUM5QixJQUFJLENBQUMsUUFBUSxDQUNkLENBQUM7Z0JBQ0YsT0FBTyxHQUFHLE1BQU0sYUFBYSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQzthQUN0RDtZQUNELE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBUyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUN2RTtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsU0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsbUNBQW1DLENBQUMsQ0FBQztZQUNsRCxPQUFPLEtBQUssQ0FBQztTQUNkO0lBQ0gsQ0FBQztJQUVPLGFBQWEsQ0FBQyxRQUFrQjtRQUN0QyxNQUFNLFlBQVksR0FBRyxjQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsY0FBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNwRSxDQUFDLENBQUMsY0FBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDO1lBQ3JDLENBQUMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDO1FBQ3ZCLE1BQU0sY0FBYyxHQUFHLGNBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxjQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hFLENBQUMsQ0FBQyxjQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUM7WUFDdkMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUM7UUFDekIsT0FBTyxJQUFJLG1CQUFRLENBQUMsWUFBWSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFFTyxxQkFBcUI7UUFDM0IsT0FBTyxJQUFBLHFCQUFLLEVBQ1YsS0FBSyxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsRUFBRTtZQUNwQixJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUU7Z0JBQ2YsU0FBRyxDQUFDLElBQUksQ0FBQyw0QkFBNEIsT0FBTyxFQUFFLENBQUMsQ0FBQzthQUNqRDtZQUNELE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN4QyxDQUFDLEVBQ0Q7WUFDRSxPQUFPLEVBQUUsQ0FBQztZQUNWLFVBQVUsRUFBRSxHQUFHO1lBQ2YsVUFBVSxFQUFFLElBQUk7U0FDakIsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELDhEQUE4RDtJQUM5RCw2SEFBNkg7SUFDN0gsNkVBQTZFO0lBQ3RFLE1BQU0sQ0FBQyw0QkFBNEIsQ0FDeEMsTUFBZSxFQUNmLFlBQTJCLEVBQzNCLFVBQW9CO1FBRXBCLG9IQUFvSDtRQUNwSCxJQUFJLE1BQU0sS0FBSyxTQUFTLElBQUksTUFBTSxLQUFLLGVBQU0sQ0FBQyxPQUFPLEVBQUU7WUFDckQsT0FBTyxLQUFLLENBQUM7U0FDZDtRQUVELHFJQUFxSTtRQUNySSx3QkFBd0I7UUFDeEIsZ0VBQWdFO1FBQ2hFLDRIQUE0SDtRQUM1SCxxSEFBcUg7UUFDckgsSUFBSSxVQUFVLEVBQUU7WUFDZCxPQUFPLElBQUksQ0FBQztTQUNiO1FBRUQsZ0lBQWdJO1FBQ2hJLElBQ0UsWUFBWSxLQUFLLFNBQVM7WUFDMUIsWUFBWSxLQUFLLG1CQUFZLENBQUMsZUFBZSxFQUM3QztZQUNBLE9BQU8sS0FBSyxDQUFDO1NBQ2Q7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7Q0FDRjtBQTdpR0Qsa0NBNmlHQyJ9