UNPKG

@uniswap/smart-order-router

Version:
184 lines 19.5 kB
import { Protocol } from '@uniswap/router-sdk'; import { TradeType } from '@uniswap/sdk-core'; import { Pool as V3Pool } from '@uniswap/v3-sdk'; import { Pool as V4Pool } from '@uniswap/v4-sdk'; import _ from 'lodash'; import { Pair } from '@uniswap/v2-sdk'; import { CurrencyAmount } from '../../../util/amounts'; import { routeToString } from '../../../util/routes'; /** * Represents a quote for swapping on a V2 only route. Contains all information * such as the route used, the amount specified by the user, the type of quote * (exact in or exact out), the quote itself, and gas estimates. * * @export * @class V2RouteWithValidQuote */ export class V2RouteWithValidQuote { constructor({ amount, rawQuote, percent, route, gasModel, quoteToken, tradeType, v2PoolProvider, }) { this.protocol = Protocol.V2; this.amount = amount; this.rawQuote = rawQuote; this.quote = CurrencyAmount.fromRawAmount(quoteToken, rawQuote.toString()); this.percent = percent; this.route = route; this.gasModel = gasModel; this.quoteToken = quoteToken; this.tradeType = tradeType; const { gasEstimate, gasCostInToken, gasCostInUSD, gasCostInGasToken } = this.gasModel.estimateGasCost(this); this.gasCostInToken = gasCostInToken; this.gasCostInUSD = gasCostInUSD; this.gasEstimate = gasEstimate; this.gasCostInGasToken = gasCostInGasToken; // If its exact out, we need to request *more* of the input token to account for the gas. if (this.tradeType == TradeType.EXACT_INPUT) { const quoteGasAdjusted = this.quote.subtract(gasCostInToken); this.quoteAdjustedForGas = quoteGasAdjusted; } else { const quoteGasAdjusted = this.quote.add(gasCostInToken); this.quoteAdjustedForGas = quoteGasAdjusted; } this.poolIdentifiers = _.map(route.pairs, (p) => v2PoolProvider.getPoolAddress(p.token0, p.token1).poolAddress); this.tokenPath = this.route.path; } toString() { return `${this.percent.toFixed(2)}% QuoteGasAdj[${this.quoteAdjustedForGas.toExact()}] Quote[${this.quote.toExact()}] Gas[${this.gasEstimate.toString()}] = ${routeToString(this.route)}`; } } /** * Represents a quote for swapping on a V3 only route. Contains all information * such as the route used, the amount specified by the user, the type of quote * (exact in or exact out), the quote itself, and gas estimates. * * @export * @class V3RouteWithValidQuote */ export class V3RouteWithValidQuote { constructor({ amount, rawQuote, sqrtPriceX96AfterList, initializedTicksCrossedList, quoterGasEstimate, percent, route, gasModel, quoteToken, tradeType, v3PoolProvider, }) { this.protocol = Protocol.V3; this.amount = amount; this.rawQuote = rawQuote; this.sqrtPriceX96AfterList = sqrtPriceX96AfterList; this.initializedTicksCrossedList = initializedTicksCrossedList; this.quoterGasEstimate = quoterGasEstimate; this.quote = CurrencyAmount.fromRawAmount(quoteToken, rawQuote.toString()); this.percent = percent; this.route = route; this.gasModel = gasModel; this.quoteToken = quoteToken; this.tradeType = tradeType; const { gasEstimate, gasCostInToken, gasCostInUSD, gasCostInGasToken } = this.gasModel.estimateGasCost(this); this.gasCostInToken = gasCostInToken; this.gasCostInUSD = gasCostInUSD; this.gasEstimate = gasEstimate; this.gasCostInGasToken = gasCostInGasToken; // If its exact out, we need to request *more* of the input token to account for the gas. if (this.tradeType == TradeType.EXACT_INPUT) { const quoteGasAdjusted = this.quote.subtract(gasCostInToken); this.quoteAdjustedForGas = quoteGasAdjusted; } else { const quoteGasAdjusted = this.quote.add(gasCostInToken); this.quoteAdjustedForGas = quoteGasAdjusted; } this.poolIdentifiers = _.map(route.pools, (p) => v3PoolProvider.getPoolAddress(p.token0, p.token1, p.fee).poolAddress); this.tokenPath = this.route.tokenPath; } toString() { return `${this.percent.toFixed(2)}% QuoteGasAdj[${this.quoteAdjustedForGas.toExact()}] Quote[${this.quote.toExact()}] Gas[${this.gasEstimate.toString()}] = ${routeToString(this.route)}`; } } export class V4RouteWithValidQuote { constructor({ amount, rawQuote, sqrtPriceX96AfterList, initializedTicksCrossedList, quoterGasEstimate, percent, route, gasModel, quoteToken, tradeType, v4PoolProvider, }) { this.protocol = Protocol.V4; this.amount = amount; this.rawQuote = rawQuote; this.sqrtPriceX96AfterList = sqrtPriceX96AfterList; this.initializedTicksCrossedList = initializedTicksCrossedList; this.quoterGasEstimate = quoterGasEstimate; this.quote = CurrencyAmount.fromRawAmount(quoteToken, rawQuote.toString()); this.percent = percent; this.route = route; this.gasModel = gasModel; this.quoteToken = quoteToken; this.tradeType = tradeType; const { gasEstimate, gasCostInToken, gasCostInUSD, gasCostInGasToken } = this.gasModel.estimateGasCost(this); this.gasCostInToken = gasCostInToken; this.gasCostInUSD = gasCostInUSD; this.gasEstimate = gasEstimate; this.gasCostInGasToken = gasCostInGasToken; // If its exact out, we need to request *more* of the input token to account for the gas. if (this.tradeType == TradeType.EXACT_INPUT) { const quoteGasAdjusted = this.quote.subtract(gasCostInToken); this.quoteAdjustedForGas = quoteGasAdjusted; } else { const quoteGasAdjusted = this.quote.add(gasCostInToken); this.quoteAdjustedForGas = quoteGasAdjusted; } this.poolIdentifiers = _.map(route.pools, (p) => v4PoolProvider.getPoolId(p.token0, p.token1, p.fee, p.tickSpacing, p.hooks).poolId); this.tokenPath = this.route.currencyPath; } toString() { return `${this.percent.toFixed(2)}% QuoteGasAdj[${this.quoteAdjustedForGas.toExact()}] Quote[${this.quote.toExact()}] Gas[${this.gasEstimate.toString()}] = ${routeToString(this.route)}`; } } /** * Represents a quote for swapping on a Mixed Route. Contains all information * such as the route used, the amount specified by the user, the type of quote * (exact in or exact out), the quote itself, and gas estimates. * * @export * @class MixedRouteWithValidQuote */ export class MixedRouteWithValidQuote { constructor({ amount, rawQuote, sqrtPriceX96AfterList, initializedTicksCrossedList, quoterGasEstimate, percent, route, mixedRouteGasModel, quoteToken, tradeType, v4PoolProvider, v3PoolProvider, v2PoolProvider, }) { this.protocol = Protocol.MIXED; this.amount = amount; this.rawQuote = rawQuote; this.sqrtPriceX96AfterList = sqrtPriceX96AfterList; this.initializedTicksCrossedList = initializedTicksCrossedList; this.quoterGasEstimate = quoterGasEstimate; this.quote = CurrencyAmount.fromRawAmount(quoteToken, rawQuote.toString()); this.percent = percent; this.route = route; this.gasModel = mixedRouteGasModel; this.quoteToken = quoteToken; this.tradeType = tradeType; const { gasEstimate, gasCostInToken, gasCostInUSD, gasCostInGasToken } = this.gasModel.estimateGasCost(this); this.gasCostInToken = gasCostInToken; this.gasCostInUSD = gasCostInUSD; this.gasEstimate = gasEstimate; this.gasCostInGasToken = gasCostInGasToken; // If its exact out, we need to request *more* of the input token to account for the gas. if (this.tradeType == TradeType.EXACT_INPUT) { const quoteGasAdjusted = this.quote.subtract(gasCostInToken); this.quoteAdjustedForGas = quoteGasAdjusted; } else { const quoteGasAdjusted = this.quote.add(gasCostInToken); this.quoteAdjustedForGas = quoteGasAdjusted; } this.poolIdentifiers = _.map(route.pools, (p) => { if (p instanceof V4Pool) { return v4PoolProvider.getPoolId(p.token0, p.token1, p.fee, p.tickSpacing, p.hooks).poolId; } else if (p instanceof V3Pool) { return v3PoolProvider.getPoolAddress(p.token0, p.token1, p.fee) .poolAddress; } else if (p instanceof Pair) { return v2PoolProvider.getPoolAddress(p.token0, p.token1).poolAddress; } else { throw new Error(`Unknown pool type ${JSON.stringify(p)}`); } }); this.tokenPath = this.route.path; } toString() { return `${this.percent.toFixed(2)}% QuoteGasAdj[${this.quoteAdjustedForGas.toExact()}] Quote[${this.quote.toExact()}] Gas[${this.gasEstimate.toString()}] = ${routeToString(this.route)}`; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUtd2l0aC12YWxpZC1xdW90ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9yb3V0ZXJzL2FscGhhLXJvdXRlci9lbnRpdGllcy9yb3V0ZS13aXRoLXZhbGlkLXF1b3RlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQW1CLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxJQUFJLElBQUksTUFBTSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDakQsT0FBTyxFQUFFLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNqRCxPQUFPLENBQUMsTUFBTSxRQUFRLENBQUM7QUFFdkIsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBSXZDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFvRXJEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLE9BQU8scUJBQXFCO0lBMkJoQyxZQUFZLEVBQ1YsTUFBTSxFQUNOLFFBQVEsRUFDUixPQUFPLEVBQ1AsS0FBSyxFQUNMLFFBQVEsRUFDUixVQUFVLEVBQ1YsU0FBUyxFQUNULGNBQWMsR0FDYztRQW5DZCxhQUFRLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQW9DckMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsSUFBSSxDQUFDLEtBQUssR0FBRyxjQUFjLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUMzRSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUUzQixNQUFNLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsR0FDcEUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFdEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFDL0IsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGlCQUFpQixDQUFDO1FBRTNDLHlGQUF5RjtRQUN6RixJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDLFdBQVcsRUFBRTtZQUMzQyxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzdELElBQUksQ0FBQyxtQkFBbUIsR0FBRyxnQkFBZ0IsQ0FBQztTQUM3QzthQUFNO1lBQ0wsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUN4RCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsZ0JBQWdCLENBQUM7U0FDN0M7UUFFRCxJQUFJLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQzFCLEtBQUssQ0FBQyxLQUFLLEVBQ1gsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsV0FBVyxDQUNyRSxDQUFDO1FBRUYsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztJQUNuQyxDQUFDO0lBbERNLFFBQVE7UUFDYixPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQzVCLENBQUMsQ0FDRixpQkFBaUIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxXQUFXLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLFNBQVMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsT0FBTyxhQUFhLENBQ3pJLElBQUksQ0FBQyxLQUFLLENBQ1gsRUFBRSxDQUFDO0lBQ04sQ0FBQztDQTZDRjtBQWdCRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxPQUFPLHFCQUFxQjtJQTZCaEMsWUFBWSxFQUNWLE1BQU0sRUFDTixRQUFRLEVBQ1IscUJBQXFCLEVBQ3JCLDJCQUEyQixFQUMzQixpQkFBaUIsRUFDakIsT0FBTyxFQUNQLEtBQUssRUFDTCxRQUFRLEVBQ1IsVUFBVSxFQUNWLFNBQVMsRUFDVCxjQUFjLEdBQ2M7UUF4Q2QsYUFBUSxHQUFHLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUF5Q3JDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxxQkFBcUIsQ0FBQztRQUNuRCxJQUFJLENBQUMsMkJBQTJCLEdBQUcsMkJBQTJCLENBQUM7UUFDL0QsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGlCQUFpQixDQUFDO1FBQzNDLElBQUksQ0FBQyxLQUFLLEdBQUcsY0FBYyxDQUFDLGFBQWEsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDM0UsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbkIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDN0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFFM0IsTUFBTSxFQUFFLFdBQVcsRUFBRSxjQUFjLEVBQUUsWUFBWSxFQUFFLGlCQUFpQixFQUFFLEdBQ3BFLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXRDLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQztRQUUzQyx5RkFBeUY7UUFDekYsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLFNBQVMsQ0FBQyxXQUFXLEVBQUU7WUFDM0MsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM3RCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsZ0JBQWdCLENBQUM7U0FDN0M7YUFBTTtZQUNMLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDeEQsSUFBSSxDQUFDLG1CQUFtQixHQUFHLGdCQUFnQixDQUFDO1NBQzdDO1FBRUQsSUFBSSxDQUFDLGVBQWUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUMxQixLQUFLLENBQUMsS0FBSyxFQUNYLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FDSixjQUFjLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsV0FBVyxDQUN2RSxDQUFDO1FBRUYsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztJQUN4QyxDQUFDO0lBekRNLFFBQVE7UUFDYixPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQzVCLENBQUMsQ0FDRixpQkFBaUIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxXQUFXLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLFNBQVMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsT0FBTyxhQUFhLENBQ3pJLElBQUksQ0FBQyxLQUFLLENBQ1gsRUFBRSxDQUFDO0lBQ04sQ0FBQztDQW9ERjtBQWdCRCxNQUFNLE9BQU8scUJBQXFCO0lBNkJoQyxZQUFZLEVBQ1YsTUFBTSxFQUNOLFFBQVEsRUFDUixxQkFBcUIsRUFDckIsMkJBQTJCLEVBQzNCLGlCQUFpQixFQUNqQixPQUFPLEVBQ1AsS0FBSyxFQUNMLFFBQVEsRUFDUixVQUFVLEVBQ1YsU0FBUyxFQUNULGNBQWMsR0FDYztRQXhDZCxhQUFRLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQXlDckMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsSUFBSSxDQUFDLHFCQUFxQixHQUFHLHFCQUFxQixDQUFDO1FBQ25ELElBQUksQ0FBQywyQkFBMkIsR0FBRywyQkFBMkIsQ0FBQztRQUMvRCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsaUJBQWlCLENBQUM7UUFDM0MsSUFBSSxDQUFDLEtBQUssR0FBRyxjQUFjLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUMzRSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUUzQixNQUFNLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsR0FDcEUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFdEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFDL0IsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGlCQUFpQixDQUFDO1FBRTNDLHlGQUF5RjtRQUN6RixJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDLFdBQVcsRUFBRTtZQUMzQyxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzdELElBQUksQ0FBQyxtQkFBbUIsR0FBRyxnQkFBZ0IsQ0FBQztTQUM3QzthQUFNO1lBQ0wsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUN4RCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsZ0JBQWdCLENBQUM7U0FDN0M7UUFFRCxJQUFJLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQzFCLEtBQUssQ0FBQyxLQUFLLEVBQ1gsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUNKLGNBQWMsQ0FBQyxTQUFTLENBQ3RCLENBQUMsQ0FBQyxNQUFNLEVBQ1IsQ0FBQyxDQUFDLE1BQU0sRUFDUixDQUFDLENBQUMsR0FBRyxFQUNMLENBQUMsQ0FBQyxXQUFXLEVBQ2IsQ0FBQyxDQUFDLEtBQUssQ0FDUixDQUFDLE1BQU0sQ0FDWCxDQUFDO1FBRUYsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQztJQUMzQyxDQUFDO0lBL0RNLFFBQVE7UUFDYixPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQzVCLENBQUMsQ0FDRixpQkFBaUIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxXQUFXLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLFNBQVMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsT0FBTyxhQUFhLENBQ3pJLElBQUksQ0FBQyxLQUFLLENBQ1gsRUFBRSxDQUFDO0lBQ04sQ0FBQztDQTBERjtBQWtCRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxPQUFPLHdCQUF3QjtJQTZCbkMsWUFBWSxFQUNWLE1BQU0sRUFDTixRQUFRLEVBQ1IscUJBQXFCLEVBQ3JCLDJCQUEyQixFQUMzQixpQkFBaUIsRUFDakIsT0FBTyxFQUNQLEtBQUssRUFDTCxrQkFBa0IsRUFDbEIsVUFBVSxFQUNWLFNBQVMsRUFDVCxjQUFjLEVBQ2QsY0FBYyxFQUNkLGNBQWMsR0FDaUI7UUExQ2pCLGFBQVEsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDO1FBMkN4QyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMscUJBQXFCLEdBQUcscUJBQXFCLENBQUM7UUFDbkQsSUFBSSxDQUFDLDJCQUEyQixHQUFHLDJCQUEyQixDQUFDO1FBQy9ELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQztRQUMzQyxJQUFJLENBQUMsS0FBSyxHQUFHLGNBQWMsQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQzNFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxRQUFRLEdBQUcsa0JBQWtCLENBQUM7UUFDbkMsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDN0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFFM0IsTUFBTSxFQUFFLFdBQVcsRUFBRSxjQUFjLEVBQUUsWUFBWSxFQUFFLGlCQUFpQixFQUFFLEdBQ3BFLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXRDLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQztRQUUzQyx5RkFBeUY7UUFDekYsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLFNBQVMsQ0FBQyxXQUFXLEVBQUU7WUFDM0MsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM3RCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsZ0JBQWdCLENBQUM7U0FDN0M7YUFBTTtZQUNMLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDeEQsSUFBSSxDQUFDLG1CQUFtQixHQUFHLGdCQUFnQixDQUFDO1NBQzdDO1FBRUQsSUFBSSxDQUFDLGVBQWUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUM5QyxJQUFJLENBQUMsWUFBWSxNQUFNLEVBQUU7Z0JBQ3ZCLE9BQU8sY0FBYyxDQUFDLFNBQVMsQ0FDN0IsQ0FBQyxDQUFDLE1BQU0sRUFDUixDQUFDLENBQUMsTUFBTSxFQUNSLENBQUMsQ0FBQyxHQUFHLEVBQ0wsQ0FBQyxDQUFDLFdBQVcsRUFDYixDQUFDLENBQUMsS0FBSyxDQUNSLENBQUMsTUFBTSxDQUFDO2FBQ1Y7aUJBQU0sSUFBSSxDQUFDLFlBQVksTUFBTSxFQUFFO2dCQUM5QixPQUFPLGNBQWMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUM7cUJBQzVELFdBQVcsQ0FBQzthQUNoQjtpQkFBTSxJQUFJLENBQUMsWUFBWSxJQUFJLEVBQUU7Z0JBQzVCLE9BQU8sY0FBYyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxXQUFXLENBQUM7YUFDdEU7aUJBQU07Z0JBQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDM0Q7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7SUFDbkMsQ0FBQztJQXhFTSxRQUFRO1FBQ2IsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUM1QixDQUFDLENBQ0YsaUJBQWlCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsV0FBVyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxTQUFTLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLE9BQU8sYUFBYSxDQUN6SSxJQUFJLENBQUMsS0FBSyxDQUNYLEVBQUUsQ0FBQztJQUNOLENBQUM7Q0FtRUYifQ==