diff --git a/lib/app/create/deposit/deposit_cubit.dart b/lib/app/create/deposit/deposit_cubit.dart index 584c703..feec52d 100644 --- a/lib/app/create/deposit/deposit_cubit.dart +++ b/lib/app/create/deposit/deposit_cubit.dart @@ -5,6 +5,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:web3kit/web3kit.dart'; import 'package:zup_app/app/app_cubit/app_cubit.dart'; import 'package:zup_app/core/cache.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart'; import 'package:zup_app/core/dtos/deposit_settings_dto.dart'; import 'package:zup_app/core/dtos/pool_search_filters_dto.dart'; import 'package:zup_app/core/dtos/pool_search_settings_dto.dart'; @@ -12,7 +13,6 @@ import 'package:zup_app/core/dtos/yield_dto.dart'; import 'package:zup_app/core/dtos/yields_dto.dart'; import 'package:zup_app/core/enums/networks.dart'; import 'package:zup_app/core/mixins/keys_mixin.dart'; -import 'package:zup_app/core/mixins/v3_pool_conversors_mixin.dart'; import 'package:zup_app/core/pool_service.dart'; import 'package:zup_app/core/repositories/yield_repository.dart'; import 'package:zup_app/core/slippage.dart'; @@ -22,7 +22,7 @@ import 'package:zup_core/zup_core.dart'; part 'deposit_cubit.freezed.dart'; part 'deposit_state.dart'; -class DepositCubit extends Cubit with KeysMixin, V3PoolConversorsMixin { +class DepositCubit extends Cubit with KeysMixin, CLPoolConversorsMixin { DepositCubit( this._yieldRepository, this._zupSingletonCache, @@ -41,26 +41,26 @@ class DepositCubit extends Cubit with KeysMixin, V3PoolConversorsM final AppCubit _appCubit; final ZupAnalytics _zupAnalytics; - final StreamController _pooltickStreamController = StreamController.broadcast(); + final StreamController _poolSqrtPriceX96StreamController = StreamController.broadcast(); final StreamController _selectedYieldStreamController = StreamController.broadcast(); - final Duration _poolTickExpiration = const Duration(seconds: 30); + final Duration _poolSqrtPriceX96CacheExpiration = const Duration(seconds: 30); - BigInt? _latestPoolTick; + BigInt? _latestPoolSqrtPriceX96; YieldDto? _selectedYield; late final Stream selectedYieldStream = _selectedYieldStreamController.stream; - late final Stream poolTickStream = _pooltickStreamController.stream; + late final Stream poolSqrtPriceX96Stream = _poolSqrtPriceX96StreamController.stream; YieldDto? get selectedYield => _selectedYield; - BigInt? get latestPoolTick => _latestPoolTick; + BigInt? get latestPoolSqrtPriceX96 => _latestPoolSqrtPriceX96; DepositSettingsDto get depositSettings => _cache.getDepositSettings(); PoolSearchSettingsDto get poolSearchSettings => _cache.getPoolSearchSettings(); void setup() async { - Timer.periodic(_poolTickExpiration, (timer) { - if (_pooltickStreamController.isClosed) return timer.cancel(); + Timer.periodic(_poolSqrtPriceX96CacheExpiration, (timer) { + if (_poolSqrtPriceX96StreamController.isClosed) return timer.cancel(); - if (selectedYield != null) getSelectedPoolTick(); + if (selectedYield != null) getSelectedPoolSqrtPriceX96(); }); } @@ -116,29 +116,29 @@ class DepositCubit extends Cubit with KeysMixin, V3PoolConversorsM _selectedYieldStreamController.add(selectedYield); if (selectedYield != null) { - _latestPoolTick = BigInt.parse(yieldDto!.latestTick); - _pooltickStreamController.add(_latestPoolTick); + _latestPoolSqrtPriceX96 = BigInt.parse(yieldDto!.latestSqrtPriceX96); + _poolSqrtPriceX96StreamController.add(_latestPoolSqrtPriceX96); - await getSelectedPoolTick(forceRefresh: true); + await getSelectedPoolSqrtPriceX96(forceRefresh: true); } } - Future getSelectedPoolTick({bool forceRefresh = false}) async { + Future getSelectedPoolSqrtPriceX96({bool forceRefresh = false}) async { if (selectedYield == null) return; final selectedYieldBeforeCall = selectedYield; - final tick = await _zupSingletonCache.run( - () => _poolService.getPoolTick(selectedYieldBeforeCall!), - expiration: _poolTickExpiration - const Duration(seconds: 1), + final sqrtPriceX96 = await _zupSingletonCache.run( + () => _poolService.getSqrtPriceX96(selectedYieldBeforeCall!), + expiration: _poolSqrtPriceX96CacheExpiration - const Duration(seconds: 1), ignoreCache: forceRefresh, - key: poolTickCacheKey(network: selectedYield!.network, poolAddress: selectedYield!.poolAddress), + key: poolSqrtPriceCacheKey(network: selectedYield!.network, poolAddress: selectedYield!.poolAddress), ); - if (selectedYieldBeforeCall != selectedYield) return await getSelectedPoolTick(); + if (selectedYieldBeforeCall != selectedYield) return await getSelectedPoolSqrtPriceX96(); - _pooltickStreamController.add(tick); - _latestPoolTick = tick; + _poolSqrtPriceX96StreamController.add(sqrtPriceX96); + _latestPoolSqrtPriceX96 = sqrtPriceX96; } Future getWalletTokenAmount(String tokenAddress, {required AppNetworks network}) async { @@ -172,7 +172,7 @@ class DepositCubit extends Cubit with KeysMixin, V3PoolConversorsM @override Future close() async { - await _pooltickStreamController.close(); + await _poolSqrtPriceX96StreamController.close(); await _selectedYieldStreamController.close(); return super.close(); } diff --git a/lib/app/create/deposit/deposit_page.dart b/lib/app/create/deposit/deposit_page.dart index bb72b47..d996f43 100644 --- a/lib/app/create/deposit/deposit_page.dart +++ b/lib/app/create/deposit/deposit_page.dart @@ -14,6 +14,10 @@ import 'package:zup_app/app/create/deposit/widgets/preview_deposit_modal/preview import 'package:zup_app/app/create/deposit/widgets/range_selector.dart'; import 'package:zup_app/app/create/deposit/widgets/token_amount_input_card/token_amount_input_card.dart'; import 'package:zup_app/core/cache.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_liquidity_calculations_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_sqrt_price_math_mixin.dart'; import 'package:zup_app/core/dtos/deposit_settings_dto.dart'; import 'package:zup_app/core/dtos/pool_search_filters_dto.dart'; import 'package:zup_app/core/dtos/token_dto.dart'; @@ -26,12 +30,9 @@ import 'package:zup_app/core/extensions/num_extension.dart'; import 'package:zup_app/core/extensions/string_extension.dart'; import 'package:zup_app/core/extensions/widget_extension.dart'; import 'package:zup_app/core/injections.dart'; -import 'package:zup_app/core/mixins/v3_pool_conversors_mixin.dart'; -import 'package:zup_app/core/mixins/v3_pool_liquidity_calculations_mixin.dart'; import 'package:zup_app/core/pool_service.dart'; import 'package:zup_app/core/repositories/yield_repository.dart'; import 'package:zup_app/core/slippage.dart'; -import 'package:zup_app/core/v3_v4_pool_constants.dart'; import 'package:zup_app/core/zup_analytics.dart'; import 'package:zup_app/core/zup_navigator.dart'; import 'package:zup_app/core/zup_route_params_names.dart'; @@ -73,7 +74,12 @@ class DepositPage extends StatefulWidget { } class _DepositPageState extends State - with V3PoolConversorsMixin, V3PoolLiquidityCalculationsMixin, DeviceInfoMixin { + with + CLPoolConversorsMixin, + CLPoolLiquidityCalculationsMixin, + DeviceInfoMixin, + CLPoolLiquidityCalculationsMixin, + CLSqrtPriceMath { final lottieClick = inject(instanceName: InjectInstanceNames.lottieClick); final lottieEmpty = inject(instanceName: InjectInstanceNames.lottieEmpty); final lottieRadar = inject(instanceName: InjectInstanceNames.lottieRadar); @@ -125,7 +131,7 @@ class _DepositPageState extends State double maxPrice = 0; RangeController minRangeController = RangeController(); RangeController maxRangeController = RangeController(); - StreamSubscription? _poolTickStreamSubscription; + StreamSubscription? _poolSqrtPriceX96StreamSubscription; YieldTimeFrame selectedYieldTimeFrame = YieldTimeFrame.day; late Slippage selectedSlippage = _cubit.depositSettings.slippage; @@ -142,19 +148,19 @@ class _DepositPageState extends State bool get isQuoteTokenNeeded => !isOutOfRange.minPrice; double get currentPrice { - if (_cubit.latestPoolTick == null || _cubit.selectedYield == null) return 0; + if (_cubit.latestPoolSqrtPriceX96 == null || _cubit.selectedYield == null) return 0; - final price = tickToPrice( - tick: _cubit.latestPoolTick!, + final price = sqrtPriceX96ToPrice( + sqrtPriceX96: _cubit.latestPoolSqrtPriceX96!, poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals, poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals, ); - return areTokensReversed ? price.priceAsQuoteToken : price.priceAsBaseToken; + return areTokensReversed ? price.token1PerToken0 : price.token0PerToken1; } ({bool minPrice, bool maxPrice, bool any}) get isOutOfRange { - if (_cubit.latestPoolTick == null) return (minPrice: false, maxPrice: false, any: false); + if (_cubit.latestPoolSqrtPriceX96 == null) return (minPrice: false, maxPrice: false, any: false); final isMinPriceOutOfRange = !isMinRangeInfinity && (minPrice) > currentPrice; final isMaxPriceOutOfRange = !isMaxRangeInfinity && (maxPrice) < currentPrice; @@ -231,19 +237,19 @@ class _DepositPageState extends State } void calculateDepositTokensAmount() { - if (_cubit.latestPoolTick == null || _cubit.selectedYield == null) return; + if (_cubit.latestPoolSqrtPriceX96 == null || _cubit.selectedYield == null) return; if (isOutOfRange.minPrice) return quoteTokenAmountController.clear(); if (isOutOfRange.maxPrice) return baseTokenAmountController.clear(); final maxTickPrice = tickToPrice( - tick: V3V4PoolConstants.maxTick, + tick: CLPoolConstants.maxTick, poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals, poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals, ); final minTickPrice = tickToPrice( - tick: V3V4PoolConstants.minTick, + tick: CLPoolConstants.minTick, poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals, poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals, ); @@ -262,19 +268,19 @@ class _DepositPageState extends State final newQuoteTokenAmount = Decimal.tryParse( calculateToken1AmountFromToken0( - double.tryParse(baseTokenAmountController.text) ?? 0, - currentPrice, - getMinPrice(), - getMaxPrice(), + currentPrice: currentPrice, + priceLower: getMinPrice(), + priceUpper: getMaxPrice(), + tokenXAmount: double.tryParse(baseTokenAmountController.text) ?? 0, ).toString(), )?.toStringAsFixed(quoteToken.decimals[_cubit.selectedYield!.network.chainId]!); final newBaseTokenAmount = Decimal.tryParse( calculateToken0AmountFromToken1( - double.tryParse(quoteTokenAmountController.text) ?? 0, - currentPrice, - getMinPrice(), - getMaxPrice(), + currentPrice: currentPrice, + priceLower: getMinPrice(), + priceUpper: getMaxPrice(), + tokenYAmount: double.tryParse(quoteTokenAmountController.text) ?? 0, ).toString(), )?.toStringAsFixed(baseToken.decimals[_cubit.selectedYield!.network.chainId]!); @@ -349,7 +355,7 @@ class _DepositPageState extends State token1DepositAmountController: areTokensReversed ? baseTokenAmountController : quoteTokenAmountController, maxPrice: (isInfinity: isMaxRangeInfinity, price: maxPrice), minPrice: (isInfinity: isMinRangeInfinity, price: minPrice), - ).show(context, currentPoolTick: _cubit.latestPoolTick ?? BigInt.zero); + ).show(context, currentPriceX96: _cubit.latestPoolSqrtPriceX96 ?? BigInt.zero); }, ); } @@ -386,8 +392,8 @@ class _DepositPageState extends State ); }); - _poolTickStreamSubscription = _cubit.poolTickStream.listen((poolTick) { - if (poolTick != null) { + _poolSqrtPriceX96StreamSubscription = _cubit.poolSqrtPriceX96Stream.listen((sqrtPriceX96) { + if (sqrtPriceX96 != null) { WidgetsBinding.instance.addPostFrameCallback((_) { setState(() => calculateDepositTokensAmount()); }); @@ -401,7 +407,7 @@ class _DepositPageState extends State void dispose() { minRangeController.dispose(); maxRangeController.dispose(); - _poolTickStreamSubscription?.cancel(); + _poolSqrtPriceX96StreamSubscription?.cancel(); super.dispose(); } @@ -949,21 +955,21 @@ class _DepositPageState extends State if (isMobileSize(context)) ...[const SizedBox(height: 5), tokenSwitcher, const SizedBox(height: 5)], const SizedBox(height: 10), StreamBuilder( - stream: _cubit.poolTickStream, - initialData: _cubit.latestPoolTick, - builder: (context, poolTickSnapshot) { + stream: _cubit.poolSqrtPriceX96Stream, + initialData: _cubit.latestPoolSqrtPriceX96, + builder: (context, poolSqrtPriceX96Snaphot) { return Text( "1 ${baseToken.symbol} ≈ ${() { - final currentPrice = tickToPrice(tick: poolTickSnapshot.data ?? BigInt.zero, poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals, poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals); + final currentPrice = sqrtPriceX96ToPrice(sqrtPriceX96: poolSqrtPriceX96Snaphot.data ?? BigInt.zero, poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals, poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals); - return areTokensReversed ? currentPrice.priceAsQuoteToken : currentPrice.priceAsBaseToken; + return areTokensReversed ? currentPrice.token1PerToken0 : currentPrice.token0PerToken1; }.call().formatCurrency(useLessThan: true, maxDecimals: 4, isUSD: false)} ${quoteToken.symbol}", style: TextStyle( fontSize: 17, fontWeight: FontWeight.w500, color: ZupThemeColors.primaryText.themed(context.brightness), ), - ).redacted(enabled: poolTickSnapshot.data == null); + ).redacted(enabled: poolSqrtPriceX96Snaphot.data == null); }, ), const SizedBox(height: 10), @@ -1006,8 +1012,8 @@ class _DepositPageState extends State ), const SizedBox(height: 10), StreamBuilder( - stream: _cubit.poolTickStream, - builder: (context, snapshot) { + stream: _cubit.poolSqrtPriceX96Stream, + builder: (context, _) { return RangeSelector( key: const Key("min-price-selector"), onUserType: () => percentRange = null, @@ -1049,8 +1055,8 @@ class _DepositPageState extends State ), const SizedBox(height: 6), StreamBuilder( - stream: _cubit.poolTickStream, - builder: (context, snapshot) { + stream: _cubit.poolSqrtPriceX96Stream, + builder: (context, _) { return RangeSelector( key: const Key("max-price-selector"), displayBaseTokenSymbol: baseToken.symbol, @@ -1109,9 +1115,9 @@ class _DepositPageState extends State duration: const Duration(milliseconds: 300), opacity: isRangeInvalid ? 0.2 : 1, child: StreamBuilder( - stream: _cubit.poolTickStream, - initialData: _cubit.latestPoolTick, - builder: (context, poolTickSnapshot) { + stream: _cubit.poolSqrtPriceX96Stream, + initialData: _cubit.latestPoolSqrtPriceX96, + builder: (context, sqrtPriceX96Snapshot) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -1130,7 +1136,7 @@ class _DepositPageState extends State } if (!isBaseTokenAmountUserInput && - !poolTickSnapshot.hasData && + !sqrtPriceX96Snapshot.hasData && quoteTokenAmountController.text.isNotEmpty) { return S.of(context).loading; } @@ -1159,7 +1165,7 @@ class _DepositPageState extends State } if (isBaseTokenAmountUserInput && - !poolTickSnapshot.hasData && + !sqrtPriceX96Snapshot.hasData && baseTokenAmountController.text.isNotEmpty) { return S.of(context).loading; } diff --git a/lib/app/create/deposit/widgets/deposit_settings_dropdown_child.dart b/lib/app/create/deposit/widgets/deposit_settings_dropdown_child.dart index f4e0827..27443d8 100644 --- a/lib/app/create/deposit/widgets/deposit_settings_dropdown_child.dart +++ b/lib/app/create/deposit/widgets/deposit_settings_dropdown_child.dart @@ -67,26 +67,26 @@ class _DepositSettingsDropdownChildState extends State(), poolService: inject(), permit2: inject(), - initialPoolTick: currentPoolTick, + currentPriceX96: currentPriceX96, navigatorKey: inject>(), ), child: PreviewDepositModal( @@ -93,7 +94,8 @@ class PreviewDepositModal extends StatefulWidget with DeviceInfoMixin { State createState() => _PreviewDepositModalState(); } -class _PreviewDepositModalState extends State with V3PoolConversorsMixin, DeviceInfoMixin { +class _PreviewDepositModalState extends State + with CLPoolConversorsMixin, CLSqrtPriceMath, DeviceInfoMixin { final zupCachedImage = inject(); final navigator = inject(); final zupLinks = inject(); @@ -125,36 +127,34 @@ class _PreviewDepositModalState extends State with V3PoolCo PreviewDepositModalCubit get cubit => context.read(); double get baseTokenAmount => isReversedLocal - ? widget.token1DepositAmountController.parseTextToDouble - : widget.token0DepositAmountController.parseTextToDouble; + ? widget.token1DepositAmountController.parseTextToDoubleOrZero + : widget.token0DepositAmountController.parseTextToDoubleOrZero; double get quoteTokenAmount => isReversedLocal - ? widget.token0DepositAmountController.parseTextToDouble - : widget.token1DepositAmountController.parseTextToDouble; + ? widget.token0DepositAmountController.parseTextToDoubleOrZero + : widget.token1DepositAmountController.parseTextToDoubleOrZero; - BigInt get token0DepositAmount => widget.token0DepositAmountController.parseTextToDouble.parseTokenAmount( + BigInt get token0DepositAmount => widget.token0DepositAmountController.parseTextToDoubleOrZero.parseTokenAmount( decimals: widget.currentYield.token0NetworkDecimals, ); - BigInt get token1DepositAmount => widget.token1DepositAmountController.parseTextToDouble.parseTokenAmount( + BigInt get token1DepositAmount => widget.token1DepositAmountController.parseTextToDoubleOrZero.parseTokenAmount( decimals: widget.currentYield.token1NetworkDecimals, ); double get currentPrice { - final currentTick = cubit.latestPoolTick; - - final price = tickToPrice( - tick: currentTick, + final price = sqrtPriceX96ToPrice( + sqrtPriceX96: cubit.latestPriceX96, poolToken0Decimals: widget.currentYield.token0NetworkDecimals, poolToken1Decimals: widget.currentYield.token1NetworkDecimals, ); - return isReversedLocal ? price.priceAsQuoteToken : price.priceAsBaseToken; + return isReversedLocal ? price.token1PerToken0 : price.token0PerToken1; } double get minPrice { BigInt tick() { - if (widget.isReversed != isReversedLocal && widget.maxPrice.isInfinity) return V3V4PoolConstants.minTick; + if (widget.isReversed != isReversedLocal && widget.maxPrice.isInfinity) return CLPoolConstants.minTick; return priceToTick( price: (widget.isReversed == !isReversedLocal) ? widget.maxPrice.price : widget.minPrice.price, @@ -175,7 +175,7 @@ class _PreviewDepositModalState extends State with V3PoolCo double get maxPrice { BigInt tick() { - if (widget.isReversed != isReversedLocal && widget.minPrice.isInfinity) return V3V4PoolConstants.minTick; + if (widget.isReversed != isReversedLocal && widget.minPrice.isInfinity) return CLPoolConstants.minTick; return priceToTick( price: (widget.isReversed == !isReversedLocal) ? widget.minPrice.price : widget.maxPrice.price, @@ -359,13 +359,15 @@ class _PreviewDepositModalState extends State with V3PoolCo showAsBottomSheet: isMobileSize(context), ); }, - slippageCheckError: () { + slippageCheckError: (isAutoSlippage) { ScaffoldMessenger.of(context).hideCurrentSnackBar(); return ScaffoldMessenger.of(context).showSnackBar( ZupSnackBar( context, - message: S.of(context).previewDepositModalSlippageCheckErrorMessage, + message: isAutoSlippage + ? S.of(context).previewDepositModalAutoSlippageCheckErrorMessage + : S.of(context).previewDepositModalSlippageCheckErrorMessage, type: ZupSnackBarType.error, ), ); @@ -413,8 +415,8 @@ class _PreviewDepositModalState extends State with V3PoolCo ), const SizedBox(width: 10), StreamBuilder( - stream: cubit.poolTickStream, - builder: (context, tickSnapshot) { + stream: cubit.poolSqrtPriceX96Stream, + builder: (context, _) { return ZupTag( title: isOutOfRange.any ? S.of(context).previewDepositModalOutOfRange diff --git a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart index 1c96778..0550ad4 100644 --- a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart +++ b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart @@ -10,12 +10,12 @@ import 'package:zup_app/abis/erc_20.abi.g.dart'; import 'package:zup_app/abis/uniswap_permit2.abi.g.dart'; import 'package:zup_app/abis/uniswap_v3_position_manager.abi.g.dart'; import 'package:zup_app/app/create/deposit/widgets/deposit_success_modal.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart'; import 'package:zup_app/core/dtos/token_dto.dart'; import 'package:zup_app/core/dtos/yield_dto.dart'; -import 'package:zup_app/core/mixins/v3_pool_conversors_mixin.dart'; import 'package:zup_app/core/pool_service.dart'; import 'package:zup_app/core/slippage.dart'; -import 'package:zup_app/core/v3_v4_pool_constants.dart'; import 'package:zup_app/core/zup_analytics.dart'; import 'package:zup_app/l10n/gen/app_localizations.dart'; import 'package:zup_core/mixins/device_info_mixin.dart'; @@ -24,9 +24,9 @@ import 'package:zup_ui_kit/zup_ui_kit.dart'; part "preview_deposit_modal_cubit.freezed.dart"; part "preview_deposit_modal_state.dart"; -class PreviewDepositModalCubit extends Cubit with V3PoolConversorsMixin, DeviceInfoMixin { +class PreviewDepositModalCubit extends Cubit with CLPoolConversorsMixin, DeviceInfoMixin { PreviewDepositModalCubit({ - required BigInt initialPoolTick, + required BigInt currentPriceX96, required PoolService poolService, required YieldDto currentYield, required Erc20 erc20, @@ -39,7 +39,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po _poolRepository = poolService, _erc20 = erc20, _wallet = wallet, - _latestPoolTick = initialPoolTick, + _latestPriceX96 = currentPriceX96, _navigatorKey = navigatorKey, _zupAnalytics = zupAnalytics, _permit2 = permit2, @@ -54,24 +54,24 @@ class PreviewDepositModalCubit extends Cubit with V3Po final ZupAnalytics _zupAnalytics; final UniswapPermit2 _permit2; - final StreamController _poolTickStreamController = StreamController.broadcast(); + final StreamController _poolSqrtPriceX96StreamController = StreamController.broadcast(); - BigInt _latestPoolTick = BigInt.zero; + BigInt _latestPriceX96 = BigInt.zero; BigInt _token0Allowance = BigInt.zero; BigInt _token1Allowance = BigInt.zero; - Stream get poolTickStream => _poolTickStreamController.stream; - BigInt get latestPoolTick => _latestPoolTick; + Stream get poolSqrtPriceX96Stream => _poolSqrtPriceX96StreamController.stream; + BigInt get latestPriceX96 => _latestPriceX96; BigInt get token0Allowance => _token0Allowance; BigInt get token1Allowance => _token1Allowance; Future setup() async { - _poolTickStreamController.add(_latestPoolTick); + _poolSqrtPriceX96StreamController.add(_latestPriceX96); Timer.periodic(const Duration(minutes: 1), (timer) { - if (_poolTickStreamController.isClosed) return timer.cancel(); + if (_poolSqrtPriceX96StreamController.isClosed) return timer.cancel(); - _updateTick(); + _updateSqrtPriceX96(); }); await _getTokensAllowance(); @@ -161,8 +161,8 @@ class PreviewDepositModalCubit extends Cubit with V3Po BigInt tickLower() { BigInt convertPriceToTickLower() { - if (isMinPriceInfinity && !isReversed) return V3V4PoolConstants.minTick; - if (isReversed && isMaxPriceInfinity) return V3V4PoolConstants.minTick; + if (isMinPriceInfinity && !isReversed) return CLPoolConstants.minTick; + if (isReversed && isMaxPriceInfinity) return CLPoolConstants.minTick; return priceToTick( price: isReversed ? maxPrice : minPrice, @@ -177,8 +177,8 @@ class PreviewDepositModalCubit extends Cubit with V3Po BigInt tickUpper() { BigInt convertPriceToTickUpper() { - if (isMaxPriceInfinity && !isReversed) return V3V4PoolConstants.maxTick; - if (isReversed && isMinPriceInfinity) return V3V4PoolConstants.maxTick; + if (isMaxPriceInfinity && !isReversed) return CLPoolConstants.maxTick; + if (isReversed && isMinPriceInfinity) return CLPoolConstants.maxTick; return priceToTick( price: isReversed ? minPrice : maxPrice, @@ -193,8 +193,6 @@ class PreviewDepositModalCubit extends Cubit with V3Po final amount0Desired = token0Amount; final amount1Desired = token1Amount; - final amount0Min = slippage.calculateMinTokenAmountFromSlippage(amount0Desired); - final amount1Min = slippage.calculateMinTokenAmountFromSlippage(amount1Desired); final recipient = await _wallet.signer!.address; final TransactionResponse tx = await () async { @@ -205,11 +203,10 @@ class PreviewDepositModalCubit extends Cubit with V3Po amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, recipient: recipient, tickLower: tickLower(), tickUpper: tickUpper(), + slippage: slippage, ); } @@ -224,8 +221,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po tickUpper: tickUpper(), amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: slippage.calculateMaxTokenAmountFromSlippage(amount0Desired), - maxAmount1ToDeposit: slippage.calculateMaxTokenAmountFromSlippage(amount1Desired), + slippage: slippage, recipient: recipient, ); }.call(); @@ -243,7 +239,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po ); } catch (e) { if (e.toString().toLowerCase().contains("slippage")) { - emit(const PreviewDepositModalState.slippageCheckError()); + emit(PreviewDepositModalState.slippageCheckError(slippage.isAutomatic)); emit(PreviewDepositModalState.initial(token0Allowance: _token0Allowance, token1Allowance: _token1Allowance)); return; @@ -297,15 +293,15 @@ class PreviewDepositModalCubit extends Cubit with V3Po } } - Future _updateTick() async { + Future _updateSqrtPriceX96() async { try { - _latestPoolTick = await _poolRepository.getPoolTick(_yield); - _poolTickStreamController.add(_latestPoolTick); + _latestPriceX96 = await _poolRepository.getSqrtPriceX96(_yield); + _poolSqrtPriceX96StreamController.add(_latestPriceX96); } catch (_) { // DO NOTHING } - return _latestPoolTick; + return _latestPriceX96; } void _waitTransactionFinishBeforeClosing() { @@ -384,7 +380,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po return _waitTransactionFinishBeforeClosing(); } - await _poolTickStreamController.close(); + await _poolSqrtPriceX96StreamController.close(); super.close(); } } diff --git a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_state.dart b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_state.dart index de255d2..f5f4234 100644 --- a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_state.dart +++ b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_state.dart @@ -1,9 +1,6 @@ part of 'preview_deposit_modal_cubit.dart'; -enum WaitingTransactionType { - deposit, - approve, -} +enum WaitingTransactionType { deposit, approve } @freezed class PreviewDepositModalState with _$PreviewDepositModalState { @@ -18,7 +15,7 @@ class PreviewDepositModalState with _$PreviewDepositModalState { const factory PreviewDepositModalState.approveSuccess({required String txId, required String symbol}) = _ApproveSuccess; const factory PreviewDepositModalState.transactionError() = _TransactionError; - const factory PreviewDepositModalState.slippageCheckError() = _SlippageCheckError; + const factory PreviewDepositModalState.slippageCheckError(bool isSlippageAutomatic) = _SlippageCheckError; const factory PreviewDepositModalState.approvingToken(String symbol) = _ApprovingToken; const factory PreviewDepositModalState.depositing() = _Depositing; } diff --git a/lib/app/create/deposit/widgets/range_selector.dart b/lib/app/create/deposit/widgets/range_selector.dart index 3a60ee1..c6c8b69 100644 --- a/lib/app/create/deposit/widgets/range_selector.dart +++ b/lib/app/create/deposit/widgets/range_selector.dart @@ -1,7 +1,7 @@ import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart'; import 'package:zup_app/core/extensions/num_extension.dart'; -import 'package:zup_app/core/mixins/v3_pool_conversors_mixin.dart'; import 'package:zup_app/core/token_amount_input_formatter.dart'; import 'package:zup_app/gen/assets.gen.dart'; import 'package:zup_app/l10n/gen/app_localizations.dart'; @@ -103,7 +103,7 @@ class RangeSelector extends StatefulWidget { State createState() => _RangeSelectorState(); } -class _RangeSelectorState extends State with V3PoolConversorsMixin { +class _RangeSelectorState extends State with CLPoolConversorsMixin { final padding = 20.0; final TextEditingController controller = TextEditingController(); diff --git a/lib/core/concentrated_liquidity_utils/cl_pool_constants.dart b/lib/core/concentrated_liquidity_utils/cl_pool_constants.dart new file mode 100644 index 0000000..8ef3400 --- /dev/null +++ b/lib/core/concentrated_liquidity_utils/cl_pool_constants.dart @@ -0,0 +1,6 @@ +abstract class CLPoolConstants { + static final BigInt minTick = BigInt.from(-887272); + static final BigInt maxTick = -minTick; + static final BigInt q96 = BigInt.from(2).pow(96); + static final BigInt q32 = BigInt.from(2).pow(32); +} diff --git a/lib/core/mixins/v3_pool_conversors_mixin.dart b/lib/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart similarity index 78% rename from lib/core/mixins/v3_pool_conversors_mixin.dart rename to lib/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart index e45c6b0..bf5e6e6 100644 --- a/lib/core/mixins/v3_pool_conversors_mixin.dart +++ b/lib/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart @@ -1,8 +1,8 @@ import 'dart:math'; -import 'package:zup_app/core/v3_v4_pool_constants.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; -mixin V3PoolConversorsMixin { +mixin CLPoolConversorsMixin { ({double priceAsQuoteToken, double priceAsBaseToken}) tickToPrice({ required BigInt tick, required int poolToken0Decimals, @@ -22,11 +22,11 @@ mixin V3PoolConversorsMixin { final highestValidTickDistanceFromTick = (highestValidTick - tick).abs(); if (lowestValidTickDistanceFromTick < highestValidTickDistanceFromTick && - lowestValidTick >= V3V4PoolConstants.minTick) { + lowestValidTick >= CLPoolConstants.minTick) { return lowestValidTick; } - return highestValidTick > V3V4PoolConstants.maxTick ? lowestValidTick : highestValidTick; + return highestValidTick > CLPoolConstants.maxTick ? lowestValidTick : highestValidTick; } BigInt priceToTick({ @@ -43,12 +43,13 @@ mixin V3PoolConversorsMixin { return BigInt.from(tickForPrice); } - ({double price, BigInt priceAsTick}) priceToClosestValidPrice( - {required double price, - required int poolToken0Decimals, - required int poolToken1Decimals, - required int tickSpacing, - required bool isReversed}) { + ({double price, BigInt priceAsTick}) priceToClosestValidPrice({ + required double price, + required int poolToken0Decimals, + required int poolToken1Decimals, + required int tickSpacing, + required bool isReversed, + }) { final priceAsTick = priceToTick( price: price, poolToken0Decimals: poolToken0Decimals, @@ -56,10 +57,7 @@ mixin V3PoolConversorsMixin { isReversed: isReversed, ); - final closestValidTick = tickToClosestValidTick( - tick: priceAsTick, - tickSpacing: tickSpacing, - ); + final closestValidTick = tickToClosestValidTick(tick: priceAsTick, tickSpacing: tickSpacing); final closestValidPrice = tickToPrice( tick: closestValidTick, @@ -69,7 +67,7 @@ mixin V3PoolConversorsMixin { return ( price: isReversed ? closestValidPrice.priceAsQuoteToken : closestValidPrice.priceAsBaseToken, - priceAsTick: closestValidTick + priceAsTick: closestValidTick, ); } } diff --git a/lib/core/concentrated_liquidity_utils/cl_pool_liquidity_calculations_mixin.dart b/lib/core/concentrated_liquidity_utils/cl_pool_liquidity_calculations_mixin.dart new file mode 100644 index 0000000..3209c82 --- /dev/null +++ b/lib/core/concentrated_liquidity_utils/cl_pool_liquidity_calculations_mixin.dart @@ -0,0 +1,170 @@ +import 'dart:math'; + +import 'package:web3kit/core/ethereum_constants.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; + +mixin CLPoolLiquidityCalculationsMixin { + double calculateToken1AmountFromToken0({ + required double tokenXAmount, + required double currentPrice, + required double priceLower, + required double priceUpper, + }) { + final liquidity = + tokenXAmount * ((sqrt(currentPrice) * sqrt(priceUpper)) / (sqrt(priceUpper) - sqrt(currentPrice))); + final token1Amount = liquidity * (sqrt(currentPrice) - sqrt(priceLower)); + + return token1Amount; + } + + double calculateToken0AmountFromToken1({ + required double tokenYAmount, + required double currentPrice, + required double priceLower, + required double priceUpper, + }) { + final liquidity = tokenYAmount / (sqrt(currentPrice) - sqrt(priceLower)); + final token0Amount = + liquidity * ((sqrt(priceUpper) - sqrt(currentPrice)) / (sqrt(priceUpper) * sqrt(currentPrice))); + + return token0Amount; + } + + BigInt getLiquidityForAmount0(BigInt sqrtPriceAX96, BigInt sqrtPriceBX96, BigInt amount0) { + if (sqrtPriceAX96 > sqrtPriceBX96) { + final sqrtPriceAX96Before = sqrtPriceAX96; + sqrtPriceAX96 = sqrtPriceBX96; + sqrtPriceBX96 = sqrtPriceAX96Before; + } + + final numerator = (amount0 * sqrtPriceAX96) * sqrtPriceBX96; + final denominator = CLPoolConstants.q96 * (sqrtPriceBX96 - sqrtPriceAX96); + + return numerator ~/ denominator; + } + + BigInt getLiquidityForAmount1(BigInt sqrtPriceAX96, BigInt sqrtPriceBX96, BigInt amount1) { + if (sqrtPriceAX96 > sqrtPriceBX96) { + final sqrtPriceAX96Before = sqrtPriceAX96; + sqrtPriceAX96 = sqrtPriceBX96; + sqrtPriceBX96 = sqrtPriceAX96Before; + } + + return (amount1 * CLPoolConstants.q96) ~/ (sqrtPriceBX96 - sqrtPriceAX96); + } + + BigInt getLiquidityForAmounts( + BigInt sqrtPriceX96, + BigInt sqrtPriceAX96, + BigInt sqrtPriceBX96, + BigInt amount0, + BigInt amount1, + ) { + if (sqrtPriceAX96 > sqrtPriceBX96) { + final sqrtPriceAX96Before = sqrtPriceAX96; + sqrtPriceAX96 = sqrtPriceBX96; + sqrtPriceBX96 = sqrtPriceAX96Before; + } + + if (sqrtPriceX96 <= sqrtPriceAX96) { + return getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0); + } else if (sqrtPriceX96 < sqrtPriceBX96) { + BigInt liquidity0 = getLiquidityForAmount0(sqrtPriceX96, sqrtPriceBX96, amount0); + BigInt liquidity1 = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceX96, amount1); + + return liquidity0 < liquidity1 ? liquidity0 : liquidity1; + } else { + return getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceBX96, amount1); + } + } + + BigInt getSqrtPriceAtTick(BigInt tick) { + final absTick = tick.abs(); + + if (absTick > CLPoolConstants.maxTick) throw Exception('Tick out of range'); + + BigInt ratio = absTick & BigInt.from(0x1) != BigInt.zero + ? BigInt.parse("0xfffcb933bd6fad37aa2d162d1a594001") + : BigInt.parse("0x100000000000000000000000000000000"); + + if (absTick & BigInt.from(0x2) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xfff97272373d413259a46990580e213a")) >> 128; + } + + if (absTick & BigInt.from(0x4) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xfff2e50f5f656932ef12357cf3c7fdcc")) >> 128; + } + + if (absTick & BigInt.from(0x8) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xffe5caca7e10e4e61c3624eaa0941cd0")) >> 128; + } + + if (absTick & BigInt.from(0x10) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xffcb9843d60f6159c9db58835c926644")) >> 128; + } + + if (absTick & BigInt.from(0x20) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xff973b41fa98c081472e6896dfb254c0")) >> 128; + } + + if (absTick & BigInt.from(0x40) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xff2ea16466c96a3843ec78b326b52861")) >> 128; + } + + if (absTick & BigInt.from(0x80) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xfe5dee046a99a2a811c461f1969c3053")) >> 128; + } + + if (absTick & BigInt.from(0x100) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xfcbe86c7900a88aedcffc83b479aa3a4")) >> 128; + } + if (absTick & BigInt.from(0x200) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xf987a7253ac413176f2b074cf7815e54")) >> 128; + } + + if (absTick & BigInt.from(0x400) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xf3392b0822b70005940c7a398e4b70f3")) >> 128; + } + if (absTick & BigInt.from(0x800) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xe7159475a2c29b7443b29c7fa6e889d9")) >> 128; + } + if (absTick & BigInt.from(0x1000) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xd097f3bdfd2022b8845ad8f792aa5825")) >> 128; + } + if (absTick & BigInt.from(0x2000) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0xa9f746462d870fdf8a65dc1f90e061e5")) >> 128; + } + + if (absTick & BigInt.from(0x4000) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0x70d869a156d2a1b890bb3df62baf32f7")) >> 128; + } + + if (absTick & BigInt.from(0x8000) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0x31be135f97d08fd981231505542fcfa6")) >> 128; + } + + if (absTick & BigInt.from(0x10000) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0x9aa508b5b7a84e1c677de54f3e99bc9")) >> 128; + } + + if (absTick & BigInt.from(0x20000) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0x5d6af8dedb81196699c329225ee604")) >> 128; + } + + if (absTick & BigInt.from(0x40000) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0x2216e584f5fa1ea926041bedfe98")) >> 128; + } + + if (absTick & BigInt.from(0x80000) != BigInt.zero) { + ratio = (ratio * BigInt.parse("0x48a170391f7dc42444e8fa2")) >> 128; + } + + if (tick > BigInt.zero) ratio = EthereumConstants.uint256Max ~/ ratio; + + if (ratio.remainder(CLPoolConstants.q32) > BigInt.zero) { + return ratio ~/ CLPoolConstants.q32 + BigInt.one; + } + + return ratio ~/ CLPoolConstants.q32; + } +} diff --git a/lib/core/concentrated_liquidity_utils/cl_sqrt_price_math_mixin.dart b/lib/core/concentrated_liquidity_utils/cl_sqrt_price_math_mixin.dart new file mode 100644 index 0000000..4dc2bd6 --- /dev/null +++ b/lib/core/concentrated_liquidity_utils/cl_sqrt_price_math_mixin.dart @@ -0,0 +1,87 @@ +import 'dart:math'; + +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; +import 'package:zup_core/extensions/extensions.dart'; + +mixin CLSqrtPriceMath { + ({double token1PerToken0, double token0PerToken1}) sqrtPriceX96ToPrice({ + required BigInt sqrtPriceX96, + required int poolToken0Decimals, + required int poolToken1Decimals, + }) { + final priceSqrt = sqrtPriceX96 / CLPoolConstants.q96; + final basePrice = pow(priceSqrt, 2) / pow(10, poolToken1Decimals - poolToken0Decimals); + final quotePrice = (1 / basePrice); + + return (token1PerToken0: quotePrice, token0PerToken1: basePrice); + } + + BigInt getAmount1Delta(BigInt sqrtRatioAX96, BigInt sqrtRatioBX96, BigInt liquidity, bool roundUp) { + if (sqrtRatioAX96 > sqrtRatioBX96) { + final tmp = sqrtRatioAX96; + sqrtRatioAX96 = sqrtRatioBX96; + sqrtRatioBX96 = tmp; + } + + final numerator = sqrtRatioBX96 - sqrtRatioAX96; + + return roundUp + ? liquidity.mulDivRoundingUp(numerator, CLPoolConstants.q96) + : liquidity.mulDiv(numerator, CLPoolConstants.q96); + } + + BigInt getAmount0Delta(BigInt sqrtRatioAX96, BigInt sqrtRatioBX96, BigInt liquidity, bool roundUp) { + if (sqrtRatioAX96 > sqrtRatioBX96) { + final tmp = sqrtRatioAX96; + + sqrtRatioAX96 = sqrtRatioBX96; + sqrtRatioBX96 = tmp; + } + + const resolution = 96; + final numerator1 = liquidity << resolution; + final numerator2 = sqrtRatioBX96 - sqrtRatioAX96; + + if (sqrtRatioAX96 <= BigInt.zero) { + throw ArgumentError("sqrtRatioAX96 must be > 0"); + } + + if (roundUp) { + final mulDivUp = numerator1.mulDivRoundingUp(numerator2, sqrtRatioBX96); + return mulDivUp.divRoundingUp(sqrtRatioAX96); + } else { + final mulDivDown = numerator1.mulDiv(numerator2, sqrtRatioBX96); + return mulDivDown ~/ sqrtRatioAX96; + } + } + + ({BigInt amount0Delta, BigInt amount1Delta}) getAmountsDeltas( + BigInt sqrtPriceX96, + BigInt sqrtPriceAX96, + BigInt sqrtPriceBX96, + BigInt liquidity, + ) { + if (sqrtPriceAX96 > sqrtPriceBX96) { + final tmp = sqrtPriceAX96; + + sqrtPriceAX96 = sqrtPriceBX96; + sqrtPriceBX96 = tmp; + } + + if (sqrtPriceX96 < sqrtPriceAX96) { + final amount0Delta = getAmount0Delta(sqrtPriceAX96, sqrtPriceBX96, liquidity, true); + final amount1Delta = BigInt.zero; + + return (amount0Delta: amount0Delta, amount1Delta: amount1Delta); + } + + if (sqrtPriceX96 < sqrtPriceBX96) { + final amount0Delta = getAmount0Delta(sqrtPriceX96, sqrtPriceBX96, liquidity, true); + final amount1Delta = getAmount1Delta(sqrtPriceAX96, sqrtPriceX96, liquidity, true); + + return (amount0Delta: amount0Delta, amount1Delta: amount1Delta); + } + + return (amount0Delta: BigInt.zero, amount1Delta: getAmount1Delta(sqrtPriceAX96, sqrtPriceBX96, liquidity, true)); + } +} diff --git a/lib/core/v4_pool_constants.dart b/lib/core/concentrated_liquidity_utils/v4_pool_constants.dart similarity index 100% rename from lib/core/v4_pool_constants.dart rename to lib/core/concentrated_liquidity_utils/v4_pool_constants.dart diff --git a/lib/core/dtos/deposit_settings_dto.dart b/lib/core/dtos/deposit_settings_dto.dart index 50b0d9c..4f0d713 100644 --- a/lib/core/dtos/deposit_settings_dto.dart +++ b/lib/core/dtos/deposit_settings_dto.dart @@ -8,7 +8,7 @@ part 'deposit_settings_dto.g.dart'; sealed class DepositSettingsDto with _$DepositSettingsDto { const DepositSettingsDto._(); - static const defaultMaxSlippage = 0.5; + static const double defaultMaxSlippage = 0.0; // should be auto static const defaultDeadlineMinutes = 10; @JsonSerializable(explicitToJson: true) diff --git a/lib/core/dtos/yield_dto.dart b/lib/core/dtos/yield_dto.dart index 62627bf..3dbc2cb 100644 --- a/lib/core/dtos/yield_dto.dart +++ b/lib/core/dtos/yield_dto.dart @@ -29,6 +29,7 @@ sealed class YieldDto with _$YieldDto { @Default(0) num yield90d, @Default(PoolType.unknown) @JsonKey(unknownEnumValue: PoolType.unknown) PoolType poolType, @Default("0") String latestTick, + @Default("0") String latestSqrtPriceX96, @Default(0) num totalValueLockedUSD, @Default(EthereumConstants.zeroAddress) @JsonKey(name: "hooksAddress") String v4Hooks, @Default(EthereumConstants.zeroAddress) @JsonKey(name: "deployerAddress") String deployerAddress, diff --git a/lib/core/dtos/yields_dto.dart b/lib/core/dtos/yields_dto.dart index 6a2f2b6..c03d0b8 100644 --- a/lib/core/dtos/yields_dto.dart +++ b/lib/core/dtos/yields_dto.dart @@ -60,26 +60,27 @@ sealed class YieldsDto with _$YieldsDto { pools: [ YieldDto( latestTick: "637812562", + latestSqrtPriceX96: "5240418162556390792557189", positionManagerAddress: "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4", poolType: PoolType.v3, yield7d: 21, token0: const TokenDto( - addresses: {11155111: "0x02a3e7E0480B668bD46b42852C58363F93e3bA5C"}, - decimals: {11155111: 6}, + addresses: {1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 "}, + decimals: {1: 18}, + name: "Wrapped Ether", + symbol: "WETH", logoUrl: - "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/scroll/assets/0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4/logo.png", - name: "USDC", - symbol: "USDC", + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/scroll/assets/0x5300000000000000000000000000000000000004/logo.png", ), token1: const TokenDto( - addresses: {11155111: "0x5300000000000000000000000000000000000004"}, - decimals: {11155111: 18}, + addresses: {1: "0xdAC17F958D2ee523a2206206994597C13D831ec7"}, + decimals: {1: 6}, logoUrl: - "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/scroll/assets/0x5300000000000000000000000000000000000004/logo.png", - name: "Wrapped Ether", - symbol: "WETH", + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/scroll/assets/0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4/logo.png", + name: "USDC", + symbol: "USDC", ), - chainId: 11155111, + chainId: 1, poolAddress: "0x4040CE732c1A538A4Ac3157FDC35179D73ea76cd", tickSpacing: 10, yield24h: 1732.42, diff --git a/lib/core/extensions/bigint_extension.dart b/lib/core/extensions/bigint_extension.dart index a4cfc49..70cceac 100644 --- a/lib/core/extensions/bigint_extension.dart +++ b/lib/core/extensions/bigint_extension.dart @@ -1,6 +1,6 @@ -import 'package:zup_app/core/v3_v4_pool_constants.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; extension BigIntExtension on BigInt { - bool get isMinTick => this == V3V4PoolConstants.minTick; - bool get isMaxTick => this == V3V4PoolConstants.maxTick; + bool get isMinTick => this == CLPoolConstants.minTick; + bool get isMaxTick => this == CLPoolConstants.maxTick; } diff --git a/lib/core/mixins/keys_mixin.dart b/lib/core/mixins/keys_mixin.dart index 2c78c40..b8b99d1 100644 --- a/lib/core/mixins/keys_mixin.dart +++ b/lib/core/mixins/keys_mixin.dart @@ -1,16 +1,17 @@ import 'package:zup_app/core/enums/networks.dart'; mixin KeysMixin { - String userTokenBalanceCacheKey( - {required String userAddress, - required String tokenAddress, - required bool isNative, - required AppNetworks network}) { + String userTokenBalanceCacheKey({ + required String userAddress, + required String tokenAddress, + required bool isNative, + required AppNetworks network, + }) { return 'userTokenBalance-$userAddress-$tokenAddress-native=$isNative-${network.name}'; } - String poolTickCacheKey({required AppNetworks network, required String poolAddress}) { - return 'poolTick-$poolAddress-${network.name}'; + String poolSqrtPriceCacheKey({required AppNetworks network, required String poolAddress}) { + return 'sqrtPrice-$poolAddress-${network.name}'; } String tokenPriceCacheKey({required String tokenAddress, required AppNetworks network}) { diff --git a/lib/core/mixins/v3_pool_liquidity_calculations_mixin.dart b/lib/core/mixins/v3_pool_liquidity_calculations_mixin.dart deleted file mode 100644 index 80760ad..0000000 --- a/lib/core/mixins/v3_pool_liquidity_calculations_mixin.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'dart:math'; - -mixin V3PoolLiquidityCalculationsMixin { - double calculateToken1AmountFromToken0( - double tokenXAmount, - double currentPrice, - double priceLower, - double priceUpper, - ) { - final liquidity = - tokenXAmount * ((sqrt(currentPrice) * sqrt(priceUpper)) / (sqrt(priceUpper) - sqrt(currentPrice))); - final token1Amount = liquidity * (sqrt(currentPrice) - sqrt(priceLower)); - - return token1Amount; - } - - double calculateToken0AmountFromToken1( - double tokenYAmount, - double currentPrice, - double priceLower, - double priceUpper, - ) { - final liquidity = tokenYAmount / (sqrt(currentPrice) - sqrt(priceLower)); - final token0Amount = - liquidity * ((sqrt(priceUpper) - sqrt(currentPrice)) / (sqrt(priceUpper) * sqrt(currentPrice))); - - return token0Amount; - } -} diff --git a/lib/core/mixins/v4_pool_liquidity_calculations_mixin.dart b/lib/core/mixins/v4_pool_liquidity_calculations_mixin.dart deleted file mode 100644 index 298d5bc..0000000 --- a/lib/core/mixins/v4_pool_liquidity_calculations_mixin.dart +++ /dev/null @@ -1,98 +0,0 @@ -mixin V4PoolLiquidityCalculationsMixin { - final _q96 = BigInt.from(2).pow(96); - - BigInt getLiquidityForAmount0(BigInt sqrtPriceAX96, BigInt sqrtPriceBX96, BigInt amount0) { - if (sqrtPriceAX96 > sqrtPriceBX96) { - final sqrtPriceAX96Before = sqrtPriceAX96; - sqrtPriceAX96 = sqrtPriceBX96; - sqrtPriceBX96 = sqrtPriceAX96Before; - } - - final numerator = (amount0 * sqrtPriceAX96) * sqrtPriceBX96; - final denominator = _q96 * (sqrtPriceBX96 - sqrtPriceAX96); - - return numerator ~/ denominator; - } - - BigInt getLiquidityForAmount1(BigInt sqrtPriceAX96, BigInt sqrtPriceBX96, BigInt amount1) { - if (sqrtPriceAX96 > sqrtPriceBX96) { - final sqrtPriceAX96Before = sqrtPriceAX96; - sqrtPriceAX96 = sqrtPriceBX96; - sqrtPriceBX96 = sqrtPriceAX96Before; - } - - return (amount1 * _q96) ~/ (sqrtPriceBX96 - sqrtPriceAX96); - } - - BigInt getLiquidityForAmounts( - BigInt sqrtPriceX96, - BigInt sqrtPriceAX96, - BigInt sqrtPriceBX96, - BigInt amount0, - BigInt amount1, - ) { - if (sqrtPriceAX96 > sqrtPriceBX96) { - final sqrtPriceAX96Before = sqrtPriceAX96; - sqrtPriceAX96 = sqrtPriceBX96; - sqrtPriceBX96 = sqrtPriceAX96Before; - } - - if (sqrtPriceX96 <= sqrtPriceAX96) { - return getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0); - } else if (sqrtPriceX96 < sqrtPriceBX96) { - BigInt liquidity0 = getLiquidityForAmount0(sqrtPriceX96, sqrtPriceBX96, amount0); - BigInt liquidity1 = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceX96, amount1); - - return liquidity0 < liquidity1 ? liquidity0 : liquidity1; - } else { - return getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceBX96, amount1); - } - } - - BigInt getSqrtPriceAtTick(BigInt tick) { - const int maxTick = 887272; - final List mulConstants = [ - BigInt.parse('fff97272373d413259a46990580e213a', radix: 16), - BigInt.parse('fff2e50f5f656932ef12357cf3c7fdcc', radix: 16), - BigInt.parse('ffe5caca7e10e4e61c3624eaa0941cd0', radix: 16), - BigInt.parse('ffcb9843d60f6159c9db58835c926644', radix: 16), - BigInt.parse('ff973b41fa98c081472e6896dfb254c0', radix: 16), - BigInt.parse('ff2ea16466c96a3843ec78b326b52861', radix: 16), - BigInt.parse('fe5dee046a99a2a811c461f1969c3053', radix: 16), - BigInt.parse('fcbe86c7900a88aedcffc83b479aa3a4', radix: 16), - BigInt.parse('f987a7253ac413176f2b074cf7815e54', radix: 16), - BigInt.parse('f3392b0822b70005940c7a398e4b70f3', radix: 16), - BigInt.parse('e7159475a2c29b7443b29c7fa6e889d9', radix: 16), - BigInt.parse('d097f3bdfd2022b8845ad8f792aa5825', radix: 16), - BigInt.parse('a9f746462d870fdf8a65dc1f90e061e5', radix: 16), - BigInt.parse('70d869a156d2a1b890bb3df62baf32f7', radix: 16), - BigInt.parse('31be135f97d08fd981231505542fcfa6', radix: 16), - BigInt.parse('9aa508b5b7a84e1c677de54f3e99bc9', radix: 16), - BigInt.parse('5d6af8dedb81196699c329225ee604', radix: 16), - BigInt.parse('2216e584f5fa1ea926041bedfe98', radix: 16), - BigInt.parse('48a170391f7dc42444e8fa2', radix: 16), - ]; - - BigInt absTick = tick.isNegative ? -tick : tick; - if (absTick > BigInt.from(maxTick)) throw Exception('Tick out of range'); - - BigInt price = - (absTick.toInt() & 0x1) != 0 ? BigInt.parse('fffcb933bd6fad37aa2d162d1a594001', radix: 16) : BigInt.one << 128; - - for (int i = 0; i < mulConstants.length; i++) { - if ((absTick.toInt() & (1 << (i + 1))) != 0) { - price = (price * mulConstants[i]) >> 128; - } - } - - if (tick > BigInt.zero) { - BigInt maxUint256 = (BigInt.one << 256) - BigInt.one; - price = maxUint256 ~/ price; - } - - final remainder = price & ((BigInt.one << 32) - BigInt.one); - final sqrtPriceX96 = price >> 32; - - return remainder > BigInt.zero ? sqrtPriceX96 + BigInt.one : sqrtPriceX96; - } -} diff --git a/lib/core/pool_service.dart b/lib/core/pool_service.dart index 0c78fa8..45c8421 100644 --- a/lib/core/pool_service.dart +++ b/lib/core/pool_service.dart @@ -11,11 +11,14 @@ import 'package:zup_app/abis/uniswap_v3_pool.abi.g.dart'; import 'package:zup_app/abis/uniswap_v3_position_manager.abi.g.dart'; import 'package:zup_app/abis/uniswap_v4_position_manager.abi.g.dart'; import 'package:zup_app/abis/uniswap_v4_state_view.abi.g.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_liquidity_calculations_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_sqrt_price_math_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/v4_pool_constants.dart'; import 'package:zup_app/core/dtos/yield_dto.dart'; -import 'package:zup_app/core/mixins/v4_pool_liquidity_calculations_mixin.dart'; -import 'package:zup_app/core/v4_pool_constants.dart'; +import 'package:zup_app/core/slippage.dart'; -class PoolService with V4PoolLiquidityCalculationsMixin { +class PoolService with CLPoolLiquidityCalculationsMixin, CLPoolConversorsMixin, CLSqrtPriceMath { final UniswapV4StateView _uniswapV4StateView; final UniswapV3Pool _uniswapV3Pool; final UniswapV3PositionManager _uniswapV3PositionManager; @@ -142,12 +145,35 @@ class PoolService with V4PoolLiquidityCalculationsMixin { required BigInt amount0Desired, required BigInt amount1Desired, required Duration deadline, - required BigInt amount0Min, - required BigInt amount1Min, required String recipient, required BigInt tickLower, required BigInt tickUpper, + required Slippage slippage, }) async { + final sqrtPriceX96 = await getSqrtPriceX96(depositOnYield); + final sqrtPriceAX96 = getSqrtPriceAtTick(tickLower); + final sqrtPriceBX96 = getSqrtPriceAtTick(tickUpper); + final liquidity = getLiquidityForAmounts( + sqrtPriceX96, + sqrtPriceAX96, + sqrtPriceBX96, + amount0Desired, + amount1Desired, + ); + + BigInt amount0Min = BigInt.zero; + BigInt amount1Min = BigInt.zero; + + if (slippage.isAutomatic) { + final deltas = getAmountsDeltas(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, liquidity); + + amount0Min = Slippage.halfPercent.calculateMinTokenAmountFromSlippage(deltas.amount0Delta); + amount1Min = Slippage.halfPercent.calculateMinTokenAmountFromSlippage(deltas.amount1Delta); + } else { + amount0Min = slippage.calculateMinTokenAmountFromSlippage(amount0Desired); + amount1Min = slippage.calculateMinTokenAmountFromSlippage(amount1Desired); + } + if (depositOnYield.protocol.id.isAerodromeOrVelodromeSlipstream) { return _sendV3DepositTransactionForSlipstream( depositOnYield, @@ -241,10 +267,34 @@ class PoolService with V4PoolLiquidityCalculationsMixin { required BigInt tickUpper, required BigInt amount0toDeposit, required BigInt amount1ToDeposit, - required BigInt maxAmount0ToDeposit, - required BigInt maxAmount1ToDeposit, required String recipient, + required Slippage slippage, }) async { + final isNativeDeposit = depositOnYield.isToken0Native || depositOnYield.isToken1Native; + final sqrtPriceX96 = await getSqrtPriceX96(depositOnYield); + final sqrtPriceAX96 = getSqrtPriceAtTick(tickLower); + final sqrtPriceBX96 = getSqrtPriceAtTick(tickUpper); + final liquidity = getLiquidityForAmounts( + sqrtPriceX96, + sqrtPriceAX96, + sqrtPriceBX96, + amount0toDeposit, + amount1ToDeposit, + ); + + BigInt maxAmount0ToDeposit; + BigInt maxAmount1ToDeposit; + + if (slippage.isAutomatic) { + final deltas = getAmountsDeltas(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, liquidity); + + maxAmount0ToDeposit = Slippage.halfPercent.calculateMaxTokenAmountFromSlippage(deltas.amount0Delta); + maxAmount1ToDeposit = Slippage.halfPercent.calculateMaxTokenAmountFromSlippage(deltas.amount1Delta); + } else { + maxAmount0ToDeposit = slippage.calculateMaxTokenAmountFromSlippage(amount0toDeposit); + maxAmount1ToDeposit = slippage.calculateMaxTokenAmountFromSlippage(amount1ToDeposit); + } + if (depositOnYield.protocol.id.isPancakeSwapInfinityCL) { return _sendV4PoolDepositTransactionForPancakeSwap( depositOnYield, @@ -257,21 +307,14 @@ class PoolService with V4PoolLiquidityCalculationsMixin { maxAmount0ToDeposit: maxAmount0ToDeposit, maxAmount1ToDeposit: maxAmount1ToDeposit, recipient: recipient, + isNativeDeposit: isNativeDeposit, + sqrtPriceX96: sqrtPriceX96, + sqrtPriceAX96: sqrtPriceAX96, + sqrtPriceBX96: sqrtPriceBX96, + liquidity: liquidity, ); } - final isNativeDeposit = depositOnYield.isToken0Native || depositOnYield.isToken1Native; - final sqrtPriceX96 = await getSqrtPriceX96(depositOnYield); - final sqrtPriceAX96 = getSqrtPriceAtTick(tickLower); - final sqrtPriceBX96 = getSqrtPriceAtTick(tickUpper); - final liquidity = getLiquidityForAmounts( - sqrtPriceX96, - sqrtPriceAX96, - sqrtPriceBX96, - amount0toDeposit, - amount1ToDeposit, - ); - final actions = _ethereumAbiCoder.encodePacked( ["uint8", "uint8", if (isNativeDeposit) "uint8"], [ @@ -354,19 +397,12 @@ class PoolService with V4PoolLiquidityCalculationsMixin { required BigInt maxAmount0ToDeposit, required BigInt maxAmount1ToDeposit, required String recipient, + required bool isNativeDeposit, + required BigInt sqrtPriceX96, + required BigInt sqrtPriceAX96, + required BigInt sqrtPriceBX96, + required BigInt liquidity, }) async { - final isNativeDeposit = depositOnYield.isToken0Native || depositOnYield.isToken1Native; - final sqrtPriceX96 = await getSqrtPriceX96(depositOnYield); - final sqrtPriceAX96 = getSqrtPriceAtTick(tickLower); - final sqrtPriceBX96 = getSqrtPriceAtTick(tickUpper); - final liquidity = getLiquidityForAmounts( - sqrtPriceX96, - sqrtPriceAX96, - sqrtPriceBX96, - amount0toDeposit, - amount1ToDeposit, - ); - final actions = _ethereumAbiCoder.encodePacked( ["uint8", "uint8", "uint8"], [ diff --git a/lib/core/slippage.dart b/lib/core/slippage.dart index c1f019f..c2cca66 100644 --- a/lib/core/slippage.dart +++ b/lib/core/slippage.dart @@ -8,12 +8,14 @@ class Slippage extends Equatable { final num value; + static const Slippage automatic = Slippage._(0); static const Slippage zeroPointOnePercent = Slippage._(0.1); static const Slippage halfPercent = Slippage._(0.5); static const Slippage onePercent = Slippage._(1.0); static Slippage custom(num value) => Slippage._(value); factory Slippage.fromValue(num value) { + if (value == automatic.value) return automatic; if (value == zeroPointOnePercent.value) return zeroPointOnePercent; if (value == halfPercent.value) return halfPercent; if (value == onePercent.value) return onePercent; @@ -45,7 +47,8 @@ class Slippage extends Equatable { return amount * (BigInt.from(10000) + BigInt.from(valueBasisPoints)) ~/ BigInt.from(10000); } - bool get isCustom => this != zeroPointOnePercent && this != halfPercent && this != onePercent; + bool get isAutomatic => this == automatic; + bool get isCustom => this != zeroPointOnePercent && this != halfPercent && this != onePercent && this != automatic; int get valueBasisPoints => (value * 100).toInt(); diff --git a/lib/core/v3_v4_pool_constants.dart b/lib/core/v3_v4_pool_constants.dart deleted file mode 100644 index 9f6a3ec..0000000 --- a/lib/core/v3_v4_pool_constants.dart +++ /dev/null @@ -1,4 +0,0 @@ -abstract class V3V4PoolConstants { - static final BigInt minTick = BigInt.from(-887272); - static final BigInt maxTick = -minTick; -} diff --git a/lib/l10n/en.arb b/lib/l10n/en.arb index 645db5e..00d3829 100644 --- a/lib/l10n/en.arb +++ b/lib/l10n/en.arb @@ -380,6 +380,7 @@ "createPageSettingsDropdownMiniumLiquidityLowWarning": "Low minimum TVL can lead to misleading yields.", "appSettingsDropdownTestnetMode": "Testnet Mode", "previewDepositModalSlippageCheckErrorMessage": "Slippage Check! Please try increasing your slippage for this transaction", + "previewDepositModalAutoSlippageCheckErrorMessage": "Strong market movement! Slippage exceeded. Try again or adjust tolerance.", "createPageTitle": "New Position", "tvl": "TVL", "createPageShowMeTheMoney": "Show me the money!", diff --git a/lib/l10n/gen/app_localizations.dart b/lib/l10n/gen/app_localizations.dart index 70efcef..1be06d7 100644 --- a/lib/l10n/gen/app_localizations.dart +++ b/lib/l10n/gen/app_localizations.dart @@ -1147,6 +1147,12 @@ abstract class S { /// **'Slippage Check! Please try increasing your slippage for this transaction'** String get previewDepositModalSlippageCheckErrorMessage; + /// No description provided for @previewDepositModalAutoSlippageCheckErrorMessage. + /// + /// In en, this message translates to: + /// **'Strong market movement! Slippage exceeded. Try again or adjust tolerance.'** + String get previewDepositModalAutoSlippageCheckErrorMessage; + /// No description provided for @createPageTitle. /// /// In en, this message translates to: diff --git a/lib/l10n/gen/app_localizations_en.dart b/lib/l10n/gen/app_localizations_en.dart index 12e0b97..7f754ab 100644 --- a/lib/l10n/gen/app_localizations_en.dart +++ b/lib/l10n/gen/app_localizations_en.dart @@ -653,6 +653,10 @@ class SEn extends S { String get previewDepositModalSlippageCheckErrorMessage => 'Slippage Check! Please try increasing your slippage for this transaction'; + @override + String get previewDepositModalAutoSlippageCheckErrorMessage => + 'Strong market movement! Slippage exceeded. Try again or adjust tolerance.'; + @override String get createPageTitle => 'New Position'; diff --git a/pubspec.lock b/pubspec.lock index 209b05c..99e1a98 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1330,7 +1330,7 @@ packages: description: path: "." ref: main - resolved-ref: "09478e486c087bc87714fe7e0ab554bc34eb07a2" + resolved-ref: "91d77f97bb4581db2fbeca62aa78916c0249493c" url: "https://github.com/Zup-Protocol/zup-core.git" source: git version: "0.0.1" diff --git a/test/app/create/deposit/deposit_cubit_test.dart b/test/app/create/deposit/deposit_cubit_test.dart index 195ff3f..0e8da21 100644 --- a/test/app/create/deposit/deposit_cubit_test.dart +++ b/test/app/create/deposit/deposit_cubit_test.dart @@ -32,7 +32,7 @@ void main() { late AppCubit appCubit; late ZupAnalytics zupAnalytics; late PoolService poolService; - final poolTick = BigInt.from(31276567121); + final poolSqrtPriceX96 = BigInt.from(31276567121); setUp(() { registerFallbackValue(DepositSettingsDto.fixture()); @@ -91,13 +91,13 @@ void main() { observationCardinality: BigInt.zero, observationCardinalityNext: BigInt.zero, observationIndex: BigInt.zero, - sqrtPriceX96: BigInt.zero, - tick: poolTick, + sqrtPriceX96: poolSqrtPriceX96, + tick: BigInt.zero, unlocked: true, ), ); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => poolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => poolSqrtPriceX96); when(() => cache.getPoolSearchSettings()).thenReturn(PoolSearchSettingsDto(minLiquidityUSD: 129816)); }); @@ -105,81 +105,84 @@ void main() { await zupSingletonCache.clear(); }); - group("When calling `setup`, the cubit should register a periodic task to get the pool tick every half minute. ", () { - test("And if the selected yield is not null, it should execute the task to get the pool tick", () async { - BigInt? actualLastEmittedPoolTick; - int eventsCounter = 0; - const minutesPassed = 3; - - final selectedYield = YieldDto.fixture(); - await sut.selectYield(selectedYield); - - fakeAsync((async) { - sut.setup(); - - sut.poolTickStream.listen((event) { - actualLastEmittedPoolTick = event; - eventsCounter++; - }); - - async.elapse(const Duration(minutes: minutesPassed)); - - expect(actualLastEmittedPoolTick, poolTick); - expect(eventsCounter, minutesPassed * 2); - }); - }); - - test( - """And when the minuted passed, but the selected yield is null - it should not execute the task to get the pool tick""", - () async { - BigInt? actualLastEmittedPoolTick; + group( + "When calling `setup`, the cubit should register a periodic task to get the pool sqrtPriceX96 every half minute. ", + () { + test("And if the selected yield is not null, it should execute the task to get the pool sqrtPriceX96", () async { + BigInt? actualLastEmittedSqrtPriceX96; int eventsCounter = 0; const minutesPassed = 3; - await sut.selectYield(null); + final selectedYield = YieldDto.fixture(); + await sut.selectYield(selectedYield); fakeAsync((async) { sut.setup(); - sut.poolTickStream.listen((event) { - actualLastEmittedPoolTick = event; + sut.poolSqrtPriceX96Stream.listen((event) { + actualLastEmittedSqrtPriceX96 = event; eventsCounter++; }); async.elapse(const Duration(minutes: minutesPassed)); - expect(actualLastEmittedPoolTick, null); - expect(eventsCounter, 0); + expect(actualLastEmittedSqrtPriceX96, poolSqrtPriceX96); + expect(eventsCounter, minutesPassed * 2); }); - }, - ); + }); - test( - """If the cubit is closed, and the minuted passed, - it should not execute the task to get the pool tick - and cancel the periodic task""", - () async { - final selectedYield = YieldDto.fixture(); - await sut.selectYield(selectedYield); - int eventCount = 0; + test( + """And when the minuted passed, but the selected yield is null + it should not execute the task to get the pool sqrtPriceX96""", + () async { + BigInt? actualLastEmittedSqrtPriceX96; + int eventsCounter = 0; + const minutesPassed = 3; - fakeAsync((async) { - sut.setup(); - sut.close(); + await sut.selectYield(null); + + fakeAsync((async) { + sut.setup(); + + sut.poolSqrtPriceX96Stream.listen((event) { + actualLastEmittedSqrtPriceX96 = event; + eventsCounter++; + }); + + async.elapse(const Duration(minutes: minutesPassed)); - sut.poolTickStream.listen((_) { - eventCount++; + expect(actualLastEmittedSqrtPriceX96, null); + expect(eventsCounter, 0); }); + }, + ); - async.elapse(const Duration(minutes: 10)); + test( + """If the cubit is closed, and the minuted passed, + it should not execute the task to get the pool sqrtPriceX96 + and cancel the periodic task""", + () async { + final selectedYield = YieldDto.fixture(); + await sut.selectYield(selectedYield); + int eventCount = 0; - expect(async.periodicTimerCount, 0); - expect(eventCount, 0); - }); - }, - ); - }); + fakeAsync((async) { + sut.setup(); + sut.close(); + + sut.poolSqrtPriceX96Stream.listen((_) { + eventCount++; + }); + + async.elapse(const Duration(minutes: 10)); + + expect(async.periodicTimerCount, 0); + expect(eventCount, 0); + }); + }, + ); + }, + ); test("When calling `getBestPools` it should emit the loading state", () async { expectLater(sut.stream, emits(const DepositState.loading())); @@ -471,43 +474,43 @@ void main() { await sut.selectYield(selectedYield); }); - test("When calling `selectYield` with a non-empty yield it should get the pool tick", () async { + test("When calling `selectYield` with a non-empty yield it should get the pool sqrtPriceX96", () async { final selectedYield = YieldDto.fixture(); await sut.selectYield(selectedYield); - verify(() => poolService.getPoolTick(selectedYield)).called(1); + verify(() => poolService.getSqrtPriceX96(selectedYield)).called(1); }); - test("When calling `selectYield` but the yield is null, it should not get the pool tick", () async { + test("When calling `selectYield` but the yield is null, it should not get the pool sqrtPriceX96", () async { await sut.selectYield(null); verifyNever(() => uniswapV3PoolImpl.slot0()); }); - test("When calling `getSelectedPoolTick` it should set the latest pool tick to null", () async { - expectLater(sut.latestPoolTick, null); + test("When calling `getSelectedPoolSqrtPriceX96` it should set the latest pool sqrtPriceX96 to null", () async { + expectLater(sut.latestPoolSqrtPriceX96, null); await sut.selectYield(YieldDto.fixture()); - await sut.getSelectedPoolTick(); + await sut.getSelectedPoolSqrtPriceX96(); }); - test("When calling `getSelectedPoolTick` it should use the pool service to get it", () async { + test("When calling `getSelectedPoolSqrtPriceX96` it should use the pool service to get it", () async { final yieldDto = YieldDto.fixture(); await sut.selectYield(yieldDto); - await sut.getSelectedPoolTick(); + await sut.getSelectedPoolSqrtPriceX96(); - verify(() => poolService.getPoolTick(yieldDto)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldDto)).called(1); }); test( """" - When calling `getSelectedPoolTick` for a selected pool, + When calling `getSelectedPoolSqrtPriceX96` for a selected pool, but when the call to the contract completes, the selected pool is not the same as the one passed to the call, it shoul re-call - `getSelectedPoolTick` to get the correct pool tick""", + `getSelectedPoolSqrtPriceX96` to get the correct pool sqrtPriceX96""", () async { - final expectedYieldBTick = BigInt.from(326287637265372111); + final expectedYieldBsqrtPriceX96 = BigInt.from(326287637265372111); const yieldAPoolAddress = "0x3263782637263"; const yieldBPoolAddress = "0xPoolAddressYieldB"; @@ -515,98 +518,98 @@ void main() { final yieldA = YieldDto.fixture().copyWith(poolAddress: yieldAPoolAddress); final yieldB = YieldDto.fixture().copyWith(poolAddress: yieldBPoolAddress); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async { - when(() => poolService.getPoolTick(any())).thenAnswer((_) async { - return expectedYieldBTick; + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async { + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async { + return expectedYieldBsqrtPriceX96; }); await sut.selectYield(yieldB); - return poolTick; + return poolSqrtPriceX96; }); - await sut.selectYield(yieldA); // assuming that select yield will call `getSelectedPoolTick` + await sut.selectYield(yieldA); // assuming that select yield will call `getSelectedPoolSqrtPriceX96` verify( - () => poolService.getPoolTick(yieldB), - ).called(1); // 2 because of the check in the `getSelectedPoolTick` that will re-call, and the selection + () => poolService.getSqrtPriceX96(yieldB), + ).called(1); // 2 because of the check in the `getSelectedPoolSqrtPriceX96` that will re-call, and the selection - expect(sut.latestPoolTick, expectedYieldBTick); + expect(sut.latestPoolSqrtPriceX96, expectedYieldBsqrtPriceX96); }, ); test( - """When calling `selectYield` it should first emit the selected yield latest tick from the DTO + """When calling `selectYield` it should first emit the selected yield latest sqrtPriceX96 from the DTO (without making a contract call)""", () { - final latestTickYield = BigInt.from(27189); + final sqrtPriceX96 = BigInt.from(27189); - expectLater(sut.poolTickStream, emits(latestTickYield)); + expectLater(sut.poolSqrtPriceX96Stream, emits(sqrtPriceX96)); - sut.selectYield(YieldDto.fixture().copyWith(latestTick: latestTickYield.toString())); + sut.selectYield(YieldDto.fixture().copyWith(latestSqrtPriceX96: sqrtPriceX96.toString())); - expect(sut.latestPoolTick, latestTickYield); + expect(sut.latestPoolSqrtPriceX96, sqrtPriceX96); }, ); test( - """When calling 'getSelectedPoolTick' with `forceRefresh` true, - it should get the tick again regardless of the cached value""", + """When calling 'getSelectedPoolSqrtPriceX96' with `forceRefresh` true, + it should get the sqrtPriceX96 again regardless of the cached value""", () async { final selectedYield = YieldDto.fixture(); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => poolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => poolSqrtPriceX96); await sut.selectYield(selectedYield); - await sut.getSelectedPoolTick(forceRefresh: true); + await sut.getSelectedPoolSqrtPriceX96(forceRefresh: true); - verify(() => poolService.getPoolTick(selectedYield)).called(2); + verify(() => poolService.getSqrtPriceX96(selectedYield)).called(2); }, ); test( - """When calling 'getSelectedPoolTick' multiple times for the same - pool within a minute, it should not get the tick again from the + """When calling 'getSelectedPoolSqrtPriceX96' multiple times for the same + pool within a minute, it should not get the sqrtPriceX96 again from the contract. Instead, it should use the cached value""", () async { final selectedYield = YieldDto.fixture(); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => poolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => poolSqrtPriceX96); await sut.selectYield(selectedYield); - await sut.getSelectedPoolTick(); - await sut.getSelectedPoolTick(); - await sut.getSelectedPoolTick(); - await sut.getSelectedPoolTick(); - await sut.getSelectedPoolTick(); + await sut.getSelectedPoolSqrtPriceX96(); + await sut.getSelectedPoolSqrtPriceX96(); + await sut.getSelectedPoolSqrtPriceX96(); + await sut.getSelectedPoolSqrtPriceX96(); + await sut.getSelectedPoolSqrtPriceX96(); - verify(() => poolService.getPoolTick(selectedYield)).called(1); + verify(() => poolService.getSqrtPriceX96(selectedYield)).called(1); }, ); test( - """When calling 'getSelectedPoolTick' multiple times for different - pools in the same network, it should get the tick again for each + """When calling 'getSelectedPoolSqrtPriceX96' multiple times for different + pools in the same network, it should get the sqrtPriceX96 again for each one and emit it""", () async { final yieldA = YieldDto.fixture().copyWith(poolAddress: "0xPoolAddressYieldA"); final yieldB = YieldDto.fixture().copyWith(poolAddress: "0xPoolAddressYieldB"); final yieldC = YieldDto.fixture().copyWith(poolAddress: "0xPoolAddressYieldC"); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => poolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => poolSqrtPriceX96); - await sut.selectYield(yieldA); // assuming that select yield will call `getSelectedPoolTick` + await sut.selectYield(yieldA); // assuming that select yield will call `getSelectedPoolSqrtPriceX96` await sut.selectYield(yieldB); await sut.selectYield(yieldC); - verify(() => poolService.getPoolTick(yieldA)).called(1); - verify(() => poolService.getPoolTick(yieldB)).called(1); - verify(() => poolService.getPoolTick(yieldC)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldA)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldB)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldC)).called(1); }, ); test( - """When calling 'getSelectedPoolTick' multiple times for different - pools in other networks, it should get the tick again for each + """When calling 'getSelectedPoolSqrtPriceX96' multiple times for different + pools in other networks, it should get the sqrtPriceX96 again for each one and emit it""", () async { final yieldA = YieldDto.fixture().copyWith( @@ -622,21 +625,21 @@ void main() { chainId: AppNetworks.unichain.chainId, ); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => poolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => poolSqrtPriceX96); - await sut.selectYield(yieldA); // assuming that select yield will call `getSelectedPoolTick` + await sut.selectYield(yieldA); // assuming that select yield will call `getSelectedPoolSqrtPriceX96` await sut.selectYield(yieldB); await sut.selectYield(yieldC); - verify(() => poolService.getPoolTick(yieldA)).called(1); - verify(() => poolService.getPoolTick(yieldB)).called(1); - verify(() => poolService.getPoolTick(yieldC)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldA)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldB)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldC)).called(1); }, ); test( - """When calling 'getSelectedPoolTick' multiple times for the same - pool address but in other networks, it should get the tick again for each + """When calling 'getSelectedPoolSqrtPriceX96' multiple times for the same + pool address but in other networks, it should get the sqrtPriceX96 again for each one and emit it""", () async { const poolAddress = "0xPoolAddress"; @@ -644,27 +647,27 @@ void main() { final yieldB = YieldDto.fixture().copyWith(poolAddress: poolAddress, chainId: AppNetworks.sepolia.chainId); final yieldC = YieldDto.fixture().copyWith(poolAddress: poolAddress, chainId: AppNetworks.unichain.chainId); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => poolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => poolSqrtPriceX96); - await sut.selectYield(yieldA); // assuming that select yield will call `getSelectedPoolTick` + await sut.selectYield(yieldA); // assuming that select yield will call `getSelectedPoolSqrtPriceX96` await sut.selectYield(yieldB); await sut.selectYield(yieldC); - verify(() => poolService.getPoolTick(yieldA)).called(1); - verify(() => poolService.getPoolTick(yieldB)).called(1); - verify(() => poolService.getPoolTick(yieldC)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldA)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldB)).called(1); + verify(() => poolService.getSqrtPriceX96(yieldC)).called(1); }, ); test( - """When calling 'getSelectedPoolTick', it should use the zup singleton cache + """When calling 'getSelectedPoolSqrtPriceX96', it should use the zup singleton cache with a expiration of half a minute (-1 second to not cause race conditions)""", () async { final selectedYield = YieldDto.fixture(); zupSingletonCache = ZupSingletonCacheMock(); sut = DepositCubit(yieldRepository, zupSingletonCache, wallet, cache, appCubit, zupAnalytics, poolService); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => poolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => poolSqrtPriceX96); when(() => zupSingletonCache.clear()).thenAnswer((_) async => {}); when( () => zupSingletonCache.run( @@ -673,15 +676,15 @@ void main() { expiration: any(named: "expiration"), ignoreCache: any(named: "ignoreCache"), ), - ).thenAnswer((_) async => poolTick); + ).thenAnswer((_) async => poolSqrtPriceX96); await sut.selectYield(selectedYield); - await sut.getSelectedPoolTick(); + await sut.getSelectedPoolSqrtPriceX96(); verify( () => zupSingletonCache.run( any(), - key: "poolTick-${selectedYield.poolAddress}-${selectedYield.network.name}", + key: "sqrtPrice-${selectedYield.poolAddress}-${selectedYield.network.name}", expiration: const Duration(seconds: 30 - 1), ignoreCache: false, ), @@ -690,54 +693,54 @@ void main() { ); test( - """When calling `getSelectedPoolTick` - it should emit the pool tick got from + """When calling `getSelectedPoolSqrtPriceX96` + it should emit the pool sqrtPriceX96 got from the contract, after emitting the one from the yield call""", () async { - final newExpectedPoolTick = BigInt.from(97866745634534392); - final latestTickYield = BigInt.from(27189); + final newExpectedSqrtPriceX96 = BigInt.from(97866745634534392); + final latestsqrtPriceX96 = BigInt.from(27189); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => newExpectedPoolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => newExpectedSqrtPriceX96); - expectLater(sut.poolTickStream, emitsInOrder([latestTickYield, newExpectedPoolTick])); + expectLater(sut.poolSqrtPriceX96Stream, emitsInOrder([latestsqrtPriceX96, newExpectedSqrtPriceX96])); await sut.selectYield( - YieldDto.fixture().copyWith(latestTick: latestTickYield.toString()), - ); // assuming that select yield will call `getSelectedPoolTick` + YieldDto.fixture().copyWith(latestSqrtPriceX96: latestsqrtPriceX96.toString()), + ); // assuming that select yield will call `getSelectedPoolSqrtPriceX96` }, ); - test("When calling `getSelectedPoolTick` it should save the pool tick in the cubit", () async { - final expectedPoolTick = BigInt.from(97866745634534392); + test("When calling `getSelectedPoolSqrtPriceX96` it should save the pool sqrtPriceX96 in the cubit", () async { + final expectedPoolSqrtPriceX96 = BigInt.from(97866745634534392); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => expectedPoolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => expectedPoolSqrtPriceX96); - await sut.selectYield(YieldDto.fixture()); // assuming that select yield will call `getSelectedPoolTick` + await sut.selectYield(YieldDto.fixture()); // assuming that select yield will call `getSelectedPoolSqrtPriceX96` - expect(sut.latestPoolTick, expectedPoolTick); + expect(sut.latestPoolSqrtPriceX96, expectedPoolSqrtPriceX96); }); - test("When calling `getSelectedPoolTick` it should save the same tick as the emitted ", () async { - final newWxpectedPoolTick = BigInt.from(97866745634534392); - final yieldTick = BigInt.from(27189); + test("When calling `getSelectedPoolSqrtPriceX96` it should save the same sqrtPriceX96 as the emitted ", () async { + final newWxpectedPoolSqrtPriceX96 = BigInt.from(97866745634534392); + final yieldSqrtPriceX96 = BigInt.from(27189); - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => newWxpectedPoolTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => newWxpectedPoolSqrtPriceX96); - expectLater(sut.poolTickStream, emitsInOrder([yieldTick, newWxpectedPoolTick])); + expectLater(sut.poolSqrtPriceX96Stream, emitsInOrder([yieldSqrtPriceX96, newWxpectedPoolSqrtPriceX96])); await sut.selectYield( - YieldDto.fixture().copyWith(latestTick: yieldTick.toString()), - ); // assuming that select yield will call `getSelectedPoolTick` + YieldDto.fixture().copyWith(latestSqrtPriceX96: yieldSqrtPriceX96.toString()), + ); // assuming that select yield will call `getSelectedPoolSqrtPriceX96` - expect(sut.latestPoolTick, newWxpectedPoolTick); + expect(sut.latestPoolSqrtPriceX96, newWxpectedPoolSqrtPriceX96); }); - test("when closing the cubit, it should close the pool tick stream", () async { + test("when closing the cubit, it should close the pool sqrtPriceX96 stream", () async { await sut.selectYield(YieldDto.fixture()); await sut.close(); - expect(() async => await sut.getSelectedPoolTick(), throwsA(isA())); + expect(() async => await sut.getSelectedPoolSqrtPriceX96(), throwsA(isA())); }); test("When closing the cubit, it should close the selected yield stream", () async { diff --git a/test/app/create/deposit/deposit_page_test.dart b/test/app/create/deposit/deposit_page_test.dart index d2846bb..4b0dbc6 100644 --- a/test/app/create/deposit/deposit_page_test.dart +++ b/test/app/create/deposit/deposit_page_test.dart @@ -141,8 +141,8 @@ void main() { when(() => cache.getPoolSearchSettings()).thenReturn(PoolSearchSettingsDto.fixture()); when(() => cubit.selectedYieldStream).thenAnswer((_) => const Stream.empty()); when(() => appCubit.selectedNetwork).thenReturn(AppNetworks.sepolia); - when(() => cubit.poolTickStream).thenAnswer((_) => const Stream.empty()); - when(() => cubit.latestPoolTick).thenAnswer((_) => BigInt.from(32523672)); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => const Stream.empty()); + when(() => cubit.latestPoolSqrtPriceX96).thenAnswer((_) => BigInt.parse("79121973566864535878904")); when(() => wallet.signerStream).thenAnswer((_) => const Stream.empty()); when(() => wallet.signer).thenReturn(null); when(() => cubit.saveDepositSettings(any(), any())).thenAnswer((_) async => ()); @@ -712,7 +712,7 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(BigInt.from(174072))); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(BigInt.from(174072))); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -731,7 +731,9 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(BigInt.from(174072))); + when( + () => cubit.poolSqrtPriceX96Stream, + ).thenAnswer((_) => Stream.value(BigInt.parse("79121973566864535878904"))); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -748,13 +750,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -776,18 +778,18 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsSqrtPriceX96 = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsSqrtPriceX96)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsSqrtPriceX96); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("min-price-selector")), "1000"); + await tester.enterText(find.byKey(const Key("min-price-selector")), "1"); FocusManager.instance.primaryFocus?.unfocus(); await tester.tap(find.byKey(const Key("reverse-tokens-reversed"))); @@ -805,13 +807,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -831,13 +833,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -863,13 +865,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -891,13 +893,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -926,13 +928,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -952,13 +954,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -980,13 +982,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1010,13 +1012,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1036,13 +1038,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1063,13 +1065,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1089,13 +1091,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1116,13 +1118,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1142,13 +1144,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1168,13 +1170,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1196,13 +1198,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1227,13 +1229,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1241,7 +1243,7 @@ void main() { await tester.tap(find.byKey(const Key("50-percent-range-button"))); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("min-price-selector")), "1216"); + await tester.enterText(find.byKey(const Key("min-price-selector")), "0.96"); FocusManager.instance.primaryFocus?.unfocus(); await tester.tap(find.byKey(const Key("reverse-tokens-reversed"))); @@ -1257,13 +1259,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1286,13 +1288,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1320,13 +1322,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsSqrtPriceX96 = BigInt.parse("5239001873626858491699987"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsSqrtPriceX96)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsSqrtPriceX96); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1345,13 +1347,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1372,13 +1374,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1402,13 +1404,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1430,13 +1432,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1458,13 +1460,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1488,13 +1490,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1521,13 +1523,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1552,13 +1554,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1589,13 +1591,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1626,13 +1628,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1645,13 +1647,13 @@ void main() { await tester.tap(find.byKey(const Key("reverse-tokens-reversed"))); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("min-price-selector")), "1200"); + await tester.enterText(find.byKey(const Key("min-price-selector")), "0.5"); await tester.pumpAndSettle(); await tester.enterText(find.byKey(const Key("max-price-selector")), "0"); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("max-price-selector")), "90000"); + await tester.enterText(find.byKey(const Key("max-price-selector")), "2"); await tester.pumpAndSettle(); FocusManager.instance.primaryFocus?.unfocus(); @@ -1666,13 +1668,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1685,13 +1687,13 @@ void main() { await tester.tap(find.byKey(const Key("reverse-tokens-reversed"))); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("min-price-selector")), "1200"); + await tester.enterText(find.byKey(const Key("min-price-selector")), "0.8"); await tester.pumpAndSettle(); await tester.enterText(find.byKey(const Key("max-price-selector")), "0"); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("max-price-selector")), "90000"); + await tester.enterText(find.byKey(const Key("max-price-selector")), "2"); await tester.pumpAndSettle(); FocusManager.instance.primaryFocus?.unfocus(); @@ -1706,13 +1708,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1743,13 +1745,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1774,31 +1776,31 @@ void main() { ); zGoldenTest( - "When inputing a range,reversing the tokens, then inputing the base token amount, the quote token amount should be automatically calculated", + "When inputing a range, reversing the tokens, then inputing the base token amount, the quote token amount should be automatically calculated", goldenFileName: "deposit_page_input_range_then_reverse_tokens_then_input_base_token_amount", (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); await tester.drag(find.byKey(const Key("deposit-settings-button")), const Offset(0, -500)); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("min-price-selector")), "1200"); + await tester.enterText(find.byKey(const Key("min-price-selector")), "0.5"); await tester.pumpAndSettle(); await tester.enterText(find.byKey(const Key("max-price-selector")), "0"); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("max-price-selector")), "90000"); + await tester.enterText(find.byKey(const Key("max-price-selector")), "1.2"); await tester.pumpAndSettle(); FocusManager.instance.primaryFocus?.unfocus(); // unfocus the fields to calculate the valid price @@ -1822,26 +1824,26 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); await tester.drag(find.byKey(const Key("deposit-settings-button")), const Offset(0, -500)); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("min-price-selector")), "1200"); + await tester.enterText(find.byKey(const Key("min-price-selector")), "0.9"); await tester.pumpAndSettle(); await tester.enterText(find.byKey(const Key("max-price-selector")), "0"); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("max-price-selector")), "90000"); + await tester.enterText(find.byKey(const Key("max-price-selector")), "1.3"); await tester.pumpAndSettle(); FocusManager.instance.primaryFocus?.unfocus(); // unfocus the fields to calculate the valid price @@ -1865,13 +1867,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1900,13 +1902,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1932,13 +1934,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -1954,7 +1956,7 @@ void main() { await tester.enterText(find.byKey(const Key("max-price-selector")), "0"); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key("max-price-selector")), "3"); + await tester.enterText(find.byKey(const Key("max-price-selector")), "0.5"); await tester.pumpAndSettle(); FocusManager.instance.primaryFocus?.unfocus(); @@ -1970,13 +1972,13 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2004,15 +2006,15 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => wallet.signer).thenReturn(null); when(() => wallet.signerStream).thenAnswer((_) => Stream.value(null)); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2031,15 +2033,15 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); when(() => wallet.signer).thenReturn(null); when(() => wallet.signerStream).thenAnswer((_) => Stream.value(null)); when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder(), wrapper: GoldenConfig.localizationsWrapper()); await tester.drag(find.byKey(const Key("deposit-settings-button")), const Offset(0, -500)); @@ -2058,7 +2060,7 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); final signer = SignerMock(); when(() => wallet.signer).thenReturn(signer); @@ -2069,8 +2071,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2088,7 +2090,7 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); final signer = SignerMock(); when(() => wallet.signer).thenReturn(signer); @@ -2099,8 +2101,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2121,7 +2123,7 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); final signer = SignerMock(); when(() => wallet.signer).thenReturn(signer); @@ -2142,8 +2144,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2163,7 +2165,7 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); final signerStreamController = StreamController.broadcast(); final signer = SignerMock(); @@ -2184,8 +2186,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2208,7 +2210,7 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); final signerStreamController = StreamController.broadcast(); final signer = SignerMock(); @@ -2229,8 +2231,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2253,7 +2255,7 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); final signer = SignerMock(); @@ -2264,7 +2266,7 @@ void main() { selectedYield.token0.addresses[selectedYield.network.chainId]!, network: any(named: "network"), ), - ).thenAnswer((_) => Future.value(347537253)); + ).thenAnswer((_) => Future.value(EthereumConstants.uint256Max.toDouble())); when( () => cubit.getWalletTokenAmount( selectedYield.token1.addresses[selectedYield.network.chainId]!, @@ -2274,8 +2276,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2295,7 +2297,7 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); final signer = SignerMock(); @@ -2316,8 +2318,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2340,7 +2342,7 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); final signer = SignerMock(); @@ -2361,8 +2363,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2390,7 +2392,7 @@ void main() { (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsTick = BigInt.parse("79121973566864535878904"); final signer = SignerMock(); @@ -2412,8 +2414,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsTick)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder(await goldenBuilder(), wrapper: GoldenConfig.localizationsWrapper()); await tester.tap(find.byKey(Key("yield-card-${selectedYield.poolAddress}"))); @@ -2441,8 +2443,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => const Stream.empty()); - when(() => cubit.latestPoolTick).thenReturn(null); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => const Stream.empty()); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(null); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2466,8 +2468,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => const Stream.empty()); - when(() => cubit.latestPoolTick).thenReturn(null); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => const Stream.empty()); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(null); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2492,8 +2494,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(BigInt.from(2131))); - when(() => cubit.latestPoolTick).thenReturn(null); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(BigInt.from(2131))); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(null); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2518,8 +2520,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(BigInt.from(2131))); - when(() => cubit.latestPoolTick).thenReturn(null); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(BigInt.from(2131))); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(null); await tester.pumpDeviceBuilder(await goldenBuilder()); await tester.pumpAndSettle(); @@ -2706,7 +2708,6 @@ void main() { await tester.pumpAndSettle(); }, ); - zGoldenTest( """When selecting a slippage and a deadline in the deposit settings dropdown, and then clicking to preview the deposit, it should pass the correct slippage and deadline @@ -2717,29 +2718,21 @@ void main() { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); + final currentPriceAsSqrtPriceX96 = BigInt.parse("5240418162556390792557189"); final signer = SignerMock(); when(() => wallet.signer).thenReturn(signer); when(() => wallet.signerStream).thenAnswer((_) => Stream.value(signer)); when( - () => cubit.getWalletTokenAmount( - selectedYield.token0.addresses[selectedYield.network.chainId]!, - network: any(named: "network"), - ), - ).thenAnswer((_) => Future.value(347537253)); - when( - () => cubit.getWalletTokenAmount( - selectedYield.token1.addresses[selectedYield.network.chainId]!, - network: any(named: "network"), - ), - ).thenAnswer((_) => Future.value(32576352673)); + () => cubit.getWalletTokenAmount(any(), network: any(named: "network")), + ).thenAnswer((_) => Future.value(EthereumConstants.uint256Max.toDouble())); + when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(currentPriceAsTick)); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(currentPriceAsSqrtPriceX96)); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsSqrtPriceX96); when(() => cubit.selectYield(any())).thenAnswer((_) async => () {}); await tester.pumpDeviceBuilder(await goldenBuilder(), wrapper: GoldenConfig.localizationsWrapper()); @@ -2799,17 +2792,16 @@ void main() { verifyNever(() => appCubit.updateAppNetwork(any())); }, ); - zGoldenTest( - """When emitting a new pool tick, and the deposit amounts are already typed, + """When emitting a new pool sqrtPriceX96, and the deposit amounts are already typed, it should update the amount that have been calculated by the typed amount""", goldenFileName: "deposit_page_pool_tick_update_deposit_amount", (tester) async { await tester.runAsync(() async { final selectedYield = YieldsDto.fixture().poolsSortedBy24hYield.first; - final currentPriceAsTick = BigInt.from(174072); - final nextPriceAsTick = BigInt.from(261892); - final poolTickStreamController = StreamController.broadcast(); + final currentPriceAsSqrtPriceX96 = BigInt.parse("79121973566864535878904"); + final nextPriceAsSqrtPriceX96 = BigInt.parse("5240418162556390792557189"); + final poolSqrtPriceX96StreamController = StreamController.broadcast(); final signer = SignerMock(); @@ -2831,8 +2823,8 @@ void main() { when(() => cubit.selectedYieldStream).thenAnswer((_) => Stream.value(selectedYield)); when(() => cubit.selectedYield).thenReturn(selectedYield); when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture())); - when(() => cubit.poolTickStream).thenAnswer((_) => poolTickStreamController.stream); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => poolSqrtPriceX96StreamController.stream); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(currentPriceAsSqrtPriceX96); await tester.pumpDeviceBuilder(await goldenBuilder(), wrapper: GoldenConfig.localizationsWrapper()); await tester.tap(find.byKey(Key("yield-card-${selectedYield.poolAddress}"))); @@ -2843,8 +2835,8 @@ void main() { await tester.enterText(find.byKey(const Key("quote-token-input-card")), "1"); await tester.pumpAndSettle(); - poolTickStreamController.add(nextPriceAsTick); - when(() => cubit.latestPoolTick).thenReturn(nextPriceAsTick); + poolSqrtPriceX96StreamController.add(nextPriceAsSqrtPriceX96); + when(() => cubit.latestPoolSqrtPriceX96).thenReturn(nextPriceAsSqrtPriceX96); await tester.pumpAndSettle(); }); }, diff --git a/test/app/create/deposit/goldens/deposit_page_24h_timeframe_hover.png b/test/app/create/deposit/goldens/deposit_page_24h_timeframe_hover.png index 5db6ee3..b6a429a 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_24h_timeframe_hover.png and b/test/app/create/deposit/goldens/deposit_page_24h_timeframe_hover.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_30d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_30d_timeframe.png index e712388..6b946e2 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_30d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_30d_timeframe.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_30d_timeframe_hover.png b/test/app/create/deposit/goldens/deposit_page_30d_timeframe_hover.png index 0215aa6..e0dce60 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_30d_timeframe_hover.png and b/test/app/create/deposit/goldens/deposit_page_30d_timeframe_hover.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_5_percent_set_to_full_range.png b/test/app/create/deposit/goldens/deposit_page_5_percent_set_to_full_range.png index 3065345..88eeecc 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_5_percent_set_to_full_range.png and b/test/app/create/deposit/goldens/deposit_page_5_percent_set_to_full_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_5_percent_set_to_full_range_reverse_tokens.png b/test/app/create/deposit/goldens/deposit_page_5_percent_set_to_full_range_reverse_tokens.png index e1a4cd3..e691781 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_5_percent_set_to_full_range_reverse_tokens.png and b/test/app/create/deposit/goldens/deposit_page_5_percent_set_to_full_range_reverse_tokens.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_7d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_7d_timeframe.png index 8156917..44499e2 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_7d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_7d_timeframe.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_7d_timeframe_hover.png b/test/app/create/deposit/goldens/deposit_page_7d_timeframe_hover.png index 0f5caea..3397b33 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_7d_timeframe_hover.png and b/test/app/create/deposit/goldens/deposit_page_7d_timeframe_hover.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_90d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_90d_timeframe.png index 8f2b63d..9b9b781 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_90d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_90d_timeframe.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_90d_timeframe_back_to_24h.png b/test/app/create/deposit/goldens/deposit_page_90d_timeframe_back_to_24h.png index c92e34b..125d551 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_90d_timeframe_back_to_24h.png and b/test/app/create/deposit/goldens/deposit_page_90d_timeframe_back_to_24h.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_90d_timeframe_hover.png b/test/app/create/deposit/goldens/deposit_page_90d_timeframe_hover.png index 80b7af0..6429854 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_90d_timeframe_hover.png and b/test/app/create/deposit/goldens/deposit_page_90d_timeframe_hover.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_base_token_input_enabled_after_loading.png b/test/app/create/deposit/goldens/deposit_page_base_token_input_enabled_after_loading.png index d74cc21..88c2099 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_base_token_input_enabled_after_loading.png and b/test/app/create/deposit/goldens/deposit_page_base_token_input_enabled_after_loading.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_base_token_input_loading.png b/test/app/create/deposit/goldens/deposit_page_base_token_input_loading.png index 91a9c33..33e07cb 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_base_token_input_loading.png and b/test/app/create/deposit/goldens/deposit_page_base_token_input_loading.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_calculate_price.png b/test/app/create/deposit/goldens/deposit_page_calculate_price.png index 3065345..e6fd760 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_calculate_price.png and b/test/app/create/deposit/goldens/deposit_page_calculate_price.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_calculate_price_reversed.png b/test/app/create/deposit/goldens/deposit_page_calculate_price_reversed.png index e1a4cd3..e691781 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_calculate_price_reversed.png and b/test/app/create/deposit/goldens/deposit_page_calculate_price_reversed.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_orange.png b/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_orange.png index e904d1c..da9dd04 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_orange.png and b/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_orange.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_red.png b/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_red.png index e56b1a4..fe64f51 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_red.png and b/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_red.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_slippage_title.png b/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_slippage_title.png index 3f9d20b..6fff08a 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_slippage_title.png and b/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_slippage_title.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_zup_purple_gray.png b/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_zup_purple_gray.png index 6717491..32498a4 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_zup_purple_gray.png and b/test/app/create/deposit/goldens/deposit_page_deposit_settings_button_zup_purple_gray.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_deposit_settings_dropdown.png b/test/app/create/deposit/goldens/deposit_page_deposit_settings_dropdown.png index 002bea2..72538b0 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_deposit_settings_dropdown.png and b/test/app/create/deposit/goldens/deposit_page_deposit_settings_dropdown.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_deposit_settings_dropdown_reopening.png b/test/app/create/deposit/goldens/deposit_page_deposit_settings_dropdown_reopening.png index 8a1a88b..d19239f 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_deposit_settings_dropdown_reopening.png and b/test/app/create/deposit/goldens/deposit_page_deposit_settings_dropdown_reopening.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_enough_balance_deposit_button.png b/test/app/create/deposit/goldens/deposit_page_enough_balance_deposit_button.png index 0342f55..409a4fe 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_enough_balance_deposit_button.png and b/test/app/create/deposit/goldens/deposit_page_enough_balance_deposit_button.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount.png b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount.png index 63e98df..0c7ad01 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount.png and b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_change_range.png b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_change_range.png index 0591330..a25ccd7 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_change_range.png and b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_change_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_reverse.png b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_reverse.png index 7500213..2384cb9 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_reverse.png and b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_reverse.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_reverse_back.png b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_reverse_back.png index df92331..66543ab 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_reverse_back.png and b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_and_reverse_back.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_reverse_tokens_and_change_range.png b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_reverse_tokens_and_change_range.png index 1cab7f7..6bf1a0f 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_reverse_tokens_and_change_range.png and b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_reverse_tokens_and_change_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_reversed.png b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_reversed.png index 90578dd..b35c4b0 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_reversed.png and b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_reversed.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_then_reverse_tokens_then_set_max_price_out_of_range.png b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_then_reverse_tokens_then_set_max_price_out_of_range.png index c989741..c911e86 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_then_reverse_tokens_then_set_max_price_out_of_range.png and b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_then_reverse_tokens_then_set_max_price_out_of_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_then_set_max_price_out_of_range.png b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_then_set_max_price_out_of_range.png index cb97a1d..06409aa 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_then_set_max_price_out_of_range.png and b/test/app/create/deposit/goldens/deposit_page_input_base_token_amount_then_set_max_price_out_of_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount.png b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount.png index e63cb7a..158d6c6 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount.png and b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_change_range.png b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_change_range.png index b79d4fa..88107a3 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_change_range.png and b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_change_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_reverse.png b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_reverse.png index 5e040ae..a4e47c2 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_reverse.png and b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_reverse.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_reverse_back.png b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_reverse_back.png index 4ebf888..825ff2c 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_reverse_back.png and b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_and_reverse_back.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_reverse_tokens_and_change_range.png b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_reverse_tokens_and_change_range.png index 0fbcafd..51c63b1 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_reverse_tokens_and_change_range.png and b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_reverse_tokens_and_change_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_reversed.png b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_reversed.png index 68c7d94..e0313fe 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_reversed.png and b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_reversed.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_then_reverse_tokens_then_set_min_price_out_of_range.png b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_then_reverse_tokens_then_set_min_price_out_of_range.png index feeedf7..3229580 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_then_reverse_tokens_then_set_min_price_out_of_range.png and b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_then_reverse_tokens_then_set_min_price_out_of_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_then_set_min_price_out_of_range.png b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_then_set_min_price_out_of_range.png index 102f55d..e8d9d78 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_then_set_min_price_out_of_range.png and b/test/app/create/deposit/goldens/deposit_page_input_quote_token_amount_then_set_min_price_out_of_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_range_then_input_base_token_amount.png b/test/app/create/deposit/goldens/deposit_page_input_range_then_input_base_token_amount.png index ac06ca4..eb1171a 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_range_then_input_base_token_amount.png and b/test/app/create/deposit/goldens/deposit_page_input_range_then_input_base_token_amount.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_range_then_input_quote_token_amount.png b/test/app/create/deposit/goldens/deposit_page_input_range_then_input_quote_token_amount.png index 539703c..1977775 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_range_then_input_quote_token_amount.png and b/test/app/create/deposit/goldens/deposit_page_input_range_then_input_quote_token_amount.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_range_then_reverse_tokens_then_input_base_token_amount.png b/test/app/create/deposit/goldens/deposit_page_input_range_then_reverse_tokens_then_input_base_token_amount.png index 0fbcafd..51039ef 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_range_then_reverse_tokens_then_input_base_token_amount.png and b/test/app/create/deposit/goldens/deposit_page_input_range_then_reverse_tokens_then_input_base_token_amount.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_input_range_then_reverse_tokens_then_input_quote_token_amount.png b/test/app/create/deposit/goldens/deposit_page_input_range_then_reverse_tokens_then_input_quote_token_amount.png index 1cab7f7..94b9881 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_input_range_then_reverse_tokens_then_input_quote_token_amount.png and b/test/app/create/deposit/goldens/deposit_page_input_range_then_reverse_tokens_then_input_quote_token_amount.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_invalid_range_deposit_section.png b/test/app/create/deposit/goldens/deposit_page_invalid_range_deposit_section.png index 90aad1c..5774344 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_invalid_range_deposit_section.png and b/test/app/create/deposit/goldens/deposit_page_invalid_range_deposit_section.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_max_price_less_than_min_price.png b/test/app/create/deposit/goldens/deposit_page_max_price_less_than_min_price.png index 67bab00..98a6938 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_max_price_less_than_min_price.png and b/test/app/create/deposit/goldens/deposit_page_max_price_less_than_min_price.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_max_price_out_of_range.png b/test/app/create/deposit/goldens/deposit_page_max_price_out_of_range.png index 47dc179..7ae87eb 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_max_price_out_of_range.png and b/test/app/create/deposit/goldens/deposit_page_max_price_out_of_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_max_price_set_to_full_range.png b/test/app/create/deposit/goldens/deposit_page_max_price_set_to_full_range.png index 3065345..88eeecc 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_max_price_set_to_full_range.png and b/test/app/create/deposit/goldens/deposit_page_max_price_set_to_full_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_max_price_set_to_infinity.png b/test/app/create/deposit/goldens/deposit_page_max_price_set_to_infinity.png index d6cd8fb..3b0d6ec 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_max_price_set_to_infinity.png and b/test/app/create/deposit/goldens/deposit_page_max_price_set_to_infinity.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_max_range_out_of_range_deposit_button.png b/test/app/create/deposit/goldens/deposit_page_max_range_out_of_range_deposit_button.png index f2c599e..2fd61e9 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_max_range_out_of_range_deposit_button.png and b/test/app/create/deposit/goldens/deposit_page_max_range_out_of_range_deposit_button.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_min_and_max_price_set_to_full_range.png b/test/app/create/deposit/goldens/deposit_page_min_and_max_price_set_to_full_range.png index 3065345..88eeecc 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_min_and_max_price_set_to_full_range.png and b/test/app/create/deposit/goldens/deposit_page_min_and_max_price_set_to_full_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range.png b/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range.png index 88f4f72..ab39001 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range.png and b/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range_reversed.png b/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range_reversed.png index 4873a9c..c50ea45 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range_reversed.png and b/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range_reversed.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range_reversed_in_range.png b/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range_reversed_in_range.png index 2feb5d8..64d87ac 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range_reversed_in_range.png and b/test/app/create/deposit/goldens/deposit_page_min_price_out_of_range_reversed_in_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_min_price_set_to_full_range.png b/test/app/create/deposit/goldens/deposit_page_min_price_set_to_full_range.png index 3065345..88eeecc 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_min_price_set_to_full_range.png and b/test/app/create/deposit/goldens/deposit_page_min_price_set_to_full_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_min_range_out_of_range_deposit_button.png b/test/app/create/deposit/goldens/deposit_page_min_range_out_of_range_deposit_button.png index 9028c5a..55418c0 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_min_range_out_of_range_deposit_button.png and b/test/app/create/deposit/goldens/deposit_page_min_range_out_of_range_deposit_button.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_no_amount_deposit_button.png b/test/app/create/deposit/goldens/deposit_page_no_amount_deposit_button.png index 5c0a797..7c313a9 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_no_amount_deposit_button.png and b/test/app/create/deposit/goldens/deposit_page_no_amount_deposit_button.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_not_connected.png b/test/app/create/deposit/goldens/deposit_page_not_connected.png index 0a136d1..ba49d0b 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_not_connected.png and b/test/app/create/deposit/goldens/deposit_page_not_connected.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_not_connected_deposit_button_click.png b/test/app/create/deposit/goldens/deposit_page_not_connected_deposit_button_click.png index b865836..ab60a20 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_not_connected_deposit_button_click.png and b/test/app/create/deposit/goldens/deposit_page_not_connected_deposit_button_click.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_not_enough_base_token_balance_deposit_button.png b/test/app/create/deposit/goldens/deposit_page_not_enough_base_token_balance_deposit_button.png index 9d93c07..ca1104f 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_not_enough_base_token_balance_deposit_button.png and b/test/app/create/deposit/goldens/deposit_page_not_enough_base_token_balance_deposit_button.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_not_enough_base_token_balance_deposit_button_after_connecting.png b/test/app/create/deposit/goldens/deposit_page_not_enough_base_token_balance_deposit_button_after_connecting.png index 560dc6c..e5fa9ba 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_not_enough_base_token_balance_deposit_button_after_connecting.png and b/test/app/create/deposit/goldens/deposit_page_not_enough_base_token_balance_deposit_button_after_connecting.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_not_enough_quote_token_balance_deposit_button.png b/test/app/create/deposit/goldens/deposit_page_not_enough_quote_token_balance_deposit_button.png index 24c2583..57e99aa 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_not_enough_quote_token_balance_deposit_button.png and b/test/app/create/deposit/goldens/deposit_page_not_enough_quote_token_balance_deposit_button.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_not_enough_quote_token_balance_deposit_button_after_connecting.png b/test/app/create/deposit/goldens/deposit_page_not_enough_quote_token_balance_deposit_button_after_connecting.png index 65658d6..e1f73be 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_not_enough_quote_token_balance_deposit_button_after_connecting.png and b/test/app/create/deposit/goldens/deposit_page_not_enough_quote_token_balance_deposit_button_after_connecting.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_pool_tick_update_deposit_amount.png b/test/app/create/deposit/goldens/deposit_page_pool_tick_update_deposit_amount.png index 5987faa..26abc6c 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_pool_tick_update_deposit_amount.png and b/test/app/create/deposit/goldens/deposit_page_pool_tick_update_deposit_amount.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_preview_modal.png b/test/app/create/deposit/goldens/deposit_page_preview_modal.png index 3180b01..1771428 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_preview_modal.png and b/test/app/create/deposit/goldens/deposit_page_preview_modal.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_quote_token_input_enabled_after_loading.png b/test/app/create/deposit/goldens/deposit_page_quote_token_input_enabled_after_loading.png index b6d6931..b709f6c 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_quote_token_input_enabled_after_loading.png and b/test/app/create/deposit/goldens/deposit_page_quote_token_input_enabled_after_loading.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_quote_token_input_loading.png b/test/app/create/deposit/goldens/deposit_page_quote_token_input_loading.png index d37eff7..2c01381 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_quote_token_input_loading.png and b/test/app/create/deposit/goldens/deposit_page_quote_token_input_loading.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_range_section_mobile.png b/test/app/create/deposit/goldens/deposit_page_range_section_mobile.png index cce63c8..59a60f9 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_range_section_mobile.png and b/test/app/create/deposit/goldens/deposit_page_range_section_mobile.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_reverse_tokens.png b/test/app/create/deposit/goldens/deposit_page_reverse_tokens.png index ac9b724..e691781 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_reverse_tokens.png and b/test/app/create/deposit/goldens/deposit_page_reverse_tokens.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_reverse_tokens_back.png b/test/app/create/deposit/goldens/deposit_page_reverse_tokens_back.png index 6a2ff1d..88eeecc 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_reverse_tokens_back.png and b/test/app/create/deposit/goldens/deposit_page_reverse_tokens_back.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_select_yield_scroll.png b/test/app/create/deposit/goldens/deposit_page_select_yield_scroll.png index 63ec0d3..4a88955 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_select_yield_scroll.png and b/test/app/create/deposit/goldens/deposit_page_select_yield_scroll.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_selected_yield_stream.png b/test/app/create/deposit/goldens/deposit_page_selected_yield_stream.png index 6a2ff1d..88eeecc 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_selected_yield_stream.png and b/test/app/create/deposit/goldens/deposit_page_selected_yield_stream.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_set_20_percent_range.png b/test/app/create/deposit/goldens/deposit_page_set_20_percent_range.png index 28473aa..70ea4d8 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_set_20_percent_range.png and b/test/app/create/deposit/goldens/deposit_page_set_20_percent_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_set_20_percent_range_reverse_tokens.png b/test/app/create/deposit/goldens/deposit_page_set_20_percent_range_reverse_tokens.png index 3145513..a344389 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_set_20_percent_range_reverse_tokens.png and b/test/app/create/deposit/goldens/deposit_page_set_20_percent_range_reverse_tokens.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_set_50_percent_range.png b/test/app/create/deposit/goldens/deposit_page_set_50_percent_range.png index a3b0b49..e307eef 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_set_50_percent_range.png and b/test/app/create/deposit/goldens/deposit_page_set_50_percent_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_set_50_percent_range_reverse_tokens.png b/test/app/create/deposit/goldens/deposit_page_set_50_percent_range_reverse_tokens.png index 4651926..64f9362 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_set_50_percent_range_reverse_tokens.png and b/test/app/create/deposit/goldens/deposit_page_set_50_percent_range_reverse_tokens.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_set_5_percent_range.png b/test/app/create/deposit/goldens/deposit_page_set_5_percent_range.png index 5eae335..83aeb1c 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_set_5_percent_range.png and b/test/app/create/deposit/goldens/deposit_page_set_5_percent_range.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_set_5_percent_range_reverse_tokens.png b/test/app/create/deposit/goldens/deposit_page_set_5_percent_range_reverse_tokens.png index 69f3936..bcdb0e9 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_set_5_percent_range_reverse_tokens.png and b/test/app/create/deposit/goldens/deposit_page_set_5_percent_range_reverse_tokens.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_set_percentage_range_then_type_max_price_reverse_tokens.png b/test/app/create/deposit/goldens/deposit_page_set_percentage_range_then_type_max_price_reverse_tokens.png index eabee8d..530a2b2 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_set_percentage_range_then_type_max_price_reverse_tokens.png and b/test/app/create/deposit/goldens/deposit_page_set_percentage_range_then_type_max_price_reverse_tokens.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_set_percentage_range_then_type_min_price_reverse_tokens.png b/test/app/create/deposit/goldens/deposit_page_set_percentage_range_then_type_min_price_reverse_tokens.png index 67c1e81..6e1160d 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_set_percentage_range_then_type_min_price_reverse_tokens.png and b/test/app/create/deposit/goldens/deposit_page_set_percentage_range_then_type_min_price_reverse_tokens.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_success.png b/test/app/create/deposit/goldens/deposit_page_success.png index c92e34b..125d551 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_success.png and b/test/app/create/deposit/goldens/deposit_page_success.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_success_filtered_by_min_liquidity.png b/test/app/create/deposit/goldens/deposit_page_success_filtered_by_min_liquidity.png index 389b2eb..59401d8 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_success_filtered_by_min_liquidity.png and b/test/app/create/deposit/goldens/deposit_page_success_filtered_by_min_liquidity.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_success_filtered_by_min_liquidity_local_filter_set.png b/test/app/create/deposit/goldens/deposit_page_success_filtered_by_min_liquidity_local_filter_set.png index dcd9a29..c31f02f 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_success_filtered_by_min_liquidity_local_filter_set.png and b/test/app/create/deposit/goldens/deposit_page_success_filtered_by_min_liquidity_local_filter_set.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_success_mobile.png b/test/app/create/deposit/goldens/deposit_page_success_mobile.png index 5db84e0..409f8c0 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_success_mobile.png and b/test/app/create/deposit/goldens/deposit_page_success_mobile.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_success_not_filtered_by_min_liquidity.png b/test/app/create/deposit/goldens/deposit_page_success_not_filtered_by_min_liquidity.png index 5e5368e..2e2b13b 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_success_not_filtered_by_min_liquidity.png and b/test/app/create/deposit/goldens/deposit_page_success_not_filtered_by_min_liquidity.png differ diff --git a/test/app/create/deposit/goldens/deposit_page_timeframe_tooltip.png b/test/app/create/deposit/goldens/deposit_page_timeframe_tooltip.png index 4180e59..f05d00c 100644 Binary files a/test/app/create/deposit/goldens/deposit_page_timeframe_tooltip.png and b/test/app/create/deposit/goldens/deposit_page_timeframe_tooltip.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage.png index 85c9b79..dc2d37b 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_greater_than_50_adjust.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_greater_than_50_adjust.png index fb78b89..d0ed03a 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_greater_than_50_adjust.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_greater_than_50_adjust.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_greater_than_50_error.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_greater_than_50_error.png index 9f68740..13e5a18 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_greater_than_50_error.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_greater_than_50_error.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_lower_than_50.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_lower_than_50.png index 758179b..3688132 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_lower_than_50.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_custom_slippage_lower_than_50.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline.png index ff9ed64..9a7e2fd 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_greater_than_1200.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_greater_than_1200.png index ae253ca..698ace6 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_greater_than_1200.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_greater_than_1200.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_greater_than_1200_error.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_greater_than_1200_error.png index a9bc890..9c2cd52 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_greater_than_1200_error.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_greater_than_1200_error.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_lower_than_1200.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_lower_than_1200.png index 89b15d6..c73db58 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_lower_than_1200.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_lower_than_1200.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_not_numbers.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_not_numbers.png index 471e337..e5f1ca9 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_not_numbers.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_not_numbers.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_tooltip.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_tooltip.png index 61b35c4..64010c0 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_tooltip.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_deadline_tooltip.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_front_running_warning.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_front_running_warning.png index a9951bc..92603de 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_front_running_warning.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_front_running_warning.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_one_percent_slippage.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_one_percent_slippage.png index e9bcd55..f481d6d 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_one_percent_slippage.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_one_percent_slippage.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_clear_textfield_after_selecting_default.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_clear_textfield_after_selecting_default.png index 383ec4b..5b72e26 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_clear_textfield_after_selecting_default.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_clear_textfield_after_selecting_default.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_textfield_disallowed_characters.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_textfield_disallowed_characters.png index 1980bdc..2b873cf 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_textfield_disallowed_characters.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_textfield_disallowed_characters.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_tooltip.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_tooltip.png index ecd7200..c128f6c 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_tooltip.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_slippage_tooltip.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_zero_point_five_percent_slippage.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_zero_point_five_percent_slippage.png index 383ec4b..5b72e26 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_zero_point_five_percent_slippage.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_zero_point_five_percent_slippage.png differ diff --git a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_zero_point_one_percent_slippage.png b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_zero_point_one_percent_slippage.png index 1843752..02018fa 100644 Binary files a/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_zero_point_one_percent_slippage.png and b/test/app/create/deposit/widgets/goldens/deposit_settings_dropdown_child_zero_point_one_percent_slippage.png differ diff --git a/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_slippage_check_error_auto_slippage.png b/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_slippage_check_error_auto_slippage.png new file mode 100644 index 0000000..1fffa64 Binary files /dev/null and b/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_slippage_check_error_auto_slippage.png differ diff --git a/test/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit_test.dart b/test/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit_test.dart index b5849dc..d6028b1 100644 --- a/test/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit_test.dart +++ b/test/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit_test.dart @@ -14,6 +14,7 @@ import 'package:zup_app/abis/uniswap_permit2.abi.g.dart'; import 'package:zup_app/abis/uniswap_v3_pool.abi.g.dart'; import 'package:zup_app/abis/uniswap_v3_position_manager.abi.g.dart'; import 'package:zup_app/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; import 'package:zup_app/core/dtos/token_dto.dart'; import 'package:zup_app/core/dtos/yield_dto.dart'; import 'package:zup_app/core/enums/networks.dart'; @@ -21,7 +22,6 @@ import 'package:zup_app/core/enums/pool_type.dart'; import 'package:zup_app/core/injections.dart'; import 'package:zup_app/core/pool_service.dart'; import 'package:zup_app/core/slippage.dart'; -import 'package:zup_app/core/v3_v4_pool_constants.dart'; import 'package:zup_app/core/zup_analytics.dart'; import 'package:zup_app/widgets/zup_cached_image.dart'; @@ -30,7 +30,7 @@ import '../../../../../mocks.dart'; import '../../../../../wrappers.dart'; void main() { - final BigInt initialPoolTick = BigInt.from(21765); + final BigInt initialPoolSqrtPriceX96 = BigInt.from(21765); final YieldDto currentYield = YieldDto.fixture(); const transactionHash = "0x21"; @@ -65,7 +65,7 @@ void main() { poolService = PoolServiceMock(); sut = PreviewDepositModalCubit( - initialPoolTick: initialPoolTick, + currentPriceX96: initialPoolSqrtPriceX96, currentYield: currentYield, erc20: erc20, wallet: wallet, @@ -78,6 +78,7 @@ void main() { registerFallbackValue(const ChainInfo(hexChainId: "0x1")); registerFallbackValue(signer); + registerFallbackValue(Slippage.halfPercent); registerFallbackValue(BigInt.one); registerFallbackValue((amount: BigInt.from(1), token: "")); registerFallbackValue(YieldDto.fixture()); @@ -98,96 +99,136 @@ void main() { when( () => zupAnalytics.logDeposit( - depositedYield: any(named: "depositedYield"), - amount0Formatted: any(named: "amount0Formatted"), - amount1Formatted: any(named: "amount1Formatted"), - walletAddress: any(named: "walletAddress")), + depositedYield: any(named: "depositedYield"), + amount0Formatted: any(named: "amount0Formatted"), + amount1Formatted: any(named: "amount1Formatted"), + walletAddress: any(named: "walletAddress"), + ), ).thenAnswer((_) async {}); when(() => wallet.signer).thenReturn(signer); when(() => signer.address).thenAnswer((_) async => "0x99E3CfADCD8Feecb5DdF91f88998cFfB3145F78c"); - when(() => - uniswapV3Pool.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl"))) - .thenReturn(uniswapV3PoolImpl); - - when(() => uniswapV3PoolImpl.slot0()).thenAnswer((_) async => ( - feeProtocol: BigInt.zero, - observationCardinality: BigInt.zero, - observationCardinalityNext: BigInt.zero, - observationIndex: BigInt.zero, - sqrtPriceX96: BigInt.zero, - tick: initialPoolTick, - unlocked: true, - )); + when( + () => uniswapV3Pool.fromRpcProvider( + contractAddress: any(named: "contractAddress"), + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(uniswapV3PoolImpl); + + when(() => uniswapV3PoolImpl.slot0()).thenAnswer( + (_) async => ( + feeProtocol: BigInt.zero, + observationCardinality: BigInt.zero, + observationCardinalityNext: BigInt.zero, + observationIndex: BigInt.zero, + sqrtPriceX96: initialPoolSqrtPriceX96, + tick: BigInt.zero, + unlocked: true, + ), + ); - when(() => permit2.fromSigner(contractAddress: any(named: "contractAddress"), signer: any(named: "signer"))) - .thenReturn(permit2Impl); - when(() => permit2.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl"))) - .thenReturn(permit2Impl); + when( + () => permit2.fromSigner( + contractAddress: any(named: "contractAddress"), + signer: any(named: "signer"), + ), + ).thenReturn(permit2Impl); + when( + () => permit2.fromRpcProvider( + contractAddress: any(named: "contractAddress"), + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(permit2Impl); - when(() => erc20.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl"))) - .thenReturn(erc20Impl); + when( + () => erc20.fromRpcProvider( + contractAddress: any(named: "contractAddress"), + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(erc20Impl); - when(() => erc20.fromSigner(contractAddress: any(named: "contractAddress"), signer: any(named: "signer"))) - .thenReturn(erc20Impl); + when( + () => erc20.fromSigner( + contractAddress: any(named: "contractAddress"), + signer: any(named: "signer"), + ), + ).thenReturn(erc20Impl); - when(() => erc20Impl.allowance(owner: any(named: "owner"), spender: any(named: "spender"))) - .thenAnswer((_) async => BigInt.zero); + when( + () => erc20Impl.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).thenAnswer((_) async => BigInt.zero); - when(() => erc20Impl.approve(spender: any(named: "spender"), value: any(named: "value"))) - .thenAnswer((_) async => transactionResponse); + when( + () => erc20Impl.approve( + spender: any(named: "spender"), + value: any(named: "value"), + ), + ).thenAnswer((_) async => transactionResponse); when(() => transactionResponse.hash).thenReturn(transactionHash); - when(() => transactionResponse.waitConfirmation()).thenAnswer( - (_) async => TransactionReceipt(hash: transactionHash), - ); + when( + () => transactionResponse.waitConfirmation(), + ).thenAnswer((_) async => TransactionReceipt(hash: transactionHash)); when( () => permit2Impl.approve( - token: any(named: "token"), - spender: any(named: "spender"), - amount: any(named: "amount"), - expiration: any(named: "expiration")), + token: any(named: "token"), + spender: any(named: "spender"), + amount: any(named: "amount"), + expiration: any(named: "expiration"), + ), ).thenAnswer((_) async => transactionResponse); - when(() => permit2Impl.allowance(any(), any(), any())).thenAnswer( - (_) async => (amount: BigInt.zero, expiration: BigInt.zero, nonce: BigInt.zero), - ); + when( + () => permit2Impl.allowance(any(), any(), any()), + ).thenAnswer((_) async => (amount: BigInt.zero, expiration: BigInt.zero, nonce: BigInt.zero)); when(() => wallet.connectedNetwork).thenAnswer((_) async => currentYield.network.chainInfo); - when(() => uniswapPositionManager.fromRpcProvider( + when( + () => uniswapPositionManager.fromRpcProvider( contractAddress: any(named: "contractAddress"), - rpcUrl: any(named: "rpcUrl"))).thenReturn(uniswapPositionManagerImpl); - - when(() => uniswapPositionManager.fromSigner(contractAddress: any(named: "contractAddress"), signer: signer)) - .thenReturn(uniswapPositionManagerImpl); + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(uniswapPositionManagerImpl); when( - () => uniswapPositionManagerImpl.mint( - params: any(named: "params"), + () => uniswapPositionManager.fromSigner( + contractAddress: any(named: "contractAddress"), + signer: signer, ), + ).thenReturn(uniswapPositionManagerImpl); + + when( + () => uniswapPositionManagerImpl.mint(params: any(named: "params")), ).thenAnswer((_) async => transactionResponse); when(() => uniswapPositionManager.getMintCalldata(params: any(named: "params"))).thenReturn("0x"); - when(() => poolService.sendV3PoolDepositTransaction(any(), any(), + when( + () => poolService.sendV3PoolDepositTransaction( + any(), + any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), - tickUpper: any(named: "tickUpper"))).thenAnswer((_) async => transactionResponse); + tickUpper: any(named: "tickUpper"), + ), + ).thenAnswer((_) async => transactionResponse); }); void sutCopyWith({ bool? customDepositWithNative, - BigInt? customInitialPoolTick, + BigInt? customInitialSqrtPriceX96, UniswapV3Pool? customUniswapV3Pool, Erc20? customErc20, Wallet? customWallet, @@ -198,7 +239,7 @@ void main() { PoolService? customPoolService, }) { sut = PreviewDepositModalCubit( - initialPoolTick: customInitialPoolTick ?? initialPoolTick, + currentPriceX96: customInitialSqrtPriceX96 ?? initialPoolSqrtPriceX96, permit2: customPermit2 ?? permit2, poolService: customPoolService ?? poolService, currentYield: customYield ?? currentYield, @@ -214,69 +255,55 @@ void main() { expect(sut.state, const PreviewDepositModalState.loading()); }); - test("After instanciating the cubit, the `latestPoolTick` should be equal to the initial pool tick", () { - expect(sut.latestPoolTick, initialPoolTick); + test("After instanciating the cubit, the `latestPriceX96` should be equal to the initial pool sqrtPriceX96", () { + expect(sut.latestPriceX96, initialPoolSqrtPriceX96); }); - test( - "When calling `setup` in the cubit, it should immediately emit the initial pool tick", - () async { - expectLater(sut.poolTickStream, emits(initialPoolTick)); + test("When calling `setup` in the cubit, it should immediately emit the initial pool sqrtPriceX96", () async { + expectLater(sut.poolSqrtPriceX96Stream, emits(initialPoolSqrtPriceX96)); - await sut.setup(); - }, - ); + await sut.setup(); + }); - test( - "When calling `setup` it should setup a timer to update the pool tick every one minute", - () async { - final expectedEmittedTick = BigInt.from(963287); - int updatedTimes = 0; - BigInt latestEmittedTick = BigInt.zero; - const minutesPassed = 2; + test("When calling `setup` it should setup a timer to update the pool sqrtPriceX96 every one minute", () async { + final expectedEmittedSqrtPriceX96 = BigInt.from(963287); + int updatedTimes = 0; + BigInt latestEmittedSqrtPriceX96 = BigInt.zero; + const minutesPassed = 2; - when(() => poolService.getPoolTick(any())).thenAnswer((_) async => expectedEmittedTick); + when(() => poolService.getSqrtPriceX96(any())).thenAnswer((_) async => expectedEmittedSqrtPriceX96); - fakeAsync((async) { - sut.setup(); + fakeAsync((async) { + sut.setup(); - sut.poolTickStream.listen((tick) { - updatedTimes++; - latestEmittedTick = tick; - }); - - async.elapse(const Duration(minutes: minutesPassed)); + sut.poolSqrtPriceX96Stream.listen((sqrtPriceX96) { + updatedTimes++; + latestEmittedSqrtPriceX96 = sqrtPriceX96; }); - expect( - updatedTimes, - minutesPassed, - reason: "`poolTickStream` should be emitted $minutesPassed times", - ); - expect( - latestEmittedTick, - expectedEmittedTick, - reason: "`poolTickStream` should be emitted with the updated tick", - ); - expect( - sut.latestPoolTick, - expectedEmittedTick, - reason: "`latestPoolTick` should be updated", - ); - verify(() => poolService.getPoolTick(any())).called(2); - }, - ); + async.elapse(const Duration(minutes: minutesPassed)); + }); + + expect(updatedTimes, minutesPassed, reason: "`poolSqrtPriceX96Stream` should be emitted $minutesPassed times"); + expect( + latestEmittedSqrtPriceX96, + expectedEmittedSqrtPriceX96, + reason: "`poolSqrtPriceX96Stream` should be emitted with the updated sqrtPriceX96", + ); + expect(sut.latestPriceX96, expectedEmittedSqrtPriceX96, reason: "`latestPriceX96` should be updated"); + verify(() => poolService.getSqrtPriceX96(any())).called(2); + }); test( - """When the cubit is closed, but the timer to update the tick have been fired, - the timer should be canceled, and it should not update the tick""", + """When the cubit is closed, but the timer to update the sqrtPriceX96 have been fired, + the timer should be canceled, and it should not update the sqrtPriceX96""", () async { fakeAsync((async) { sut.setup(); async.flushMicrotasks(); sut.close(); - expectLater(sut.poolTickStream, neverEmits(anything)); + expectLater(sut.poolSqrtPriceX96Stream, neverEmits(anything)); async.elapse(const Duration(minutes: 2)); verifyNever(() => uniswapV3PoolImpl.slot0()); @@ -290,43 +317,54 @@ void main() { () async { final customYield = YieldDto.fixture().copyWith( chainId: AppNetworks.sepolia.chainId, - token0: TokenDto.fixture().copyWith(addresses: { - AppNetworks.sepolia.chainId: "Token 0 Address", - }), - token1: TokenDto.fixture().copyWith(addresses: { - AppNetworks.sepolia.chainId: "Token 1 Address", - }), + token0: TokenDto.fixture().copyWith(addresses: {AppNetworks.sepolia.chainId: "Token 0 Address"}), + token1: TokenDto.fixture().copyWith(addresses: {AppNetworks.sepolia.chainId: "Token 1 Address"}), ); sut = PreviewDepositModalCubit( - uniswapPositionManager: uniswapPositionManager, - initialPoolTick: initialPoolTick, - permit2: permit2, - poolService: poolService, - currentYield: customYield, - erc20: erc20, - wallet: wallet, - navigatorKey: GlobalKey(), - zupAnalytics: zupAnalytics); + uniswapPositionManager: uniswapPositionManager, + currentPriceX96: initialPoolSqrtPriceX96, + permit2: permit2, + poolService: poolService, + currentYield: customYield, + erc20: erc20, + wallet: wallet, + navigatorKey: GlobalKey(), + zupAnalytics: zupAnalytics, + ); final token0Contract = Erc20ImplMock(); final token1Contract = Erc20ImplMock(); final token0Allowance = BigInt.from(12345); final token1Allowance = BigInt.from(54321); - when(() => erc20.fromRpcProvider( + when( + () => erc20.fromRpcProvider( contractAddress: customYield.token0.addresses[customYield.network.chainId]!, - rpcUrl: any(named: "rpcUrl"))).thenReturn(token0Contract); + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(token0Contract); - when(() => erc20.fromRpcProvider( + when( + () => erc20.fromRpcProvider( contractAddress: customYield.token1.addresses[customYield.network.chainId]!, - rpcUrl: any(named: "rpcUrl"))).thenReturn(token1Contract); + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(token1Contract); - when(() => token0Contract.allowance(owner: any(named: "owner"), spender: any(named: "spender"))) - .thenAnswer((_) async => token0Allowance); + when( + () => token0Contract.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).thenAnswer((_) async => token0Allowance); - when(() => token1Contract.allowance(owner: any(named: "owner"), spender: any(named: "spender"))) - .thenAnswer((_) async => token1Allowance); + when( + () => token1Contract.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).thenAnswer((_) async => token1Allowance); await sut.setup(); @@ -340,15 +378,12 @@ void main() { }, ); - test( - "When calling `approveToken` it should emit the approving token state with the token symbol", - () async { - final token = TokenDto.fixture().copyWith(symbol: "TOKE SYMB"); + test("When calling `approveToken` it should emit the approving token state with the token symbol", () async { + final token = TokenDto.fixture().copyWith(symbol: "TOKE SYMB"); - expectLater(sut.stream, emits(PreviewDepositModalState.approvingToken(token.symbol))); - await sut.approveToken(token, BigInt.one); - }, - ); + expectLater(sut.stream, emits(PreviewDepositModalState.approvingToken(token.symbol))); + await sut.approveToken(token, BigInt.one); + }); test( """When calling `approveToken` and the current user connected @@ -359,21 +394,22 @@ void main() { final customYield = YieldDto.fixture().copyWith(chainId: yieldNetwork.chainId); sut = PreviewDepositModalCubit( - navigatorKey: GlobalKey(), - initialPoolTick: initialPoolTick, - permit2: permit2, - poolService: poolService, - currentYield: customYield, - erc20: erc20, - wallet: wallet, - uniswapPositionManager: uniswapPositionManager, - zupAnalytics: zupAnalytics); + navigatorKey: GlobalKey(), + currentPriceX96: initialPoolSqrtPriceX96, + permit2: permit2, + poolService: poolService, + currentYield: customYield, + erc20: erc20, + wallet: wallet, + uniswapPositionManager: uniswapPositionManager, + zupAnalytics: zupAnalytics, + ); when(() => wallet.switchOrAddNetwork(any())).thenAnswer((_) async {}); when(() => wallet.connectedNetwork).thenAnswer((_) async => AppNetworks.mainnet.chainInfo); - when(() => permit2Impl.allowance(any(), any(), any())).thenAnswer( - (_) async => (amount: BigInt.zero, expiration: BigInt.zero, nonce: BigInt.zero), - ); + when( + () => permit2Impl.allowance(any(), any(), any()), + ).thenAnswer((_) async => (amount: BigInt.zero, expiration: BigInt.zero, nonce: BigInt.zero)); await sut.approveToken(currentYield.token0, BigInt.from(32761)); @@ -390,15 +426,16 @@ void main() { final customYield = YieldDto.fixture().copyWith(chainId: yieldNetwork.chainId); sut = PreviewDepositModalCubit( - navigatorKey: GlobalKey(), - uniswapPositionManager: uniswapPositionManager, - initialPoolTick: initialPoolTick, - permit2: permit2, - poolService: poolService, - currentYield: customYield, - erc20: erc20, - wallet: wallet, - zupAnalytics: zupAnalytics); + navigatorKey: GlobalKey(), + uniswapPositionManager: uniswapPositionManager, + currentPriceX96: initialPoolSqrtPriceX96, + permit2: permit2, + poolService: poolService, + currentYield: customYield, + erc20: erc20, + wallet: wallet, + zupAnalytics: zupAnalytics, + ); when(() => wallet.switchOrAddNetwork(any())).thenAnswer((_) async {}); when(() => wallet.connectedNetwork).thenAnswer((_) async => yieldNetwork.chainInfo); @@ -416,11 +453,19 @@ void main() { final token = currentYield.token0; final tokenAmount = BigInt.from(121); - when(() => erc20.fromSigner(contractAddress: any(named: "contractAddress"), signer: any(named: "signer"))) - .thenReturn(erc20Impl); + when( + () => erc20.fromSigner( + contractAddress: any(named: "contractAddress"), + signer: any(named: "signer"), + ), + ).thenReturn(erc20Impl); - when(() => erc20Impl.approve(spender: any(named: "spender"), value: any(named: "value"))) - .thenAnswer((_) async => transactionResponse); + when( + () => erc20Impl.approve( + spender: any(named: "spender"), + value: any(named: "value"), + ), + ).thenAnswer((_) async => transactionResponse); when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async => TransactionReceipt(hash: "")); @@ -431,33 +476,37 @@ void main() { }, ); - test("""When calling `approve token`, after the transaction + test( + """When calling `approve token`, after the transaction to the contract it sent, it should emit the waiting transaction state with the transaction hash - """, () async { - bool callbackCalled = false; + """, + () async { + bool callbackCalled = false; - when(() => erc20Impl.approve(spender: any(named: "spender"), value: any(named: "value"))).thenAnswer( - (_) async { + when( + () => erc20Impl.approve( + spender: any(named: "spender"), + value: any(named: "value"), + ), + ).thenAnswer((_) async { const txId = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; when(() => transactionResponse.hash).thenReturn(txId); expectLater( sut.stream, - emits( - const PreviewDepositModalState.waitingTransaction(txId: txId, type: WaitingTransactionType.approve), - ), + emits(const PreviewDepositModalState.waitingTransaction(txId: txId, type: WaitingTransactionType.approve)), ); callbackCalled = true; return transactionResponse; - }, - ); + }); - await sut.approveToken(currentYield.token0, BigInt.two); + await sut.approveToken(currentYield.token0, BigInt.two); - // Check that the callback above in the approval is called to validate the test - expect(callbackCalled, true); - }); + // Check that the callback above in the approval is called to validate the test + expect(callbackCalled, true); + }, + ); test( """When calling `approveToken` it should wait for the transaction @@ -492,13 +541,19 @@ void main() { final token0Erc20Impl = Erc20ImplMock(); - when(() => erc20.fromRpcProvider( + when( + () => erc20.fromRpcProvider( contractAddress: currentYield.token0.addresses[currentYield.chainId]!, - rpcUrl: any(named: "rpcUrl"))).thenReturn(token0Erc20Impl); + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(token0Erc20Impl); - when(() => token0Erc20Impl.allowance(owner: any(named: "owner"), spender: any(named: "spender"))).thenAnswer( - (_) async => expectedToken0Allowance, - ); + when( + () => token0Erc20Impl.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).thenAnswer((_) async => expectedToken0Allowance); await sut.approveToken(currentYield.token0, expectedToken0Allowance); @@ -519,13 +574,19 @@ void main() { final token1Erc20Impl = Erc20ImplMock(); - when(() => erc20.fromRpcProvider( + when( + () => erc20.fromRpcProvider( contractAddress: currentYield.token1.addresses[currentYield.chainId]!, - rpcUrl: any(named: "rpcUrl"))).thenReturn(token1Erc20Impl); + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(token1Erc20Impl); - when(() => token1Erc20Impl.allowance(owner: any(named: "owner"), spender: any(named: "spender"))).thenAnswer( - (_) async => expectedToken1Allowance, - ); + when( + () => token1Erc20Impl.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).thenAnswer((_) async => expectedToken1Allowance); await sut.approveToken(currentYield.token1, expectedToken1Allowance); @@ -547,26 +608,38 @@ void main() { final token0Allowance = BigInt.from(12345); final token0Erc20Impl = Erc20ImplMock(); - when(() => erc20.fromRpcProvider( + when( + () => erc20.fromRpcProvider( contractAddress: currentYield.token0.addresses[currentYield.chainId]!, - rpcUrl: any(named: "rpcUrl"))).thenReturn(token0Erc20Impl); + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(token0Erc20Impl); - when(() => token0Erc20Impl.allowance(owner: any(named: "owner"), spender: any(named: "spender"))).thenAnswer( - (_) async => token0Allowance, - ); + when( + () => token0Erc20Impl.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).thenAnswer((_) async => token0Allowance); expectLater( - sut.stream, - emitsInOrder([ - anything, - anything, - PreviewDepositModalState.approveSuccess(txId: transactionResponse.hash, symbol: currentYield.token0.symbol), - PreviewDepositModalState.initial(token0Allowance: token0Allowance, token1Allowance: BigInt.zero), - ])); + sut.stream, + emitsInOrder([ + anything, + anything, + PreviewDepositModalState.approveSuccess(txId: transactionResponse.hash, symbol: currentYield.token0.symbol), + PreviewDepositModalState.initial(token0Allowance: token0Allowance, token1Allowance: BigInt.zero), + ]), + ); await sut.approveToken(currentYield.token0, token0Allowance); - verify(() => token0Erc20Impl.allowance(owner: any(named: "owner"), spender: any(named: "spender"))).called(1); + verify( + () => token0Erc20Impl.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).called(1); }, ); @@ -579,26 +652,38 @@ void main() { final token1Allowance = BigInt.from(12345); final token1Erc20Impl = Erc20ImplMock(); - when(() => erc20.fromRpcProvider( + when( + () => erc20.fromRpcProvider( contractAddress: currentYield.token1.addresses[currentYield.chainId]!, - rpcUrl: any(named: "rpcUrl"))).thenReturn(token1Erc20Impl); + rpcUrl: any(named: "rpcUrl"), + ), + ).thenReturn(token1Erc20Impl); - when(() => token1Erc20Impl.allowance(owner: any(named: "owner"), spender: any(named: "spender"))).thenAnswer( - (_) async => token1Allowance, - ); + when( + () => token1Erc20Impl.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).thenAnswer((_) async => token1Allowance); expectLater( - sut.stream, - emitsInOrder([ - anything, - anything, - PreviewDepositModalState.approveSuccess(txId: transactionResponse.hash, symbol: currentYield.token1.symbol), - PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: token1Allowance), - ])); + sut.stream, + emitsInOrder([ + anything, + anything, + PreviewDepositModalState.approveSuccess(txId: transactionResponse.hash, symbol: currentYield.token1.symbol), + PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: token1Allowance), + ]), + ); await sut.approveToken(currentYield.token1, token1Allowance); - verify(() => token1Erc20Impl.allowance(owner: any(named: "owner"), spender: any(named: "spender"))).called(1); + verify( + () => token1Erc20Impl.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).called(1); }, ); @@ -610,17 +695,22 @@ void main() { () async { final token1Allowance = BigInt.from(12345); - when(() => erc20Impl.allowance(owner: any(named: "owner"), spender: any(named: "spender"))) - .thenThrow("dale error"); + when( + () => erc20Impl.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).thenThrow("dale error"); expectLater( - sut.stream, - emitsInOrder([ - anything, - anything, - anything, - PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: token1Allowance), - ])); + sut.stream, + emitsInOrder([ + anything, + anything, + anything, + PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: token1Allowance), + ]), + ); await sut.approveToken(currentYield.token1, token1Allowance); }, @@ -634,17 +724,22 @@ void main() { () async { final token0Allowance = BigInt.from(439868); - when(() => erc20Impl.allowance(owner: any(named: "owner"), spender: any(named: "spender"))) - .thenThrow("dale error"); + when( + () => erc20Impl.allowance( + owner: any(named: "owner"), + spender: any(named: "spender"), + ), + ).thenThrow("dale error"); expectLater( - sut.stream, - emitsInOrder([ - anything, - anything, - anything, - PreviewDepositModalState.initial(token0Allowance: token0Allowance, token1Allowance: BigInt.zero), - ])); + sut.stream, + emitsInOrder([ + anything, + anything, + anything, + PreviewDepositModalState.initial(token0Allowance: token0Allowance, token1Allowance: BigInt.zero), + ]), + ); await sut.approveToken(currentYield.token0, token0Allowance); }, @@ -654,16 +749,16 @@ void main() { """When calling `approveToken` an error is thrown, and it's that the user rejected the action, it should emit the initial state""", () async { - when(() => erc20Impl.approve(spender: any(named: "spender"), value: any(named: "value"))).thenThrow( - UserRejectedAction(), - ); + when( + () => erc20Impl.approve( + spender: any(named: "spender"), + value: any(named: "value"), + ), + ).thenThrow(UserRejectedAction()); await sut.approveToken(currentYield.token0, BigInt.one); - expect( - sut.state, - PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: BigInt.zero), - ); + expect(sut.state, PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: BigInt.zero)); }, ); @@ -672,15 +767,21 @@ void main() { that the user rejected the action, it should emit the transaction error state, and right after the initial state""", () async { - when(() => erc20Impl.approve(spender: any(named: "spender"), value: any(named: "value"))).thenThrow(Exception()); + when( + () => erc20Impl.approve( + spender: any(named: "spender"), + value: any(named: "value"), + ), + ).thenThrow(Exception()); expectLater( - sut.stream, - emitsInOrder([ - anything, - const PreviewDepositModalState.transactionError(), - PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: BigInt.zero), - ])); + sut.stream, + emitsInOrder([ + anything, + const PreviewDepositModalState.transactionError(), + PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: BigInt.zero), + ]), + ); await sut.approveToken(currentYield.token0, BigInt.one); }, @@ -775,8 +876,7 @@ void main() { any(), amount0Desired: token0Amount, amount1Desired: token1Amount, - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), @@ -786,8 +886,8 @@ void main() { }); test( - """When calling `deposit`, the amount1Min sent to the pool service to deposit - should be the one calculated from the slippage""", + """When calling `deposit`, the slippage sent to the pool service to deposit + should be the one sent by the user""", () async { final token1Amount = BigInt.from(6721); const slippage = Slippage.halfPercent; @@ -814,8 +914,7 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: slippage.calculateMinTokenAmountFromSlippage(token1Amount), + slippage: slippage, deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), @@ -826,20 +925,18 @@ void main() { ); test( - """When calling `deposit`, the amount0Min sent to the pool service to deposit - should be the one calculated from the slippage""", + "When calling `deposit`, the recipient sent to the pool service to deposit should be the signer address", () async { - final token0Amount = BigInt.from(32421); - final slippage = Slippage.fromValue(50); + const signerAddress = "0x0000000000000000000000000000000000000231"; + when(() => signer.address).thenAnswer((_) async => signerAddress); - when(() => uniswapPositionManager.getMintCalldata(params: any(named: "params"))).thenReturn(""); sutCopyWith(customDepositWithNative: true); await sut.deposit( - token0Amount: token0Amount, + token0Amount: BigInt.one, token1Amount: BigInt.one, deadline: const Duration(minutes: 30), - slippage: slippage, + slippage: Slippage.halfPercent, minPrice: 0, maxPrice: 0, isMinPriceInfinity: true, @@ -853,10 +950,9 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: slippage.calculateMinTokenAmountFromSlippage(token0Amount), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), - recipient: any(named: "recipient"), + recipient: signerAddress, tickLower: any(named: "tickLower"), tickUpper: any(named: "tickUpper"), ), @@ -865,11 +961,9 @@ void main() { ); test( - "When calling `deposit`, the recipient sent to the pool service to deposit should be the signer address", + """When calling `deposit` the minPrice is infinity, and is not reversed, + the tick lower send to the pool service should be the min tick (adjusted for the tick spacing)""", () async { - const signerAddress = "0x0000000000000000000000000000000000000231"; - when(() => signer.address).thenAnswer((_) async => signerAddress); - sutCopyWith(customDepositWithNative: true); await sut.deposit( @@ -878,9 +972,9 @@ void main() { deadline: const Duration(minutes: 30), slippage: Slippage.halfPercent, minPrice: 0, - maxPrice: 0, + maxPrice: 3000, isMinPriceInfinity: true, - isMaxPriceInfinity: true, + isMaxPriceInfinity: false, isReversed: false, ); @@ -890,87 +984,56 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), - recipient: signerAddress, - tickLower: any(named: "tickLower"), + recipient: any(named: "recipient"), + tickLower: CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConstants.minTick, + tickSpacing: currentYield.tickSpacing, + ), tickUpper: any(named: "tickUpper"), ), ).called(1); }, ); - test("""When calling `deposit` the minPrice is infinity, and is not reversed, - the tick lower send to the pool service should be the min tick (adjusted for the tick spacing)""", () async { - sutCopyWith(customDepositWithNative: true); - - await sut.deposit( - token0Amount: BigInt.one, - token1Amount: BigInt.one, - deadline: const Duration(minutes: 30), - slippage: Slippage.halfPercent, - minPrice: 0, - maxPrice: 3000, - isMinPriceInfinity: true, - isMaxPriceInfinity: false, - isReversed: false, - ); - - verify( - () => poolService.sendV3PoolDepositTransaction( - any(), - any(), - amount0Desired: any(named: "amount0Desired"), - amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), - deadline: any(named: "deadline"), - recipient: any(named: "recipient"), - tickLower: V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3V4PoolConstants.minTick, - tickSpacing: currentYield.tickSpacing, - ), - tickUpper: any(named: "tickUpper"), - ), - ).called(1); - }); - - test("""When calling `deposit` with the maxPrice infinity, and reversed, + test( + """When calling `deposit` with the maxPrice infinity, and reversed, the tick lower sent to the pool service should be the min tick - (but adjusted for the tick spacing)""", () async { - sutCopyWith(customDepositWithNative: true); + (but adjusted for the tick spacing)""", + () async { + sutCopyWith(customDepositWithNative: true); - await sut.deposit( - token0Amount: BigInt.one, - token1Amount: BigInt.one, - deadline: const Duration(minutes: 30), - slippage: Slippage.halfPercent, - minPrice: 1200, - maxPrice: 0, - isMinPriceInfinity: false, - isMaxPriceInfinity: true, - isReversed: true, - ); + await sut.deposit( + token0Amount: BigInt.one, + token1Amount: BigInt.one, + deadline: const Duration(minutes: 30), + slippage: Slippage.halfPercent, + minPrice: 1200, + maxPrice: 0, + isMinPriceInfinity: false, + isMaxPriceInfinity: true, + isReversed: true, + ); - verify( - () => poolService.sendV3PoolDepositTransaction( - any(), - any(), - amount0Desired: any(named: "amount0Desired"), - amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), - deadline: any(named: "deadline"), - recipient: any(named: "recipient"), - tickLower: V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3V4PoolConstants.minTick, - tickSpacing: currentYield.tickSpacing, + verify( + () => poolService.sendV3PoolDepositTransaction( + any(), + any(), + amount0Desired: any(named: "amount0Desired"), + amount1Desired: any(named: "amount1Desired"), + slippage: any(named: "slippage"), + deadline: any(named: "deadline"), + recipient: any(named: "recipient"), + tickLower: CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConstants.minTick, + tickSpacing: currentYield.tickSpacing, + ), + tickUpper: any(named: "tickUpper"), ), - tickUpper: any(named: "tickUpper"), - ), - ).called(1); - }); + ).called(1); + }, + ); test( "When calling `deposit` with a min price that is not infinity, it should calculate the correct tickLower and send it to the pool service", @@ -997,12 +1060,11 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), - tickLower: V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3PoolConversorsMixinWrapper().priceToTick( + tickLower: CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConversorsMixinWrapper().priceToTick( price: minPrice, poolToken0Decimals: currentYield.token0NetworkDecimals, poolToken1Decimals: currentYield.token1NetworkDecimals, @@ -1045,12 +1107,11 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), - tickLower: V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3PoolConversorsMixinWrapper().priceToTick( + tickLower: CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConversorsMixinWrapper().priceToTick( price: maxPrice, poolToken0Decimals: currentYield.token0NetworkDecimals, poolToken1Decimals: currentYield.token1NetworkDecimals, @@ -1088,13 +1149,12 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), - tickUpper: V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3V4PoolConstants.maxTick, + tickUpper: CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConstants.maxTick, tickSpacing: currentYield.tickSpacing, ), ), @@ -1128,13 +1188,12 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), - tickUpper: V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3V4PoolConstants.maxTick, + tickUpper: CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConstants.maxTick, tickSpacing: currentYield.tickSpacing, ), ), @@ -1169,13 +1228,12 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), - tickUpper: V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3PoolConversorsMixinWrapper().priceToTick( + tickUpper: CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConversorsMixinWrapper().priceToTick( price: maxPrice, poolToken0Decimals: currentYield.token0NetworkDecimals, poolToken1Decimals: currentYield.token1NetworkDecimals, @@ -1216,13 +1274,12 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), - tickUpper: V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3PoolConversorsMixinWrapper().priceToTick( + tickUpper: CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConversorsMixinWrapper().priceToTick( price: minPrice, poolToken0Decimals: currentYield.token0NetworkDecimals, poolToken1Decimals: currentYield.token1NetworkDecimals, @@ -1248,8 +1305,7 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), @@ -1258,9 +1314,7 @@ void main() { ).thenAnswer((_) async { expectLater( sut.stream, - emits( - const PreviewDepositModalState.waitingTransaction(txId: txId, type: WaitingTransactionType.deposit), - ), + emits(const PreviewDepositModalState.waitingTransaction(txId: txId, type: WaitingTransactionType.deposit)), ); callbackCalled = true; @@ -1355,8 +1409,7 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), @@ -1396,8 +1449,7 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), @@ -1435,8 +1487,9 @@ void main() { withClock(Clock(() => date), () async { const deadline = Duration(minutes: 54); - when(() => uniswapPositionManagerImpl.multicall(data: any(named: "data"))) - .thenAnswer((_) async => transactionResponse); + when( + () => uniswapPositionManagerImpl.multicall(data: any(named: "data")), + ).thenAnswer((_) async => transactionResponse); sutCopyWith(customDepositWithNative: true); @@ -1458,8 +1511,7 @@ void main() { any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: deadline, recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), @@ -1470,187 +1522,184 @@ void main() { }, ); - group( - "Close golden tests", - () { - setUp(() { - final confettiController = ConfettiControllerMock(); + group("Close golden tests", () { + setUp(() { + final confettiController = ConfettiControllerMock(); - inject.registerFactory(() => mockZupCachedImage()); - inject.registerFactory( - () => confettiController, - instanceName: InjectInstanceNames.confettiController10s, - ); + inject.registerFactory(() => mockZupCachedImage()); + inject.registerFactory( + () => confettiController, + instanceName: InjectInstanceNames.confettiController10s, + ); - when(() => confettiController.duration).thenReturn(Duration.zero); - when(() => confettiController.play()).thenAnswer((_) async {}); - when(() => confettiController.state).thenReturn(ConfettiControllerState.stoppedAndCleared); - }); + when(() => confettiController.duration).thenReturn(Duration.zero); + when(() => confettiController.play()).thenAnswer((_) async {}); + when(() => confettiController.state).thenReturn(ConfettiControllerState.stoppedAndCleared); + }); - tearDown(() => inject.reset()); + tearDown(() => inject.reset()); - zGoldenTest( - """When the state is waiting transation from a deposit and the cubit is trying to close, + zGoldenTest( + """When the state is waiting transation from a deposit and the cubit is trying to close, it should show a snackbar about the deposit in progress""", - (tester) async { - bool tested = false; - sutCopyWith(customNavigatorKey: GoldenConfig.navigatorKey); - - await tester.pumpDeviceBuilder( - await goldenDeviceBuilder(const SizedBox()), - wrapper: GoldenConfig.localizationsWrapper(), - ); - - when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async { - try { - await tester.pumpAndSettle(); - - await sut.close(); - await screenMatchesGolden(tester, "preview_deposit_modal_cubit_close_depositing_snackbar"); - tested = true; // if it does not reach here, the test have been failed - } catch (e) { - debugPrint(e.toString()); - } - - return TransactionReceipt(hash: ""); - }); - - await sut.deposit( - deadline: const Duration(minutes: 30), - slippage: Slippage.halfPercent, - token0Amount: BigInt.one, - token1Amount: BigInt.one, - minPrice: 1200, - maxPrice: 3000.50, - isMinPriceInfinity: false, - isMaxPriceInfinity: false, - isReversed: false, - ); - - // if waitConfirmation its not called, the test will fail. As the real test is - // inside the stub of the waitConfirmation, it should change the `tested` variable - expect(tested, true); - }, - ); + (tester) async { + bool tested = false; + sutCopyWith(customNavigatorKey: GoldenConfig.navigatorKey); - zGoldenTest( - """When the state is waiting transation from a approval and the cubit is trying to close, + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder(const SizedBox()), + wrapper: GoldenConfig.localizationsWrapper(), + ); + + when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async { + try { + await tester.pumpAndSettle(); + + await sut.close(); + await screenMatchesGolden(tester, "preview_deposit_modal_cubit_close_depositing_snackbar"); + tested = true; // if it does not reach here, the test have been failed + } catch (e) { + debugPrint(e.toString()); + } + + return TransactionReceipt(hash: ""); + }); + + await sut.deposit( + deadline: const Duration(minutes: 30), + slippage: Slippage.halfPercent, + token0Amount: BigInt.one, + token1Amount: BigInt.one, + minPrice: 1200, + maxPrice: 3000.50, + isMinPriceInfinity: false, + isMaxPriceInfinity: false, + isReversed: false, + ); + + // if waitConfirmation its not called, the test will fail. As the real test is + // inside the stub of the waitConfirmation, it should change the `tested` variable + expect(tested, true); + }, + ); + + zGoldenTest( + """When the state is waiting transation from a approval and the cubit is trying to close, it should show a snackbar about the approval in progress""", - (tester) async { - bool tested = false; - sutCopyWith(customNavigatorKey: GoldenConfig.navigatorKey); - - await tester.pumpDeviceBuilder( - await goldenDeviceBuilder(const SizedBox()), - wrapper: GoldenConfig.localizationsWrapper(), - ); - - when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async { - try { - await sut.close(); - await tester.pumpAndSettle(); - - await screenMatchesGolden(tester, "preview_deposit_modal_cubit_close_approving_snackbar"); - - tested = true; // if it does not reach here, the test have been failed - } catch (e) { - debugPrint(e.toString()); - } - return TransactionReceipt(hash: ""); - }); - - await sut.approveToken(TokenDto.fixture(), BigInt.one); - - // if waitConfirmation its not called, the test will fail. As the real test is - // inside the stub of the waitConfirmation, it should change the `tested` variable - expect(tested, true); - }, - ); + (tester) async { + bool tested = false; + sutCopyWith(customNavigatorKey: GoldenConfig.navigatorKey); + + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder(const SizedBox()), + wrapper: GoldenConfig.localizationsWrapper(), + ); + + when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async { + try { + await sut.close(); + await tester.pumpAndSettle(); + + await screenMatchesGolden(tester, "preview_deposit_modal_cubit_close_approving_snackbar"); + + tested = true; // if it does not reach here, the test have been failed + } catch (e) { + debugPrint(e.toString()); + } + return TransactionReceipt(hash: ""); + }); + + await sut.approveToken(TokenDto.fixture(), BigInt.one); + + // if waitConfirmation its not called, the test will fail. As the real test is + // inside the stub of the waitConfirmation, it should change the `tested` variable + expect(tested, true); + }, + ); - zGoldenTest( - """When the state is waiting transation from a approval, the cubit is trying to close, + zGoldenTest( + """When the state is waiting transation from a approval, the cubit is trying to close, and the approve succes state is emitted, it should show a snackbar about the approval success and then close the cubit""", - goldenFileName: "preview_deposit_modal_cubit_close_approval_success_snackbar", - (tester) async { - sutCopyWith(customNavigatorKey: GoldenConfig.navigatorKey); - - await tester.pumpDeviceBuilder( - await goldenDeviceBuilder(const SizedBox()), - wrapper: GoldenConfig.localizationsWrapper(), - ); - - when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async { - try { - await sut.close(); - } catch (e) { - debugPrint(e.toString()); - } - return TransactionReceipt(hash: ""); - }); - - await sut.approveToken(TokenDto.fixture(), BigInt.one); - await tester.pumpAndSettle(); - - expect(sut.isClosed, true); - }, - ); + goldenFileName: "preview_deposit_modal_cubit_close_approval_success_snackbar", + (tester) async { + sutCopyWith(customNavigatorKey: GoldenConfig.navigatorKey); + + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder(const SizedBox()), + wrapper: GoldenConfig.localizationsWrapper(), + ); - zGoldenTest( - """When the state is waiting transation from a deposit, the cubit is trying to close, + when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async { + try { + await sut.close(); + } catch (e) { + debugPrint(e.toString()); + } + return TransactionReceipt(hash: ""); + }); + + await sut.approveToken(TokenDto.fixture(), BigInt.one); + await tester.pumpAndSettle(); + + expect(sut.isClosed, true); + }, + ); + + zGoldenTest( + """When the state is waiting transation from a deposit, the cubit is trying to close, and the deposit succes state is emitted, it should show the deposit success modal and then close the cubit""", - goldenFileName: "preview_deposit_modal_cubit_close_deposit_success_modal", - (tester) async { - sutCopyWith(customNavigatorKey: GoldenConfig.navigatorKey); - - await tester.pumpDeviceBuilder( - await goldenDeviceBuilder(const SizedBox()), - wrapper: GoldenConfig.localizationsWrapper(), - ); - - when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async { - try { - await sut.close(); - } catch (e) { - debugPrint(e.toString()); - } - return TransactionReceipt(hash: ""); - }); - - await sut.deposit( - deadline: const Duration(minutes: 30), - slippage: Slippage.halfPercent, - token0Amount: BigInt.one, - token1Amount: BigInt.one, - minPrice: 1200, - maxPrice: 3000.50, - isMinPriceInfinity: false, - isMaxPriceInfinity: false, - isReversed: false, - ); - - await tester.pumpAndSettle(); - await tester.pumpAndSettle(); - - expect(sut.isClosed, true); - }, - ); - }, - ); + goldenFileName: "preview_deposit_modal_cubit_close_deposit_success_modal", + (tester) async { + sutCopyWith(customNavigatorKey: GoldenConfig.navigatorKey); + + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder(const SizedBox()), + wrapper: GoldenConfig.localizationsWrapper(), + ); + + when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async { + try { + await sut.close(); + } catch (e) { + debugPrint(e.toString()); + } + return TransactionReceipt(hash: ""); + }); + + await sut.deposit( + deadline: const Duration(minutes: 30), + slippage: Slippage.halfPercent, + token0Amount: BigInt.one, + token1Amount: BigInt.one, + minPrice: 1200, + maxPrice: 3000.50, + isMinPriceInfinity: false, + isMaxPriceInfinity: false, + isReversed: false, + ); + + await tester.pumpAndSettle(); + await tester.pumpAndSettle(); + + expect(sut.isClosed, true); + }, + ); + }); test( """When calling `deposit` and an error with `slippage` text in its body occur while depositing, it should emit the slippage check error state and the initial state""", () async { + const slippage = Slippage.halfPercent; when( () => poolService.sendV3PoolDepositTransaction( any(), any(), amount0Desired: any(named: "amount0Desired"), amount1Desired: any(named: "amount1Desired"), - amount0Min: any(named: "amount0Min"), - amount1Min: any(named: "amount1Min"), + slippage: any(named: "slippage"), deadline: any(named: "deadline"), recipient: any(named: "recipient"), tickLower: any(named: "tickLower"), @@ -1662,14 +1711,14 @@ void main() { sut.stream, emitsInOrder([ anything, - const PreviewDepositModalState.slippageCheckError(), + PreviewDepositModalState.slippageCheckError(slippage.isAutomatic), PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: BigInt.zero), ]), ); await sut.deposit( deadline: const Duration(minutes: 30), - slippage: Slippage.halfPercent, + slippage: slippage, token0Amount: BigInt.one, token1Amount: BigInt.one, minPrice: 1200, @@ -1700,60 +1749,63 @@ void main() { isReversed: false, ); - verify(() => zupAnalytics.logDeposit( - depositedYield: currentYield, - amount0Formatted: token0amount.parseTokenAmount(decimals: currentYield.token0NetworkDecimals), - amount1Formatted: token1amount.parseTokenAmount(decimals: currentYield.token1NetworkDecimals), - walletAddress: userAddress, - )).called(1); + verify( + () => zupAnalytics.logDeposit( + depositedYield: currentYield, + amount0Formatted: token0amount.parseTokenAmount(decimals: currentYield.token0NetworkDecimals), + amount1Formatted: token1amount.parseTokenAmount(decimals: currentYield.token1NetworkDecimals), + walletAddress: userAddress, + ), + ).called(1); }, ); - test( - "When calling `deposit` and it don't succeed, it should not log the any deposit event ", - () async { - when(() => transactionResponse.waitConfirmation()).thenThrow(Exception()); + test("When calling `deposit` and it don't succeed, it should not log the any deposit event ", () async { + when(() => transactionResponse.waitConfirmation()).thenThrow(Exception()); - await sut.deposit( - deadline: const Duration(minutes: 30), - slippage: Slippage.halfPercent, - token0Amount: BigInt.one, - token1Amount: BigInt.one, - minPrice: 1200, - maxPrice: 3000.50, - isMinPriceInfinity: false, - isMaxPriceInfinity: false, - isReversed: false, - ); + await sut.deposit( + deadline: const Duration(minutes: 30), + slippage: Slippage.halfPercent, + token0Amount: BigInt.one, + token1Amount: BigInt.one, + minPrice: 1200, + maxPrice: 3000.50, + isMinPriceInfinity: false, + isMaxPriceInfinity: false, + isReversed: false, + ); - verifyNever(() => zupAnalytics.logDeposit( - depositedYield: any(named: "depositedYield"), - amount0Formatted: any(named: "amount0Formatted"), - amount1Formatted: any(named: "amount1Formatted"), - walletAddress: any(named: "walletAddress"), - )); - }, - ); + verifyNever( + () => zupAnalytics.logDeposit( + depositedYield: any(named: "depositedYield"), + amount0Formatted: any(named: "amount0Formatted"), + amount1Formatted: any(named: "amount1Formatted"), + walletAddress: any(named: "walletAddress"), + ), + ); + }); test( "When calling `approveToken` and the pool type is v4, it should approve the permit2 contract as well ", () async { - when(() => permit2Impl.allowance(any(), any(), any())) - .thenAnswer((_) async => (amount: BigInt.zero, expiration: BigInt.zero, nonce: BigInt.zero)); + when( + () => permit2Impl.allowance(any(), any(), any()), + ).thenAnswer((_) async => (amount: BigInt.zero, expiration: BigInt.zero, nonce: BigInt.zero)); when( () => permit2Impl.approve( - token: any(named: "token"), - spender: any(named: "spender"), - amount: any(named: "amount"), - expiration: any(named: "expiration")), + token: any(named: "token"), + spender: any(named: "spender"), + amount: any(named: "amount"), + expiration: any(named: "expiration"), + ), ).thenAnswer((_) async => transactionResponse); const permit2Address = "0x1234"; final currentYield0 = currentYield.copyWith(poolType: PoolType.v4, permit2: permit2Address); sut = PreviewDepositModalCubit( - initialPoolTick: initialPoolTick, + currentPriceX96: initialPoolSqrtPriceX96, poolService: poolService, currentYield: currentYield0, erc20: erc20, @@ -1785,23 +1837,24 @@ void main() { () async { final allowedAmount = BigInt.from(1275); - when(() => permit2Impl.allowance(any(), any(), any())).thenAnswer( - (_) async => (amount: allowedAmount, expiration: EthereumConstants.uint48Max, nonce: BigInt.zero), - ); + when( + () => permit2Impl.allowance(any(), any(), any()), + ).thenAnswer((_) async => (amount: allowedAmount, expiration: EthereumConstants.uint48Max, nonce: BigInt.zero)); when( () => permit2Impl.approve( - token: any(named: "token"), - spender: any(named: "spender"), - amount: any(named: "amount"), - expiration: any(named: "expiration")), + token: any(named: "token"), + spender: any(named: "spender"), + amount: any(named: "amount"), + expiration: any(named: "expiration"), + ), ).thenAnswer((_) async => transactionResponse); const permit2Address = "0x1234"; final currentYield0 = currentYield.copyWith(poolType: PoolType.v4, permit2: permit2Address); sut = PreviewDepositModalCubit( - initialPoolTick: initialPoolTick, + currentPriceX96: initialPoolSqrtPriceX96, poolService: poolService, currentYield: currentYield0, erc20: erc20, @@ -1838,23 +1891,24 @@ void main() { (_) async => ( amount: allowedAmount, expiration: BigInt.from((DateTime.now().millisecondsSinceEpoch / 1000) - 1), - nonce: BigInt.zero + nonce: BigInt.zero, ), ); when( () => permit2Impl.approve( - token: any(named: "token"), - spender: any(named: "spender"), - amount: any(named: "amount"), - expiration: any(named: "expiration")), + token: any(named: "token"), + spender: any(named: "spender"), + amount: any(named: "amount"), + expiration: any(named: "expiration"), + ), ).thenAnswer((_) async => transactionResponse); const permit2Address = "0x1234"; final currentYield0 = currentYield.copyWith(poolType: PoolType.v4, permit2: permit2Address); sut = PreviewDepositModalCubit( - initialPoolTick: initialPoolTick, + currentPriceX96: initialPoolSqrtPriceX96, poolService: poolService, currentYield: currentYield0, erc20: erc20, @@ -1886,12 +1940,12 @@ void main() { () async { const permit2Address = "0x1234"; final currentYield0 = currentYield.copyWith(poolType: PoolType.v4, permit2: permit2Address); - when(() => permit2Impl.allowance(any(), any(), any())).thenAnswer( - (_) async => (amount: BigInt.zero, expiration: BigInt.zero, nonce: BigInt.zero), - ); + when( + () => permit2Impl.allowance(any(), any(), any()), + ).thenAnswer((_) async => (amount: BigInt.zero, expiration: BigInt.zero, nonce: BigInt.zero)); sut = PreviewDepositModalCubit( - initialPoolTick: initialPoolTick, + currentPriceX96: initialPoolSqrtPriceX96, poolService: poolService, currentYield: currentYield0, erc20: erc20, @@ -1907,85 +1961,79 @@ void main() { await sut.approveToken(token, value); - verify( - () => erc20Impl.approve( - spender: permit2Address, - value: value, - ), - ).called(1); + verify(() => erc20Impl.approve(spender: permit2Address, value: value)).called(1); }, ); test( - "when calling `deposit` and the pool type is v4, it should call the pool service to deposit on v4 with the correct parameters", - () async { - final currentYield0 = currentYield.copyWith( - poolType: PoolType.v4, - permit2: "0x1234", - ); - final token0Amount = BigInt.one; - final token1Amount = BigInt.two; - const minPrice = 1200.43; - const maxPrice = 4000.12; - const isMinPriceInfinity = false; - const isMaxPriceInfinity = false; - const isReversed = false; - final slippage = Slippage.fromValue(32); - const deadline = Duration(minutes: 30); - final recipient = await signer.address; - final tickLower = V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3PoolConversorsMixinWrapper().priceToTick( + "when calling `deposit` and the pool type is v4, it should call the pool service to deposit on v4 with the correct parameters", + () async { + final currentYield0 = currentYield.copyWith(poolType: PoolType.v4, permit2: "0x1234"); + final token0Amount = BigInt.one; + final token1Amount = BigInt.two; + const minPrice = 1200.43; + const maxPrice = 4000.12; + const isMinPriceInfinity = false; + const isMaxPriceInfinity = false; + const isReversed = false; + final slippage = Slippage.fromValue(32); + const deadline = Duration(minutes: 30); + final recipient = await signer.address; + final tickLower = CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConversorsMixinWrapper().priceToTick( price: minPrice, poolToken0Decimals: currentYield0.token0NetworkDecimals, poolToken1Decimals: currentYield0.token1NetworkDecimals, ), - tickSpacing: currentYield0.tickSpacing); + tickSpacing: currentYield0.tickSpacing, + ); - final tickUpper = V3PoolConversorsMixinWrapper().tickToClosestValidTick( - tick: V3PoolConversorsMixinWrapper().priceToTick( + final tickUpper = CLPoolConversorsMixinWrapper().tickToClosestValidTick( + tick: CLPoolConversorsMixinWrapper().priceToTick( price: maxPrice, poolToken0Decimals: currentYield0.token0NetworkDecimals, poolToken1Decimals: currentYield0.token1NetworkDecimals, ), - tickSpacing: currentYield0.tickSpacing); - - sut = PreviewDepositModalCubit( - initialPoolTick: initialPoolTick, - poolService: poolService, - currentYield: currentYield0, - erc20: erc20, - wallet: wallet, - uniswapPositionManager: uniswapPositionManager, - permit2: permit2, - navigatorKey: GlobalKey(), - zupAnalytics: zupAnalytics, - ); + tickSpacing: currentYield0.tickSpacing, + ); - await sut.deposit( - token0Amount: token0Amount, - token1Amount: token1Amount, - minPrice: minPrice, - maxPrice: maxPrice, - isMinPriceInfinity: isMinPriceInfinity, - isMaxPriceInfinity: isMaxPriceInfinity, - isReversed: isReversed, - slippage: slippage, - deadline: deadline, - ); + sut = PreviewDepositModalCubit( + currentPriceX96: initialPoolSqrtPriceX96, + poolService: poolService, + currentYield: currentYield0, + erc20: erc20, + wallet: wallet, + uniswapPositionManager: uniswapPositionManager, + permit2: permit2, + navigatorKey: GlobalKey(), + zupAnalytics: zupAnalytics, + ); - verify( - () => poolService.sendV4PoolDepositTransaction( - currentYield0, - signer, - amount0toDeposit: token0Amount, - amount1ToDeposit: token1Amount, - maxAmount0ToDeposit: slippage.calculateMaxTokenAmountFromSlippage(token0Amount), - maxAmount1ToDeposit: slippage.calculateMaxTokenAmountFromSlippage(token1Amount), + await sut.deposit( + token0Amount: token0Amount, + token1Amount: token1Amount, + minPrice: minPrice, + maxPrice: maxPrice, + isMinPriceInfinity: isMinPriceInfinity, + isMaxPriceInfinity: isMaxPriceInfinity, + isReversed: isReversed, + slippage: slippage, deadline: deadline, - tickLower: tickLower, - tickUpper: tickUpper, - recipient: recipient, - ), - ).called(1); - }); + ); + + verify( + () => poolService.sendV4PoolDepositTransaction( + currentYield0, + signer, + amount0toDeposit: token0Amount, + amount1ToDeposit: token1Amount, + slippage: slippage, + deadline: deadline, + tickLower: tickLower, + tickUpper: tickUpper, + recipient: recipient, + ), + ).called(1); + }, + ); } diff --git a/test/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_test.dart b/test/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_test.dart index ad0f7e3..fa93977 100644 --- a/test/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_test.dart +++ b/test/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_test.dart @@ -14,6 +14,7 @@ import 'package:zup_app/abis/uniswap_v3_pool.abi.g.dart'; import 'package:zup_app/abis/uniswap_v3_position_manager.abi.g.dart'; import 'package:zup_app/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart'; import 'package:zup_app/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; import 'package:zup_app/core/dtos/token_dto.dart'; import 'package:zup_app/core/dtos/yield_dto.dart'; import 'package:zup_app/core/enums/networks.dart'; @@ -21,7 +22,6 @@ import 'package:zup_app/core/enums/yield_timeframe.dart'; import 'package:zup_app/core/injections.dart'; import 'package:zup_app/core/pool_service.dart'; import 'package:zup_app/core/slippage.dart'; -import 'package:zup_app/core/v3_v4_pool_constants.dart'; import 'package:zup_app/core/zup_analytics.dart'; import 'package:zup_app/core/zup_links.dart'; import 'package:zup_app/core/zup_navigator.dart'; @@ -79,8 +79,8 @@ void main() { inject.registerFactory>(() => GlobalKey()); when(() => cubit.setup()).thenAnswer((_) async {}); - when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(V3V4PoolConstants.maxTick)); - when(() => cubit.latestPoolTick).thenReturn(BigInt.from(3247)); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => Stream.value(CLPoolConstants.maxTick)); + when(() => cubit.latestPriceX96).thenReturn(BigInt.from(3247)); when(() => cubit.stream).thenAnswer( (_) => Stream.value(PreviewDepositModalState.initial(token0Allowance: BigInt.zero, token1Allowance: BigInt.zero)), ); @@ -301,13 +301,13 @@ void main() { const currentPrice = 3200.0; const minPrice = 4000.0; - final currentPriceAsTick = V3PoolConversorsMixinWrapper().priceToTick( + final currentPriceAsTick = CLPoolConversorsMixinWrapper().priceToTick( price: currentPrice, poolToken0Decimals: currentYield.token0NetworkDecimals, poolToken1Decimals: currentYield.token1NetworkDecimals, ); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.latestPriceX96).thenReturn(currentPriceAsTick); await tester.pumpDeviceBuilder( await goldenBuilder(minPrice: (price: minPrice, isInfinity: false), maxPrice: (price: 0, isInfinity: true)), @@ -325,13 +325,15 @@ void main() { const currentPrice = 3200.0; const maxPrice = 2000.0; - final currentPriceAsTick = V3PoolConversorsMixinWrapper().priceToTick( - price: currentPrice, - poolToken0Decimals: currentYield.token0NetworkDecimals, - poolToken1Decimals: currentYield.token1NetworkDecimals, + final currentPriceAsSqrtPrice = CLPoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick( + CLPoolConversorsMixinWrapper().priceToTick( + price: currentPrice, + poolToken0Decimals: currentYield.token0NetworkDecimals, + poolToken1Decimals: currentYield.token1NetworkDecimals, + ), ); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.latestPriceX96).thenReturn(currentPriceAsSqrtPrice); await tester.pumpDeviceBuilder( await goldenBuilder(minPrice: (price: 0, isInfinity: true), maxPrice: (price: maxPrice, isInfinity: false)), @@ -352,13 +354,15 @@ void main() { const minPrice = 2000.0; const maxPrice = 4000.0; - final currentPriceAsTick = V3PoolConversorsMixinWrapper().priceToTick( - price: currentPrice, - poolToken0Decimals: currentYield.token0NetworkDecimals, - poolToken1Decimals: currentYield.token1NetworkDecimals, + final currentPriceAsSqrtPriceX96 = CLPoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick( + CLPoolConversorsMixinWrapper().priceToTick( + price: currentPrice, + poolToken0Decimals: currentYield.token0NetworkDecimals, + poolToken1Decimals: currentYield.token1NetworkDecimals, + ), ); - when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick); + when(() => cubit.latestPriceX96).thenReturn(currentPriceAsSqrtPriceX96); await tester.pumpDeviceBuilder( await goldenBuilder( @@ -723,8 +727,8 @@ void main() { "Current price card should show the correct price based on the current tick", goldenFileName: "preview_deposit_modal_current_price", (tester) async { - when(() => cubit.latestPoolTick).thenReturn( - V3PoolConversorsMixinWrapper().priceToTick( + when(() => cubit.latestPriceX96).thenReturn( + CLPoolConversorsMixinWrapper().priceToTick( price: 0.01, // It should be shown in the card (or very close to it) poolToken0Decimals: currentYield.token0NetworkDecimals, poolToken1Decimals: currentYield.token1NetworkDecimals, @@ -741,8 +745,8 @@ void main() { "When it's reversed, the Current price card should show the correct price based on the current tick", goldenFileName: "preview_deposit_modal_current_price_reversed", (tester) async { - when(() => cubit.latestPoolTick).thenReturn( - V3PoolConversorsMixinWrapper().priceToTick( + when(() => cubit.latestPriceX96).thenReturn( + CLPoolConversorsMixinWrapper().priceToTick( price: 1200, // It should be shown in the card (or very close to it) poolToken0Decimals: currentYield.token0NetworkDecimals, poolToken1Decimals: currentYield.token1NetworkDecimals, @@ -762,21 +766,21 @@ void main() { goldenFileName: "preview_deposit_modal_current_price_stream", (tester) async { const newPrice = 0.02632; // It should be shown in the card (or very close to it) - final newPriceAsTick = V3PoolConversorsMixinWrapper().priceToTick( + final newPriceAsTick = CLPoolConversorsMixinWrapper().priceToTick( price: newPrice, poolToken0Decimals: currentYield.token0NetworkDecimals, poolToken1Decimals: currentYield.token1NetworkDecimals, isReversed: false, ); - final poolTickStreamController = StreamController.broadcast(); - when(() => cubit.poolTickStream).thenAnswer((_) => poolTickStreamController.stream); + final poolSqrtPriceX96StreamController = StreamController.broadcast(); + when(() => cubit.poolSqrtPriceX96Stream).thenAnswer((_) => poolSqrtPriceX96StreamController.stream); await tester.pumpDeviceBuilder(await goldenBuilder(), wrapper: GoldenConfig.localizationsWrapper()); await tester.pumpAndSettle(); - when(() => cubit.latestPoolTick).thenReturn(newPriceAsTick); - poolTickStreamController.add(newPriceAsTick); + when(() => cubit.latestPriceX96).thenReturn(newPriceAsTick); + poolSqrtPriceX96StreamController.add(newPriceAsTick); await tester.pumpAndSettle(); }, @@ -915,7 +919,7 @@ void main() { token1DepositAmountController: TextEditingController(text: "4300"), deadline: const Duration(minutes: 30), maxSlippage: Slippage.halfPercent, - ).show(context, currentPoolTick: BigInt.from(121475)); + ).show(context, currentPriceX96: BigInt.from(121475)); }); return const SizedBox(); @@ -950,7 +954,7 @@ void main() { token1DepositAmountController: TextEditingController(text: "4300"), deadline: const Duration(minutes: 30), maxSlippage: Slippage.halfPercent, - ).show(context, currentPoolTick: BigInt.from(121475)); + ).show(context, currentPriceX96: BigInt.from(121475)); }); return const SizedBox(); @@ -991,9 +995,27 @@ void main() { "When the state is slippage check error, it should show an error snack bar saying to change the slippage", goldenFileName: "preview_deposit_modal_slippage_check_error", (tester) async { - when(() => cubit.state).thenReturn(const PreviewDepositModalState.slippageCheckError()); + when(() => cubit.state).thenReturn(const PreviewDepositModalState.slippageCheckError(false)); + when(() => cubit.stream).thenAnswer((_) { + return Stream.value(const PreviewDepositModalState.slippageCheckError(false)); + }); + + await tester.pumpDeviceBuilder( + await goldenBuilder(), + wrapper: GoldenConfig.localizationsWrapper(scaffoldMessengerKey: scaffoldMessengerKey), + ); + + await tester.pumpAndSettle(); + }, + ); + + zGoldenTest( + "When the state is slippage check error with automatic slippage one, it should show an error snack bar saying to try again or change the slippage", + goldenFileName: "preview_deposit_modal_slippage_check_error_auto_slippage", + (tester) async { + when(() => cubit.state).thenReturn(const PreviewDepositModalState.slippageCheckError(true)); when(() => cubit.stream).thenAnswer((_) { - return Stream.value(const PreviewDepositModalState.slippageCheckError()); + return Stream.value(const PreviewDepositModalState.slippageCheckError(true)); }); await tester.pumpDeviceBuilder( diff --git a/test/app/goldens/app_layout_cookie_consent_not_null.png b/test/app/goldens/app_layout_cookie_consent_not_null.png index 0d58aa3..31af96c 100644 Binary files a/test/app/goldens/app_layout_cookie_consent_not_null.png and b/test/app/goldens/app_layout_cookie_consent_not_null.png differ diff --git a/test/app/goldens/app_layout_cookie_consent_null.png b/test/app/goldens/app_layout_cookie_consent_null.png index fdf81b4..fbc25ae 100644 Binary files a/test/app/goldens/app_layout_cookie_consent_null.png and b/test/app/goldens/app_layout_cookie_consent_null.png differ diff --git a/test/app/goldens/app_layout_footer_desktop.png b/test/app/goldens/app_layout_footer_desktop.png index b263421..e695cfa 100644 Binary files a/test/app/goldens/app_layout_footer_desktop.png and b/test/app/goldens/app_layout_footer_desktop.png differ diff --git a/test/app/goldens/app_layout_footer_mobile.png b/test/app/goldens/app_layout_footer_mobile.png index b8c790d..659789b 100644 Binary files a/test/app/goldens/app_layout_footer_mobile.png and b/test/app/goldens/app_layout_footer_mobile.png differ diff --git a/test/app/goldens/app_layout_navbar.png b/test/app/goldens/app_layout_navbar.png index b3bd968..5041723 100644 Binary files a/test/app/goldens/app_layout_navbar.png and b/test/app/goldens/app_layout_navbar.png differ diff --git a/test/app/goldens/app_layout_top_app_bar.png b/test/app/goldens/app_layout_top_app_bar.png index 0d58aa3..31af96c 100644 Binary files a/test/app/goldens/app_layout_top_app_bar.png and b/test/app/goldens/app_layout_top_app_bar.png differ diff --git a/test/core/bigint_extension_test.dart b/test/core/bigint_extension_test.dart index 8997dfb..b6f3e52 100644 --- a/test/core/bigint_extension_test.dart +++ b/test/core/bigint_extension_test.dart @@ -1,16 +1,16 @@ import 'package:flutter_test/flutter_test.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; import 'package:zup_app/core/extensions/bigint_extension.dart'; -import 'package:zup_app/core/v3_v4_pool_constants.dart'; void main() { test("`isMaxTick` extension should return if the bigInt passed is the max tick based on the V3 pool", () { - BigInt maxTick = V3V4PoolConstants.maxTick; + BigInt maxTick = CLPoolConstants.maxTick; expect(maxTick.isMaxTick, true); }); test("`isMinTick` extension should return if the bigInt passed is the min tick based on the V3 pool", () { - BigInt minTick = V3V4PoolConstants.minTick; + BigInt minTick = CLPoolConstants.minTick; expect(minTick.isMinTick, true); }); diff --git a/test/core/concentrated_liquidity_utils/cl_pool_constants_test.dart b/test/core/concentrated_liquidity_utils/cl_pool_constants_test.dart new file mode 100644 index 0000000..e52f624 --- /dev/null +++ b/test/core/concentrated_liquidity_utils/cl_pool_constants_test.dart @@ -0,0 +1,20 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; + +void main() { + test("minTick should be the correct value", () { + expect(CLPoolConstants.minTick, BigInt.from(-887272)); + }); + + test("maxTick should be the correct value", () { + expect(CLPoolConstants.maxTick, BigInt.from(887272)); + }); + + test("Q96 should be the correct value", () { + expect(CLPoolConstants.q96, BigInt.from(2).pow(96)); + }); + + test("Q32 should be the correct value", () { + expect(CLPoolConstants.q32, BigInt.from(2).pow(32)); + }); +} diff --git a/test/core/concentrated_liquidity_utils/cl_sqrt_price_math_mixin_test.dart b/test/core/concentrated_liquidity_utils/cl_sqrt_price_math_mixin_test.dart new file mode 100644 index 0000000..dadacc4 --- /dev/null +++ b/test/core/concentrated_liquidity_utils/cl_sqrt_price_math_mixin_test.dart @@ -0,0 +1,181 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_sqrt_price_math_mixin.dart'; + +class _Sut with CLSqrtPriceMath {} + +void main() { + late _Sut sut; + + setUp(() { + sut = _Sut(); + }); + + test("When passing a sqrtPriceX96 to `sqrtPriceX96ToPrice` it should return the correct price", () { + final prices = sut.sqrtPriceX96ToPrice( + sqrtPriceX96: BigInt.parse("5240418162556390792557189"), + poolToken0Decimals: 18, + poolToken1Decimals: 6, + ); + + expect(prices.token0PerToken1, 4374.946221380494, reason: "`token0PerToken1` is not correct"); + expect(prices.token1PerToken0, 0.00022857423826445452, reason: "`token1PerToken0` is not correct"); + }); + + test( + """When calling 'getAmount0Delta' with sqrtRatioAX96 greater than sqrtRatioBX96 it should exchange them, + and return the correct value""", + () { + final sqrtRatioAX96 = BigInt.parse("5240418162556390792557189"); + final sqrtRatioBX96 = BigInt.parse("5240418162556390792111188"); + final liquidity = BigInt.parse("100000000000000000000000000"); + + final delta = sut.getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, liquidity, false); + + expect(delta, BigInt.parse("128671845471")); + }, + ); + + test( + """When calling 'getAmount0Delta' with sqrtRatioAX96 less than sqrtRatioBX96 it should, + return the correct value""", + () { + final sqrtRatioAX96 = BigInt.parse("19271902719072981"); + final sqrtRatioBX96 = BigInt.parse("8632786378263726372"); + final liquidity = BigInt.parse("88288282261567"); + + final delta = sut.getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, liquidity, false); + + expect(delta, BigInt.parse("362149133068570772354378451")); + }, + ); + + test( + """When calling 'getAmoun0Delta' with roundUp set to true it should not truncate the value + but instead round it up""", + () { + final sqrtRatioAX96 = BigInt.parse("1111111111119091919191"); + final sqrtRatioBX96 = BigInt.parse("3312413425190"); + final liquidity = BigInt.parse("2781627156271"); + + final delta = sut.getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, liquidity, true); + + expect(delta, BigInt.parse("66532518573368692340871338459")); + }, + ); + + test( + """When calling 'getAmount1Delta' with sqrtRatioAX96 greater than sqrtRatioBX96 it should exchange them, + and return the correct value""", + () { + final sqrtRatioAX96 = BigInt.parse("5240418162556390792557189"); + final sqrtRatioBX96 = BigInt.parse("5240418162556390792111188"); + final liquidity = BigInt.parse("100000000000000000000000000"); + + final delta = sut.getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, liquidity, false); + + expect(delta, BigInt.parse("562")); + }, + ); + + test( + """When calling 'getAmount1Delta' with sqrtRatioAX96 less than sqrtRatioBX96 it should, + return the correct value""", + () { + final sqrtRatioAX96 = BigInt.parse("19271902719072981"); + final sqrtRatioBX96 = BigInt.parse("8632786378263726372"); + final liquidity = BigInt.parse("88288282261567"); + + final delta = sut.getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, liquidity, false); + + expect(delta, BigInt.parse("9598")); + }, + ); + + test( + """When calling 'getAmount1Delta' with roundUp set to true it should not truncate the value + but instead round it up""", + () { + final sqrtRatioAX96 = BigInt.parse("1111111111119091919191"); + final sqrtRatioBX96 = BigInt.parse("3312413425190"); + final liquidity = BigInt.parse("2781627156271"); + + final delta = sut.getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, liquidity, true); + + expect(delta, BigInt.parse("39011")); + }, + ); + + test( + """When calling 'getAmountsDeltas' with the sqrtPriceX96 + lower than the sqrtPriceAX96 it should calculate only the + amount0 delta, and the amount1 should be zero""", + () { + final sqrtPriceX96 = BigInt.parse("19271902719"); + final sqrtPriceAX96 = BigInt.parse("5240418162556"); + final sqrtPriceBX96 = BigInt.parse("8632786378263726372"); + + final liquidity = BigInt.parse("88288282261567"); + + final amountsDeltas = sut.getAmountsDeltas(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, liquidity); + + expect(amountsDeltas.amount0Delta, BigInt.parse("1334800756728304192095196701447")); + expect(amountsDeltas.amount1Delta, BigInt.zero); + }, + ); + + test( + """When calling 'getAmountsDeltas' with the sqrtPriceX96 + greater than the sqrtPriceAX96, but lower than B, this mean + the prices are in range, so both amounts should be calculed""", + () { + final sqrtPriceX96 = BigInt.parse("52404181625563907925571"); + final sqrtPriceAX96 = BigInt.parse("524041816255639079"); + final sqrtPriceBX96 = BigInt.parse("5240418162556390792557189"); + + final liquidity = BigInt.parse("1903728937892"); + + final amountsDeltas = sut.getAmountsDeltas(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, liquidity); + + expect(amountsDeltas.amount0Delta, BigInt.parse("2849403455712571914")); + expect(amountsDeltas.amount1Delta, BigInt.parse("1259179")); + }, + ); + + test( + """When calling 'getAmountsDeltas' with the sqrtPriceX96 + lower than the sqrtPriceAX96, but sqrtPriceA is greater + than B, this mean the prices are reversed, so the + B should be reversed to A and A to B, and then + calculate the amounts, as they are in range""", + () { + final sqrtPriceX96 = BigInt.parse("52404181625563907925571"); + final sqrtPriceAX96 = BigInt.parse("5240418162556390792557189"); + final sqrtPriceBX96 = BigInt.parse("524041816255639079"); + + final liquidity = BigInt.parse("1903728937892"); + + final amountsDeltas = sut.getAmountsDeltas(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, liquidity); + + expect(amountsDeltas.amount0Delta, BigInt.parse("2849403455712571914")); + expect(amountsDeltas.amount1Delta, BigInt.parse("1259179")); + }, + ); + + test( + """When calling 'getAmountsDeltas' with the sqrtPriceX96 + greater than A, and B, this mean it's out of range (upper side) + it should calculate only the delta for the amount 1""", + () { + final sqrtPriceX96 = BigInt.parse("52404181625563907925571"); + final sqrtPriceAX96 = BigInt.parse("524041816255907"); + final sqrtPriceBX96 = BigInt.parse("524041816255"); + + final liquidity = BigInt.parse("897987283288888029739287"); + + final amountsDeltas = sut.getAmountsDeltas(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, liquidity); + + expect(amountsDeltas.amount0Delta, BigInt.zero); + expect(amountsDeltas.amount1Delta, BigInt.parse("5933651484")); + }, + ); +} diff --git a/test/core/mixins/keys_mixin_test.dart b/test/core/mixins/keys_mixin_test.dart index 57ba489..2d6b2a9 100644 --- a/test/core/mixins/keys_mixin_test.dart +++ b/test/core/mixins/keys_mixin_test.dart @@ -21,26 +21,20 @@ void main() { expect(key, 'userTokenBalance-$userAddress-$tokenAddress-native=$isNative-${network.name}'); }); - test("`poolTickCacheKey` should return correct key", () { + test("`poolSqrtPriceCacheKey` should return correct key", () { const network = AppNetworks.sepolia; const poolAddress = '0xPoolAddress'; - final key = _KeysMixinWrapper().poolTickCacheKey( - network: network, - poolAddress: poolAddress, - ); + final key = _KeysMixinWrapper().poolSqrtPriceCacheKey(network: network, poolAddress: poolAddress); - expect(key, 'poolTick-$poolAddress-${network.name}'); + expect(key, 'sqrtPrice-$poolAddress-${network.name}'); }); test("`tokenPriceCacheKey` should return correct key", () { const tokenAddress = '0xTokenAddress'; const network = AppNetworks.sepolia; - final key = _KeysMixinWrapper().tokenPriceCacheKey( - tokenAddress: tokenAddress, - network: network, - ); + final key = _KeysMixinWrapper().tokenPriceCacheKey(tokenAddress: tokenAddress, network: network); expect(key, 'tokenPrice-$tokenAddress-${network.name}'); }); diff --git a/test/core/mixins/v3_pool_conversors_mixin_test.dart b/test/core/mixins/v3_pool_conversors_mixin_test.dart index b8d7aef..0588fc3 100644 --- a/test/core/mixins/v3_pool_conversors_mixin_test.dart +++ b/test/core/mixins/v3_pool_conversors_mixin_test.dart @@ -1,8 +1,8 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:zup_app/core/mixins/v3_pool_conversors_mixin.dart'; -import 'package:zup_app/core/v3_v4_pool_constants.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart'; -class _V3PoolConversorsMixinTest with V3PoolConversorsMixin {} +class _V3PoolConversorsMixinTest with CLPoolConversorsMixin {} void main() { test("`tickToPrice` should correctly convert a passed tick to a price", () { @@ -16,52 +16,60 @@ void main() { expect(price.priceAsBaseToken, 0.00028879450994994706, reason: "`priceAsBaseToken` is not correct"); }); - test("""`tickToClosestValidTick` should correctly convert a - passed tick to its closest valid tick based on the tick spacing (lower tick test case)""", () { - final closestValidTick = _V3PoolConversorsMixinTest().tickToClosestValidTick( - tick: BigInt.from(7), - tickSpacing: 5, - ); + test( + """`tickToClosestValidTick` should correctly convert a + passed tick to its closest valid tick based on the tick spacing (lower tick test case)""", + () { + final closestValidTick = _V3PoolConversorsMixinTest().tickToClosestValidTick( + tick: BigInt.from(7), + tickSpacing: 5, + ); - expect(closestValidTick, BigInt.from(5)); - }); + expect(closestValidTick, BigInt.from(5)); + }, + ); - test("""When calling `tickToClosestValidTick` and the closest valid tick is lower - than the minimum tick, it should return the higher valid tick""", () { - final closestValidTick = _V3PoolConversorsMixinTest().tickToClosestValidTick( - tick: V3V4PoolConstants.minTick - BigInt.from(1), - tickSpacing: 1, - ); + test( + """When calling `tickToClosestValidTick` and the closest valid tick is lower + than the minimum tick, it should return the higher valid tick""", + () { + final closestValidTick = _V3PoolConversorsMixinTest().tickToClosestValidTick( + tick: CLPoolConstants.minTick - BigInt.from(1), + tickSpacing: 1, + ); - expect(closestValidTick, V3V4PoolConstants.minTick); - }); + expect(closestValidTick, CLPoolConstants.minTick); + }, + ); - test("""When calling `tickToClosestValidTick` and the closest valid tick is higher - than the maximum tick, it should return the lower valid tick""", () { - final closestValidTick = _V3PoolConversorsMixinTest().tickToClosestValidTick( - tick: V3V4PoolConstants.maxTick + BigInt.from(2), - tickSpacing: 4, - ); + test( + """When calling `tickToClosestValidTick` and the closest valid tick is higher + than the maximum tick, it should return the lower valid tick""", + () { + final closestValidTick = _V3PoolConversorsMixinTest().tickToClosestValidTick( + tick: CLPoolConstants.maxTick + BigInt.from(2), + tickSpacing: 4, + ); - expect(closestValidTick, V3V4PoolConstants.maxTick); - }); + expect(closestValidTick, CLPoolConstants.maxTick); + }, + ); - test("""`tickToClosestValidTick` should correctly convert a - passed tick to its closest valid tick based on the tick spacing (higher tick test case)""", () { - final closestValidTick = _V3PoolConversorsMixinTest().tickToClosestValidTick( - tick: BigInt.from(8), - tickSpacing: 5, - ); + test( + """`tickToClosestValidTick` should correctly convert a + passed tick to its closest valid tick based on the tick spacing (higher tick test case)""", + () { + final closestValidTick = _V3PoolConversorsMixinTest().tickToClosestValidTick( + tick: BigInt.from(8), + tickSpacing: 5, + ); - expect(closestValidTick, BigInt.from(10)); - }); + expect(closestValidTick, BigInt.from(10)); + }, + ); test("`priceToTick` should correctly convert a passed price to a tick", () { - final tick = _V3PoolConversorsMixinTest().priceToTick( - price: 1200, - poolToken0Decimals: 6, - poolToken1Decimals: 18, - ); + final tick = _V3PoolConversorsMixinTest().priceToTick(price: 1200, poolToken0Decimals: 6, poolToken1Decimals: 18); expect(tick, BigInt.from(347228)); }); diff --git a/test/core/mixins/v3_pool_liquidity_calculations_mixin_test.dart b/test/core/mixins/v3_pool_liquidity_calculations_mixin_test.dart index c9b52e9..1ec142f 100644 --- a/test/core/mixins/v3_pool_liquidity_calculations_mixin_test.dart +++ b/test/core/mixins/v3_pool_liquidity_calculations_mixin_test.dart @@ -1,42 +1,48 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:zup_app/core/mixins/v3_pool_liquidity_calculations_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_liquidity_calculations_mixin.dart'; -class _V3PoolLiquidityCalculationsMixinWrapper with V3PoolLiquidityCalculationsMixin {} +class _CLPoolLiquidityCalculationsMixinWrapper with CLPoolLiquidityCalculationsMixin {} void main() { - test(""""`calculateToken1AmountFromToken0` should return the correct + test( + """"`calculateToken1AmountFromToken0` should return the correct amount for token 1 based on the amount of token 0 to deposit in a pool. - Coming from factors of range and current price""", () { - const tokenXAmount = 1.0; - const currentPrice = 3400.0; - const priceLower = 0.0; - const priceUpper = 4100.0; + Coming from factors of range and current price""", + () { + const tokenXAmount = 1.0; + const currentPrice = 3400.0; + const priceLower = 0.0; + const priceUpper = 4100.0; - final tokenYAmount = _V3PoolLiquidityCalculationsMixinWrapper().calculateToken1AmountFromToken0( - tokenXAmount, - currentPrice, - priceLower, - priceUpper, - ); + final tokenYAmount = _CLPoolLiquidityCalculationsMixinWrapper().calculateToken1AmountFromToken0( + tokenXAmount: tokenXAmount, + currentPrice: currentPrice, + priceLower: priceLower, + priceUpper: priceUpper, + ); - expect(tokenYAmount, 38049.06456823463); - }); + expect(tokenYAmount, 38049.06456823463); + }, + ); - test(""""`calculateToken0AmountFromToken1` should return the correct + test( + """"`calculateToken0AmountFromToken1` should return the correct amount for token 0 based on the amount of token 1 to deposit in a pool. - Coming from factors of range and current price""", () { - const token1Amount = 1.0; - const currentPrice = 3400.0; - const priceLower = 0.0; - const priceUpper = 4100.0; + Coming from factors of range and current price""", + () { + const token1Amount = 1.0; + const currentPrice = 3400.0; + const priceLower = 0.0; + const priceUpper = 4100.0; - final token0Amount = _V3PoolLiquidityCalculationsMixinWrapper().calculateToken0AmountFromToken1( - token1Amount, - currentPrice, - priceLower, - priceUpper, - ); + final token0Amount = _CLPoolLiquidityCalculationsMixinWrapper().calculateToken0AmountFromToken1( + currentPrice: currentPrice, + priceLower: priceLower, + priceUpper: priceUpper, + tokenYAmount: token1Amount, + ); - expect(token0Amount, 0.000026281855056033442); - }); + expect(token0Amount, 0.000026281855056033442); + }, + ); } diff --git a/test/core/mixins/v4_pool_liquidity_calculations_mixin_test.dart b/test/core/mixins/v4_pool_liquidity_calculations_mixin_test.dart index d47280a..7336f5a 100644 --- a/test/core/mixins/v4_pool_liquidity_calculations_mixin_test.dart +++ b/test/core/mixins/v4_pool_liquidity_calculations_mixin_test.dart @@ -1,36 +1,30 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:zup_app/core/mixins/v4_pool_liquidity_calculations_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_liquidity_calculations_mixin.dart'; -class _V4PoolLiquidityCalculationsMixinTest with V4PoolLiquidityCalculationsMixin {} +class _V4PoolLiquidityCalculationsMixinTest with CLPoolLiquidityCalculationsMixin {} void main() { - test( - "When calling `getLiquidityForAmount0` it should return the correct value based on the v4 pool math", - () { - BigInt sqrtPriceAX96 = BigInt.parse("4242269098745952767280720"); - BigInt sqrtPriceBX96 = BigInt.parse("4242269098745952767280721"); - BigInt amount0 = BigInt.from(1241555); + test("When calling `getLiquidityForAmount0` it should return the correct value based on the v4 pool math", () { + BigInt sqrtPriceAX96 = BigInt.parse("4242269098745952767280720"); + BigInt sqrtPriceBX96 = BigInt.parse("4242269098745952767280721"); + BigInt amount0 = BigInt.from(1241555); - expect( - _V4PoolLiquidityCalculationsMixinTest().getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0), - BigInt.parse("282021882116526385820841971"), - ); - }, - ); + expect( + _V4PoolLiquidityCalculationsMixinTest().getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0), + BigInt.parse("282021882116526385820841971"), + ); + }); - test( - "When calling `getLiquidityForAmount1` it should return the correct value based on the v4 pool math", - () { - BigInt sqrtPriceAX96 = BigInt.parse("4242269098745952767280720"); - BigInt sqrtPriceBX96 = BigInt.parse("4242269098745952767280721"); - BigInt amount0 = BigInt.from(1241555); + test("When calling `getLiquidityForAmount1` it should return the correct value based on the v4 pool math", () { + BigInt sqrtPriceAX96 = BigInt.parse("4242269098745952767280720"); + BigInt sqrtPriceBX96 = BigInt.parse("4242269098745952767280721"); + BigInt amount0 = BigInt.from(1241555); - expect( - _V4PoolLiquidityCalculationsMixinTest().getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceBX96, amount0), - BigInt.parse("98366121310397459660952459259412480"), - ); - }, - ); + expect( + _V4PoolLiquidityCalculationsMixinTest().getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceBX96, amount0), + BigInt.parse("98366121310397459660952459259412480"), + ); + }); test( "When calling `getLiquidityForAmounts` and the sqrtpricea is bigger, it should return the token0 liquidity calculated", @@ -42,8 +36,13 @@ void main() { BigInt amount1 = BigInt.from(1241555); expect( - _V4PoolLiquidityCalculationsMixinTest() - .getLiquidityForAmounts(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, amount0, amount1), + _V4PoolLiquidityCalculationsMixinTest().getLiquidityForAmounts( + sqrtPriceX96, + sqrtPriceAX96, + sqrtPriceBX96, + amount0, + amount1, + ), BigInt.parse("282021882116526385820841971"), ); }, @@ -59,8 +58,13 @@ void main() { BigInt amount1 = BigInt.from(1241555); expect( - _V4PoolLiquidityCalculationsMixinTest() - .getLiquidityForAmounts(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, amount0, amount1), + _V4PoolLiquidityCalculationsMixinTest().getLiquidityForAmounts( + sqrtPriceX96, + sqrtPriceAX96, + sqrtPriceBX96, + amount0, + amount1, + ), BigInt.parse("94007294038842128606947412"), ); }, @@ -82,14 +86,8 @@ void main() { }); test('getSqrtPriceAtTick should throw for tick out of range', () { - expect( - () => _V4PoolLiquidityCalculationsMixinTest().getSqrtPriceAtTick(BigInt.from(887273)), - throwsException, - ); + expect(() => _V4PoolLiquidityCalculationsMixinTest().getSqrtPriceAtTick(BigInt.from(887273)), throwsException); - expect( - () => _V4PoolLiquidityCalculationsMixinTest().getSqrtPriceAtTick(BigInt.from(-887273)), - throwsException, - ); + expect(() => _V4PoolLiquidityCalculationsMixinTest().getSqrtPriceAtTick(BigInt.from(-887273)), throwsException); }); } diff --git a/test/core/pool_service_test.dart b/test/core/pool_service_test.dart index 22d136c..09b4a58 100644 --- a/test/core/pool_service_test.dart +++ b/test/core/pool_service_test.dart @@ -14,20 +14,22 @@ import 'package:zup_app/abis/uniswap_v3_pool.abi.g.dart'; import 'package:zup_app/abis/uniswap_v3_position_manager.abi.g.dart'; import 'package:zup_app/abis/uniswap_v4_position_manager.abi.g.dart'; import 'package:zup_app/abis/uniswap_v4_state_view.abi.g.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_constants.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_liquidity_calculations_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/v4_pool_constants.dart'; import 'package:zup_app/core/dtos/protocol_dto.dart'; import 'package:zup_app/core/dtos/token_dto.dart'; import 'package:zup_app/core/dtos/yield_dto.dart'; import 'package:zup_app/core/enums/networks.dart'; import 'package:zup_app/core/enums/pool_type.dart'; import 'package:zup_app/core/enums/protocol_id.dart'; -import 'package:zup_app/core/mixins/v4_pool_liquidity_calculations_mixin.dart'; import 'package:zup_app/core/pool_service.dart'; -import 'package:zup_app/core/v4_pool_constants.dart'; +import 'package:zup_app/core/slippage.dart'; import '../matchers.dart'; import '../mocks.dart'; -class _V4PoolLiquidityCalculationsMixinWrapper with V4PoolLiquidityCalculationsMixin {} +class _V4PoolLiquidityCalculationsMixinWrapper with CLPoolLiquidityCalculationsMixin {} void main() { late PoolService sut; @@ -273,11 +275,10 @@ void main() { final amount0Desired = BigInt.from(100); final amount1Desired = BigInt.from(100); const deadline = Duration.zero; - final amount0Min = BigInt.from(12); - final amount1Min = BigInt.from(12); + const slippage = Slippage.zeroPointOnePercent; final recipient = await signer.address; - final tickLower = BigInt.from(0); - final tickUpper = BigInt.from(0); + final tickLower = CLPoolConstants.minTick; + final tickUpper = CLPoolConstants.maxTick; await sut.sendV3PoolDepositTransaction( currentYield0, @@ -285,8 +286,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: slippage, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -331,8 +331,7 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); + const slippage = Slippage.halfPercent; final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -343,8 +342,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: slippage, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -354,9 +352,9 @@ void main() { () => positionManagerV3.getMintCalldata( params: ( amount0Desired: amount0Desired, - amount0Min: amount0Min, + amount0Min: slippage.calculateMinTokenAmountFromSlippage(amount0Desired), + amount1Min: slippage.calculateMinTokenAmountFromSlippage(amount1Desired), amount1Desired: amount1Desired, - amount1Min: amount1Min, deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch), fee: BigInt.from(currentYield0.initialFeeTier), recipient: recipient, @@ -401,8 +399,7 @@ void main() { final amount0Desired = BigInt.from(100); final amount1Desired = BigInt.from(31); const deadline = Duration.zero; - final amount0Min = BigInt.from(320); - final amount1Min = BigInt.from(12); + const slippage = Slippage.halfPercent; final recipient = await signer.address; final tickLower = BigInt.from(32); final tickUpper = BigInt.from(14489); @@ -413,8 +410,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: slippage, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -424,9 +420,9 @@ void main() { () => positionManagerV3.getMintCalldata( params: ( amount0Desired: amount0Desired, - amount0Min: amount0Min, + amount0Min: slippage.calculateMinTokenAmountFromSlippage(amount0Desired), + amount1Min: slippage.calculateMinTokenAmountFromSlippage(amount1Desired), amount1Desired: amount1Desired, - amount1Min: amount1Min, deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch), fee: BigInt.from(currentYield0.initialFeeTier), recipient: recipient, @@ -471,8 +467,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -483,8 +477,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -530,8 +523,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -542,8 +533,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -586,11 +576,10 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); + const slippage = Slippage.halfPercent; await sut.sendV3PoolDepositTransaction( currentYield0, @@ -598,8 +587,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: slippage, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -615,8 +603,8 @@ void main() { tickUpper: tickUpper, amount0Desired: amount0Desired, amount1Desired: amount1Desired, - amount0Min: amount0Min, - amount1Min: amount1Min, + amount0Min: slippage.calculateMinTokenAmountFromSlippage(amount0Desired), + amount1Min: slippage.calculateMinTokenAmountFromSlippage(amount1Desired), recipient: recipient, deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch), ), @@ -644,8 +632,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -666,8 +652,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -701,8 +686,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -723,8 +706,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -758,8 +740,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -780,8 +760,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -801,8 +780,7 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); + const slippage = Slippage.halfPercent; final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -839,8 +817,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: slippage, recipient: recipient, ); @@ -873,8 +850,8 @@ void main() { amount0Desired, amount1Desired, ), - amount0Max, - amount1Max, + slippage.calculateMaxTokenAmountFromSlippage(amount0Desired), + slippage.calculateMaxTokenAmountFromSlippage(amount1Desired), recipient, EthereumConstants.emptyBytes, ], @@ -892,8 +869,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -901,6 +876,7 @@ void main() { const parameters = "0x2186271217625167f2ffff"; const hooks = "0x2111"; const poolManager = "0xAAABbbaaa"; + const slippage = Slippage.halfPercent; when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x"); when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x"); @@ -946,8 +922,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -974,8 +949,8 @@ void main() { amount0Desired, amount1Desired, ), - amount0Max, - amount1Max, + slippage.calculateMaxTokenAmountFromSlippage(amount0Desired), + slippage.calculateMaxTokenAmountFromSlippage(amount1Desired), recipient, EthereumConstants.emptyBytes, ], @@ -995,8 +970,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1049,8 +1022,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1079,8 +1051,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1133,8 +1103,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1161,8 +1130,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1215,8 +1182,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1244,8 +1210,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1266,8 +1230,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1294,8 +1257,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1316,8 +1277,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1346,8 +1306,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1368,8 +1326,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1395,8 +1352,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1456,8 +1411,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1488,8 +1442,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1566,8 +1518,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1598,8 +1549,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1676,8 +1625,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1707,8 +1655,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1768,8 +1714,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1798,8 +1743,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1855,8 +1798,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1881,8 +1823,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1914,8 +1854,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1939,8 +1878,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -1972,8 +1909,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -1997,8 +1933,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -2030,8 +1964,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -2055,8 +1988,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Max = BigInt.from(4312); - final amount1Max = BigInt.from(1031901); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -2088,8 +2019,7 @@ void main() { tickUpper: tickUpper, amount0toDeposit: amount0Desired, amount1ToDeposit: amount1Desired, - maxAmount0ToDeposit: amount0Max, - maxAmount1ToDeposit: amount1Max, + slippage: Slippage.halfPercent, recipient: recipient, ); @@ -2277,6 +2207,17 @@ void main() { ), ).thenReturn(aerodromeV3PoolImpl); + when(() => aerodromeV3PoolImpl.slot0()).thenAnswer( + (_) async => ( + observationCardinality: BigInt.from(0), + observationCardinalityNext: BigInt.from(0), + observationIndex: BigInt.from(0), + sqrtPriceX96: BigInt.from(12861721), + tick: BigInt.from(128618721), + unlocked: true, + ), + ); + when( () => aerodromePositionManagerV3.getMintCalldata(params: any(named: "params")), ).thenReturn("0x0000000000000000000000000000000000000000000000000000000000000000"); @@ -2292,6 +2233,120 @@ void main() { ).thenAnswer((_) => Future.value(transactionResponse)); }); + test( + """When calling 'sendV3PoolDepositTransaction' with yield protocol being + aerodrome, and passing an automatic slippage, it should calculate + the amounts to deposit from tick lower, tick upper, and the current price, + passing 0.5% slippage to the calculated amount, to not fail during + normal market movements""", + () async { + final poolSqrtPriceX96 = BigInt.parse("5298378196876347059858795"); + final tickLower = BigInt.from(-193920); + final tickUpper = BigInt.from(-190740); + const slippage = Slippage.automatic; + final amount0Desired = BigInt.parse("1773078246741921660"); + final amount1Desired = BigInt.parse("8296557142"); + const deadline = Duration(days: 1); + final recipient = await signer.address; + + when(() => aerodromeV3PoolImpl.slot0()).thenAnswer( + (_) async => ( + sqrtPriceX96: poolSqrtPriceX96, + tick: BigInt.from(1), + observationIndex: BigInt.from(1), + observationCardinality: BigInt.from(1), + observationCardinalityNext: BigInt.from(1), + unlocked: false, + ), + ); + + when( + () => aerodromePositionManagerV3Impl.mint(params: any(named: "params")), + ).thenAnswer((_) async => transactionResponse); + + await sut.sendV3PoolDepositTransaction( + currentYield.copyWith(protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream)), + signer, + amount0Desired: amount0Desired, + amount1Desired: amount1Desired, + deadline: deadline, + recipient: recipient, + tickLower: tickLower, + tickUpper: tickUpper, + slippage: slippage, + ); + + verify( + () => aerodromePositionManagerV3Impl.mint( + params: any( + named: "params", + that: ObjectParamMatcher((object) { + return object.amount0Min == BigInt.parse("1702885666110151159") && + object.amount1Min == BigInt.parse("8255074356"); + }), + ), + ), + ).called(1); + }, + ); + + test( + """When calling 'sendV3PoolDepositTransaction' with yield protocol being + velodrome, and passing an automatic slippage, it should calculate + the amounts to deposit from tick lower, tick upper, and the current price, + passing 0.5% slippage to the calculated amount, to not fail during + normal market movements""", + () async { + final poolSqrtPriceX96 = BigInt.parse("5298378196876347059858795"); + final tickLower = BigInt.from(-193920); + final tickUpper = BigInt.from(-190740); + const slippage = Slippage.automatic; + final amount0Desired = BigInt.parse("1773078246741921660"); + final amount1Desired = BigInt.parse("8296557142"); + const deadline = Duration(days: 1); + final recipient = await signer.address; + + when(() => aerodromeV3PoolImpl.slot0()).thenAnswer( + (_) async => ( + sqrtPriceX96: poolSqrtPriceX96, + tick: BigInt.from(1), + observationIndex: BigInt.from(1), + observationCardinality: BigInt.from(1), + observationCardinalityNext: BigInt.from(1), + unlocked: false, + ), + ); + + when( + () => aerodromePositionManagerV3Impl.mint(params: any(named: "params")), + ).thenAnswer((_) async => transactionResponse); + + await sut.sendV3PoolDepositTransaction( + currentYield.copyWith(protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.velodromeSlipstream)), + signer, + amount0Desired: amount0Desired, + amount1Desired: amount1Desired, + deadline: deadline, + recipient: recipient, + tickLower: tickLower, + tickUpper: tickUpper, + slippage: slippage, + ); + + verify( + () => aerodromePositionManagerV3Impl.mint( + params: any( + named: "params", + that: ObjectParamMatcher((object) { + return object.amount0Min == BigInt.parse("1702885666110151159") && + object.amount1Min == BigInt.parse("8255074356"); + }), + ), + ), + ).called(1); + }, + ); + test("When the protocol is aerodrome v3 it should use aerodrome v3 pool to get the pool tick", () async { final expectedTick = BigInt.from(1271897); @@ -2373,11 +2428,9 @@ void main() { final amount0Desired = BigInt.from(100); final amount1Desired = BigInt.from(100); const deadline = Duration.zero; - final amount0Min = BigInt.from(12); - final amount1Min = BigInt.from(12); final recipient = await signer.address; - final tickLower = BigInt.from(0); - final tickUpper = BigInt.from(0); + final tickLower = CLPoolConstants.minTick; + final tickUpper = CLPoolConstants.maxTick; await sut.sendV3PoolDepositTransaction( currentYield0, @@ -2385,8 +2438,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -2433,11 +2485,10 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); + const slippage = Slippage.halfPercent; await sut.sendV3PoolDepositTransaction( currentYield0, @@ -2445,8 +2496,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: slippage, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -2456,9 +2506,9 @@ void main() { () => aerodromePositionManagerV3.getMintCalldata( params: ( amount0Desired: amount0Desired, - amount0Min: amount0Min, amount1Desired: amount1Desired, - amount1Min: amount1Min, + amount0Min: slippage.calculateMinTokenAmountFromSlippage(amount0Desired), + amount1Min: slippage.calculateMinTokenAmountFromSlippage(amount1Desired), deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch), recipient: recipient, tickLower: tickLower, @@ -2506,8 +2556,7 @@ void main() { final amount0Desired = BigInt.from(100); final amount1Desired = BigInt.from(31); const deadline = Duration.zero; - final amount0Min = BigInt.from(320); - final amount1Min = BigInt.from(12); + const slippage = Slippage.onePercent; final recipient = await signer.address; final tickLower = BigInt.from(32); final tickUpper = BigInt.from(14489); @@ -2518,8 +2567,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: slippage, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -2529,9 +2577,9 @@ void main() { () => aerodromePositionManagerV3.getMintCalldata( params: ( amount0Desired: amount0Desired, - amount0Min: amount0Min, + amount0Min: slippage.calculateMinTokenAmountFromSlippage(amount0Desired), amount1Desired: amount1Desired, - amount1Min: amount1Min, + amount1Min: slippage.calculateMinTokenAmountFromSlippage(amount1Desired), deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch), recipient: recipient, tickLower: tickLower, @@ -2575,8 +2623,7 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); + final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -2587,8 +2634,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -2631,8 +2677,7 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); + final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -2643,8 +2688,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -2686,11 +2730,10 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); + const slipagge = Slippage.halfPercent; await sut.sendV3PoolDepositTransaction( currentYield0, @@ -2698,8 +2741,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: slipagge, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -2715,8 +2757,8 @@ void main() { tickUpper: tickUpper, amount0Desired: amount0Desired, amount1Desired: amount1Desired, - amount0Min: amount0Min, - amount1Min: amount1Min, + amount0Min: slipagge.calculateMinTokenAmountFromSlippage(amount0Desired), + amount1Min: slipagge.calculateMinTokenAmountFromSlippage(amount1Desired), recipient: recipient, deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch), sqrtPriceX96: BigInt.from(0), @@ -2768,8 +2810,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -2780,8 +2820,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -2840,8 +2879,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -2852,8 +2889,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -2942,8 +2978,8 @@ void main() { amount0Min: BigInt.from(0), amount1Min: BigInt.from(0), recipient: "", - tickLower: BigInt.from(0), - tickUpper: BigInt.from(0), + tickLower: CLPoolConstants.minTick, + tickUpper: CLPoolConstants.maxTick, deployer: "", token0: "", token1: "", @@ -2957,6 +2993,17 @@ void main() { ), ).thenReturn(algebra121PoolImpl); + when(() => algebra121PoolImpl.globalState()).thenAnswer( + (_) async => ( + price: BigInt.from(8261872678162871), + tick: BigInt.from(16278156721), + lastFee: BigInt.from(0), + pluginConfig: BigInt.from(0), + communityFee: BigInt.from(0), + unlocked: false, + ), + ); + when( () => algebra121PositionManager.fromSigner( contractAddress: any(named: "contractAddress"), @@ -2965,6 +3012,63 @@ void main() { ).thenReturn(algebra121PositionManagerImpl); }); + test( + """When calling 'sendV3PoolDepositTransaction' with yield protocol being + gliquid, and passing an automatic slippage, it should calculate + the amounts to deposit from tick lower, tick upper, and the current price, + passing 0.5% slippage to the calculated amount, to not fail during + normal market movements""", + () async { + final poolSqrtPriceX96 = BigInt.parse("5298378196876347059858795"); + final tickLower = BigInt.from(-193920); + final tickUpper = BigInt.from(-190740); + const slippage = Slippage.automatic; + final amount0Desired = BigInt.parse("1773078246741921660"); + final amount1Desired = BigInt.parse("8296557142"); + const deadline = Duration(days: 1); + final recipient = await signer.address; + + when(() => algebra121PoolImpl.globalState()).thenAnswer( + (_) async => ( + price: poolSqrtPriceX96, + tick: BigInt.from(0), + lastFee: BigInt.from(0), + pluginConfig: BigInt.from(0), + communityFee: BigInt.from(0), + unlocked: false, + ), + ); + + when( + () => algebra121PositionManagerImpl.mint(params: any(named: "params")), + ).thenAnswer((_) async => transactionResponse); + + await sut.sendV3PoolDepositTransaction( + currentYield.copyWith(protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3)), + signer, + amount0Desired: amount0Desired, + amount1Desired: amount1Desired, + deadline: deadline, + recipient: recipient, + tickLower: tickLower, + tickUpper: tickUpper, + slippage: slippage, + ); + + verify( + () => algebra121PositionManagerImpl.mint( + params: any( + named: "params", + that: ObjectParamMatcher((object) { + return object.amount0Min == BigInt.parse("1702885666110151159") && + object.amount1Min == BigInt.parse("8255074356"); + }), + ), + ), + ).called(1); + }, + ); + test("When calling 'getPoolTick' it should return the pool tick got from algebra pool 1.2.1", () async { final expectedTick = BigInt.from(12871); when(() => algebra121PoolImpl.globalState()).thenAnswer( @@ -3033,11 +3137,9 @@ void main() { final amount0Desired = BigInt.from(100); final amount1Desired = BigInt.from(100); const deadline = Duration.zero; - final amount0Min = BigInt.from(12); - final amount1Min = BigInt.from(12); final recipient = await signer.address; - final tickLower = BigInt.from(0); - final tickUpper = BigInt.from(0); + final tickLower = CLPoolConstants.minTick; + final tickUpper = CLPoolConstants.maxTick; await sut.sendV3PoolDepositTransaction( currentYield0, @@ -3045,8 +3147,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -3091,11 +3192,11 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); + final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); + const slippage = Slippage.halfPercent; await sut.sendV3PoolDepositTransaction( currentYield0, @@ -3103,8 +3204,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: slippage, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -3114,9 +3214,9 @@ void main() { () => algebra121PositionManager.getMintCalldata( params: ( amount0Desired: amount0Desired, - amount0Min: amount0Min, + amount0Min: slippage.calculateMinTokenAmountFromSlippage(amount0Desired), + amount1Min: slippage.calculateMinTokenAmountFromSlippage(amount1Desired), amount1Desired: amount1Desired, - amount1Min: amount1Min, deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch), recipient: recipient, tickLower: tickLower, @@ -3161,8 +3261,7 @@ void main() { final amount0Desired = BigInt.from(100); final amount1Desired = BigInt.from(31); const deadline = Duration.zero; - final amount0Min = BigInt.from(320); - final amount1Min = BigInt.from(12); + const slippage = Slippage.halfPercent; final recipient = await signer.address; final tickLower = BigInt.from(32); final tickUpper = BigInt.from(14489); @@ -3173,8 +3272,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: slippage, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -3184,9 +3282,9 @@ void main() { () => algebra121PositionManager.getMintCalldata( params: ( amount0Desired: amount0Desired, - amount0Min: amount0Min, + amount0Min: slippage.calculateMinTokenAmountFromSlippage(amount0Desired), + amount1Min: slippage.calculateMinTokenAmountFromSlippage(amount1Desired), amount1Desired: amount1Desired, - amount1Min: amount1Min, deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch), recipient: recipient, tickLower: tickLower, @@ -3229,8 +3327,6 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -3241,8 +3337,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -3289,8 +3384,7 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); + final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -3301,8 +3395,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -3342,8 +3435,7 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); + final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -3354,8 +3446,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -3395,8 +3486,7 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); + final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -3407,8 +3497,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -3457,8 +3546,7 @@ void main() { final amount0Desired = BigInt.from(4311); final amount1Desired = BigInt.from(1031900); const deadline = Duration(days: 1); - final amount0Min = BigInt.from(1390); - final amount1Min = BigInt.from(432); + final recipient = await signer.address; final tickLower = BigInt.from(321); final tickUpper = BigInt.from(1222); @@ -3469,8 +3557,7 @@ void main() { amount0Desired: amount0Desired, amount1Desired: amount1Desired, deadline: deadline, - amount0Min: amount0Min, - amount1Min: amount1Min, + slippage: Slippage.halfPercent, recipient: recipient, tickLower: tickLower, tickUpper: tickUpper, @@ -3488,4 +3575,244 @@ void main() { }, ); }); + + test( + """When calling 'sendV3PoolDepositTransaction' passing an automatic slippage, + it should calculate the amounts to deposit from tick lower, tick upper, + and the current price, passing 0.5% slippage to the calculated amount, + to not fail during normal market movements""", + () async { + final poolSqrtPriceX96 = BigInt.parse("5298378196876347059858795"); + final tickLower = BigInt.from(-193920); + final tickUpper = BigInt.from(-190740); + const slippage = Slippage.automatic; + final amount0Desired = BigInt.parse("1773078246741921660"); + final amount1Desired = BigInt.parse("8296557142"); + const deadline = Duration(days: 1); + final recipient = await signer.address; + + when(() => uniswapV3PoolImpl.slot0()).thenAnswer( + (_) async => ( + sqrtPriceX96: poolSqrtPriceX96, + tick: BigInt.from(1), + observationIndex: BigInt.from(1), + observationCardinality: BigInt.from(1), + observationCardinalityNext: BigInt.from(1), + feeProtocol: BigInt.from(1), + unlocked: false, + ), + ); + + when(() => positionManagerV3Impl.mint(params: any(named: "params"))).thenAnswer((_) async => transactionResponse); + + await sut.sendV3PoolDepositTransaction( + currentYield, + signer, + amount0Desired: amount0Desired, + amount1Desired: amount1Desired, + deadline: deadline, + recipient: recipient, + tickLower: tickLower, + tickUpper: tickUpper, + slippage: slippage, + ); + + verify( + () => positionManagerV3Impl.mint( + params: any( + named: "params", + that: ObjectParamMatcher((object) { + return object.amount0Min == BigInt.parse("1702885666110151159") && + object.amount1Min == BigInt.parse("8255074356"); + }), + ), + ), + ).called(1); + }, + ); + + test( + """When calling 'sendV4PoolDepositTransaction' passing an automatic slippage, + it should calculate the amounts to deposit from tick lower, tick upper, + and the current price, passing 0.5% slippage to the calculated amount, + to not fail during normal market movements""", + () async { + final poolSqrtPriceX96 = BigInt.parse("5324028620041997063966665"); + final tickLower = BigInt.from(-887220); + final tickUpper = BigInt.from(887220); + const slippage = Slippage.automatic; + final amount0Desired = BigInt.parse("14999999952321436"); + final amount1Desired = BigInt.parse("67734956"); + const deadline = Duration(days: 1); + final recipient = await signer.address; + final liquidity = _V4PoolLiquidityCalculationsMixinWrapper().getLiquidityForAmounts( + poolSqrtPriceX96, + _V4PoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick(tickLower), + _V4PoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick(tickUpper), + amount0Desired, + amount1Desired, + ); + + when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x"); + when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x"); + + when(() => uniswapV4StateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer( + (_) async => + (sqrtPriceX96: poolSqrtPriceX96, tick: BigInt.from(1), protocolFee: BigInt.from(1), lpFee: BigInt.from(1)), + ); + + when( + () => uniswapPositionManagerV4Impl.modifyLiquidities( + unlockData: any(named: "unlockData"), + deadline: any(named: "deadline"), + ), + ).thenAnswer((_) async => transactionResponse); + + await sut.sendV4PoolDepositTransaction( + currentYield.copyWith(poolType: PoolType.v4, v4StateView: "0x"), + signer, + amount0toDeposit: amount0Desired, + amount1ToDeposit: amount1Desired, + deadline: deadline, + recipient: recipient, + tickLower: tickLower, + tickUpper: tickUpper, + slippage: slippage, + ); + + verify( + () => ethereumAbiCoder.encode( + [ + "tuple(address,address,int32,int24,address)", + "int24", + "int24", + "uint256", + "uint128", + "uint128", + "address", + "bytes", + ], + [ + [ + currentYield.token0.addresses[currentYield.network.chainId]!, + currentYield.token1.addresses[currentYield.network.chainId]!, + BigInt.from(currentYield.initialFeeTier), + BigInt.from(currentYield.tickSpacing), + currentYield.v4Hooks, + ], + tickLower, + tickUpper, + liquidity, + BigInt.from(15074999952083043), + BigInt.from(68073630), + recipient, + EthereumConstants.emptyBytes, + ], + ), + ).called(1); + }, + ); + + test( + """When calling 'sendV4PoolDepositTransaction' passing an automatic slippage, + and the protocol be pancakeSwapInfinityCL it should calculate the amounts to deposit from tick lower, tick upper, + and the current price, passing 0.5% slippage to the calculated amount, + to not fail during normal market movements""", + () async { + final poolSqrtPriceX96 = BigInt.parse("5324028620041997063966665"); + final tickLower = BigInt.from(-887220); + final tickUpper = BigInt.from(887220); + const slippage = Slippage.automatic; + final amount0Desired = BigInt.parse("14999999952321436"); + final amount1Desired = BigInt.parse("67734956"); + const deadline = Duration(days: 1); + final recipient = await signer.address; + final liquidity = _V4PoolLiquidityCalculationsMixinWrapper().getLiquidityForAmounts( + poolSqrtPriceX96, + _V4PoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick(tickLower), + _V4PoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick(tickUpper), + amount0Desired, + amount1Desired, + ); + const hooks = "0x"; + const parameters = "0x"; + const poolManager = "0x"; + + when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x"); + when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x"); + + when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer( + (_) async => + (sqrtPriceX96: poolSqrtPriceX96, tick: BigInt.from(1), protocolFee: BigInt.from(1), lpFee: BigInt.from(1)), + ); + + when( + () => pancakeSwapInfinityCLPositionManagerImpl.modifyLiquidities( + payload: any(named: "payload"), + deadline: any(named: "deadline"), + ), + ).thenAnswer((_) async => transactionResponse); + + when(() => pancakeSwapInfinityCLPoolManagerImpl.poolIdToPoolKey(id: any(named: "id"))).thenAnswer( + (_) async => ( + currency0: "0x", + currency1: "0x", + fee: BigInt.from(1), + hooks: hooks, + parameters: parameters, + poolManager: poolManager, + ), + ); + + await sut.sendV4PoolDepositTransaction( + currentYield.copyWith( + protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL), + poolType: PoolType.v4, + v4Hooks: hooks, + v4PoolManager: "0x", + v4StateView: "0x", + ), + signer, + amount0toDeposit: amount0Desired, + amount1ToDeposit: amount1Desired, + deadline: deadline, + recipient: recipient, + tickLower: tickLower, + tickUpper: tickUpper, + slippage: slippage, + ); + + verify( + () => ethereumAbiCoder.encode( + [ + "tuple(address,address,address,address,uint24,bytes32)", + "int24", + "int24", + "uint256", + "uint128", + "uint128", + "address", + "bytes", + ], + [ + [ + currentYield.token0.addresses[currentYield.network.chainId]!, + currentYield.token1.addresses[currentYield.network.chainId]!, + hooks, + poolManager, + currentYield.initialFeeTier, + parameters, + ], + tickLower, + tickUpper, + liquidity, + BigInt.from(15074999952083043), + BigInt.from(68073630), + recipient, + EthereumConstants.emptyBytes, + ], + ), + ).called(1); + }, + ); } diff --git a/test/core/slippage_test.dart b/test/core/slippage_test.dart index 5d84c62..18bd511 100644 --- a/test/core/slippage_test.dart +++ b/test/core/slippage_test.dart @@ -5,6 +5,10 @@ import 'package:zup_app/core/slippage.dart'; import 'package:zup_ui_kit/zup_ui_kit.dart'; void main() { + test("When using `automatic` method, it should create the slippage object with 0 value", () { + expect(Slippage.automatic.value, 0); + }); + test("When using `zeroPointOnePercent` method it should create the slippage object with 0.1 value", () { expect(Slippage.zeroPointOnePercent.value, 0.1); }); @@ -25,6 +29,10 @@ void main() { expect(Slippage.fromValue(0.1), Slippage.zeroPointOnePercent); }); + test("When passing '0' to `fromValue` factory, it should create a 'automatic' slippage object", () { + expect(Slippage.fromValue(0), Slippage.automatic); + }); + test("When passing '0.5' to `fromValue` factory, it should create a 'halfPercent' slippage object", () { expect(Slippage.fromValue(0.5), Slippage.halfPercent); }); @@ -37,6 +45,14 @@ void main() { expect(Slippage.fromValue(542), Slippage.custom(542)); }); + test("When calling `isAutomatic` and the slippage type is automatic, it should return true", () { + expect(Slippage.automatic.isAutomatic, true); + }); + + test("When calling `isAutomatic` and the slippage type is not automatic, it should return false", () { + expect(Slippage.zeroPointOnePercent.isAutomatic, false); + }); + test( "When passing a value greater than 10 in `riskBackgroundColor` and a light brightness, it should return the red6 color", () { @@ -96,18 +112,19 @@ void main() { }); test( - "When using `isCustom` method it should return true if the slippage is not `zeroPointOnePercent`, `halfPercent` or `onePercent`", + "When using `isCustom` method it should return true if the slippage is not `zeroPointOnePercent`, `halfPercent`, `onePercent` or `automatic`", () { expect(Slippage.custom(43672).isCustom, true); }, ); test( - "When using `isCustom` method it should return false if the slippage is one of `zeroPointOnePercent`, `halfPercent` or `onePercent`", + "When using `isCustom` method it should return false if the slippage is one of `zeroPointOnePercent`, `halfPercent`, `onePercent` or `automatic`", () { expect(Slippage.zeroPointOnePercent.isCustom, false, reason: "zeroPointOnePercent is not custom"); expect(Slippage.halfPercent.isCustom, false, reason: "halfPercent is not custom"); expect(Slippage.onePercent.isCustom, false, reason: "onePercent is not custom"); + expect(Slippage.automatic.isCustom, false, reason: "automatic is not custom"); }, ); diff --git a/test/core/v4_pool_constants_test.dart b/test/core/v4_pool_constants_test.dart index dd380c2..e819bd9 100644 --- a/test/core/v4_pool_constants_test.dart +++ b/test/core/v4_pool_constants_test.dart @@ -1,5 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:zup_app/core/v4_pool_constants.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/v4_pool_constants.dart'; void main() { test('mintPositionActionValue should return the correct value', () { diff --git a/test/wrappers.dart b/test/wrappers.dart index 2989d0b..c11403d 100644 --- a/test/wrappers.dart +++ b/test/wrappers.dart @@ -1,3 +1,6 @@ -import 'package:zup_app/core/mixins/v3_pool_conversors_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_conversors_mixin.dart'; +import 'package:zup_app/core/concentrated_liquidity_utils/cl_pool_liquidity_calculations_mixin.dart'; -class V3PoolConversorsMixinWrapper with V3PoolConversorsMixin {} +class CLPoolConversorsMixinWrapper with CLPoolConversorsMixin {} + +class CLPoolLiquidityCalculationsMixinWrapper with CLPoolLiquidityCalculationsMixin {} diff --git a/web/index.html b/web/index.html index c0f51ca..fb1e7c2 100644 --- a/web/index.html +++ b/web/index.html @@ -66,6 +66,6 @@ inject(); - +