@fanx-protocol/smart-order-router 0.0.1

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