diff --git a/.vscode/launch.json b/.vscode/launch.json
index ad61127..fe8f4b8 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -11,9 +11,6 @@
"toolArgs": [
"--dart-define=env=local",
],
- "args": [
- "--web-experimental-hot-reload"
- ]
},
{
"name": "Zup App (Web) (Debug)",
diff --git a/assets/logos/bnb_chain.svg b/assets/logos/bnb_chain.svg
new file mode 100644
index 0000000..7f8d0da
--- /dev/null
+++ b/assets/logos/bnb_chain.svg
@@ -0,0 +1,3 @@
+
diff --git a/lib/abis/pancake_swap_infinity_cl_pool_manager.abi.json b/lib/abis/pancake_swap_infinity_cl_pool_manager.abi.json
new file mode 100644
index 0000000..1117a3b
--- /dev/null
+++ b/lib/abis/pancake_swap_infinity_cl_pool_manager.abi.json
@@ -0,0 +1,36 @@
+[
+ {
+ "inputs": [
+ {
+ "internalType": "PoolId",
+ "name": "id",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getSlot0",
+ "outputs": [
+ {
+ "internalType": "uint160",
+ "name": "sqrtPriceX96",
+ "type": "uint160"
+ },
+ {
+ "internalType": "int24",
+ "name": "tick",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint24",
+ "name": "protocolFee",
+ "type": "uint24"
+ },
+ {
+ "internalType": "uint24",
+ "name": "lpFee",
+ "type": "uint24"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+]
\ No newline at end of file
diff --git a/lib/app/app_layout.dart b/lib/app/app_layout.dart
index 595e756..c75802a 100644
--- a/lib/app/app_layout.dart
+++ b/lib/app/app_layout.dart
@@ -73,9 +73,13 @@ class _AppPageState extends State with DeviceInfoMixin {
title: AppHeader(height: appBarHeight),
toolbarHeight: appBarHeight,
),
- const SliverFillRemaining(
- hasScrollBody: false,
- child: RouterOutlet(key: Key("screen")),
+ SliverToBoxAdapter(
+ child: ConstrainedBox(
+ constraints: BoxConstraints(minHeight: MediaQuery.of(context).size.height - appBarHeight),
+ child: const RouterOutlet(
+ key: Key("screen"),
+ ),
+ ),
),
SliverToBoxAdapter(
child: Padding(
diff --git a/lib/app/create/create_page_select_tokens_stage.dart b/lib/app/create/create_page_select_tokens_stage.dart
index 5989e8e..9bcc059 100644
--- a/lib/app/create/create_page_select_tokens_stage.dart
+++ b/lib/app/create/create_page_select_tokens_stage.dart
@@ -2,7 +2,8 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:zup_app/app/app_cubit/app_cubit.dart';
-import 'package:zup_app/app/create/widgets/create_page_settings_dropdown.dart';
+import 'package:zup_app/app/create/widgets/create_page_settings_dropdown/create_page_settings_dropdown.dart';
+import 'package:zup_app/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button.dart';
import 'package:zup_app/core/cache.dart';
import 'package:zup_app/core/dtos/token_dto.dart';
import 'package:zup_app/core/injections.dart';
@@ -100,7 +101,7 @@ class _CreatePageState extends State with DeviceInf
child: Align(
alignment: Alignment.topCenter,
child: ConstrainedBox(
- constraints: const BoxConstraints(maxWidth: 490, minHeight: 500),
+ constraints: const BoxConstraints(maxWidth: 490),
child: Align(
alignment: Alignment.topLeft,
child: Column(
@@ -112,48 +113,56 @@ class _CreatePageState extends State with DeviceInf
style: const TextStyle(fontSize: 14, color: ZupColors.gray),
),
const SizedBox(height: 20),
- Row(
- children: [
- Transform.translate(
- offset: const Offset(0, 8),
- child: Text(
- S.of(context).token0,
- style: const TextStyle(
- fontWeight: FontWeight.w500,
- fontSize: 14,
- color: ZupColors.gray,
+ SizedBox(
+ width: double.infinity,
+ child: Wrap(
+ runSpacing: 10,
+ verticalDirection: VerticalDirection.up,
+ alignment: WrapAlignment.spaceBetween,
+ children: [
+ Transform.translate(
+ offset: const Offset(0, 8),
+ child: Text(
+ S.of(context).token0,
+ style: const TextStyle(
+ fontWeight: FontWeight.w500,
+ fontSize: 14,
+ color: ZupColors.gray,
+ ),
),
),
- ),
- const Spacer(),
- StatefulBuilder(builder: (context, localSetState) {
- return Row(
- children: [
- Badge(
- alignment: const Alignment(1.05, -1.05),
- smallSize: cache.getPoolSearchSettings().isDefault ? 0 : 6,
- backgroundColor: ZupColors.orange,
- child: ZupPillButton(
- key: const Key("pool-search-settings-button"),
- onPressed: (buttonContext) => CreatePageSettingsDropdown.show(
- buttonContext,
- onClose: () {
- if (mounted) {
- WidgetsBinding.instance.addPostFrameCallback((_) => localSetState(() {}));
- }
- },
+ StatefulBuilder(builder: (context, localSetState) {
+ return Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ const ExchangesFilterDropdownButton(),
+ const SizedBox(width: 10),
+ Badge(
+ alignment: const Alignment(1.05, -1.05),
+ smallSize: cache.getPoolSearchSettings().isDefault ? 0 : 6,
+ backgroundColor: ZupColors.orange,
+ child: ZupMiniButton(
+ key: const Key("pool-search-settings-button"),
+ onPressed: (buttonContext) => CreatePageSettingsDropdown.show(
+ buttonContext,
+ onClose: () {
+ if (mounted) {
+ WidgetsBinding.instance.addPostFrameCallback((_) => localSetState(() {}));
+ }
+ },
+ ),
+ title: S.of(context).createPageSelectTokensStageSearchSettings,
+ icon: Assets.icons.gear.svg(
+ height: 18,
+ colorFilter: const ColorFilter.mode(ZupColors.white, BlendMode.srcIn),
+ ),
),
- foregroundColor: ZupColors.gray,
- backgroundColor: ZupColors.gray6,
- title: "Search settings",
- icon: Assets.icons.gear.svg(
- height: 18, colorFilter: const ColorFilter.mode(ZupColors.white, BlendMode.srcIn)),
),
- ),
- ],
- );
- })
- ],
+ ],
+ );
+ })
+ ],
+ ),
),
const SizedBox(height: 12),
TokenSelectorButton(
@@ -191,7 +200,7 @@ class _CreatePageState extends State with DeviceInf
icon: Assets.icons.sparkleMagnifyingglass.svg(),
onPressed: token0SelectorController.selectedToken != null &&
token1SelectorController.selectedToken != null
- ? () {
+ ? (buttonContext) {
return navigator.navigateToDeposit(
appCubit.selectedNetwork.isAllNetworks
? token0SelectorController.selectedToken!.internalId!
diff --git a/lib/app/create/deposit/deposit_cubit.dart b/lib/app/create/deposit/deposit_cubit.dart
index f47a4df..83b10ec 100644
--- a/lib/app/create/deposit/deposit_cubit.dart
+++ b/lib/app/create/deposit/deposit_cubit.dart
@@ -6,6 +6,7 @@ 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/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';
import 'package:zup_app/core/dtos/yield_dto.dart';
import 'package:zup_app/core/dtos/yields_dto.dart';
@@ -42,6 +43,7 @@ class DepositCubit extends Cubit with KeysMixin, V3PoolConversorsM
final StreamController _pooltickStreamController = StreamController.broadcast();
final StreamController _selectedYieldStreamController = StreamController.broadcast();
+ final Duration _poolTickExpiration = const Duration(seconds: 30);
BigInt? _latestPoolTick;
YieldDto? _selectedYield;
@@ -57,7 +59,7 @@ class DepositCubit extends Cubit with KeysMixin, V3PoolConversorsM
PoolSearchSettingsDto get poolSearchSettings => _cache.getPoolSearchSettings();
void setup() async {
- Timer.periodic(const Duration(minutes: 1), (timer) {
+ Timer.periodic(_poolTickExpiration, (timer) {
if (_pooltickStreamController.isClosed) return timer.cancel();
if (selectedYield != null) getSelectedPoolTick();
@@ -79,12 +81,14 @@ class DepositCubit extends Cubit with KeysMixin, V3PoolConversorsM
emit(const DepositState.loading());
final yields = _appCubit.selectedNetwork.isAllNetworks
? await _yieldRepository.getAllNetworksYield(
+ blockedProtocolIds: _cache.blockedProtocolsIds,
token0InternalId: token0AddressOrId,
token1InternalId: token1AddressOrId,
searchSettings: ignoreMinLiquidity ? poolSearchSettings.copyWith(minLiquidityUSD: 0) : poolSearchSettings,
testnetMode: _appCubit.isTestnetMode,
)
: await _yieldRepository.getSingleNetworkYield(
+ blockedProtocolIds: _cache.blockedProtocolsIds,
token0Address: token0AddressOrId,
token1Address: token1AddressOrId,
network: _appCubit.selectedNetwork,
@@ -93,7 +97,7 @@ class DepositCubit extends Cubit with KeysMixin, V3PoolConversorsM
if (yields.isEmpty) {
return emit(
- DepositState.noYields(minLiquiditySearched: yields.minLiquidityUSD),
+ DepositState.noYields(filtersApplied: yields.filters),
);
}
@@ -123,7 +127,7 @@ class DepositCubit extends Cubit with KeysMixin, V3PoolConversorsM
final tick = await _zupSingletonCache.run(
() => _poolService.getPoolTick(selectedYieldBeforeCall!),
- expiration: const Duration(minutes: 1),
+ expiration: _poolTickExpiration - const Duration(seconds: 1),
ignoreCache: forceRefresh,
key: poolTickCacheKey(
network: selectedYield!.network,
diff --git a/lib/app/create/deposit/deposit_page.dart b/lib/app/create/deposit/deposit_page.dart
index f596b2b..c1f448b 100644
--- a/lib/app/create/deposit/deposit_page.dart
+++ b/lib/app/create/deposit/deposit_page.dart
@@ -1,3 +1,5 @@
+import 'dart:async';
+
import 'package:decimal/decimal.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@@ -14,6 +16,7 @@ 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/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';
import 'package:zup_app/core/dtos/yield_dto.dart';
import 'package:zup_app/core/dtos/yields_dto.dart';
@@ -103,6 +106,7 @@ class _DepositPageState extends State
double maxPrice = 0;
RangeController minRangeController = RangeController();
RangeController maxRangeController = RangeController();
+ StreamSubscription? _poolTickStreamSubscription;
late Slippage selectedSlippage = _cubit.depositSettings.slippage;
late Duration selectedDeadline = _cubit.depositSettings.deadline;
@@ -122,8 +126,8 @@ class _DepositPageState extends State
final price = tickToPrice(
tick: _cubit.latestPoolTick!,
- poolToken0Decimals: _cubit.selectedYield!.token0.decimals,
- poolToken1Decimals: _cubit.selectedYield!.token1.decimals,
+ poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals,
+ poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals,
);
return areTokensReversed ? price.priceAsQuoteToken : price.priceAsBaseToken;
@@ -214,14 +218,14 @@ class _DepositPageState extends State
final maxTickPrice = tickToPrice(
tick: V3V4PoolConstants.maxTick,
- poolToken0Decimals: _cubit.selectedYield!.token0.decimals,
- poolToken1Decimals: _cubit.selectedYield!.token1.decimals,
+ poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals,
+ poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals,
);
final minTickPrice = tickToPrice(
tick: V3V4PoolConstants.minTick,
- poolToken0Decimals: _cubit.selectedYield!.token0.decimals,
- poolToken1Decimals: _cubit.selectedYield!.token1.decimals,
+ poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals,
+ poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals,
);
double getMinPrice() {
@@ -242,7 +246,7 @@ class _DepositPageState extends State
getMinPrice(),
getMaxPrice(),
).toString())
- .toString();
+ ?.toStringAsFixed(quoteToken.decimals[_cubit.selectedYield!.network.chainId]!);
final newBaseTokenAmount = Decimal.tryParse(calculateToken0AmountFromToken1(
double.tryParse(quoteTokenAmountController.text) ?? 0,
@@ -250,17 +254,17 @@ class _DepositPageState extends State
getMinPrice(),
getMaxPrice(),
).toString())
- .toString();
+ ?.toStringAsFixed(baseToken.decimals[_cubit.selectedYield!.network.chainId]!);
if (isBaseTokenAmountUserInput) {
- if (newQuoteTokenAmount.isEmptyOrZero) return quoteTokenAmountController.clear();
- quoteTokenAmountController.text = newQuoteTokenAmount;
+ if (newQuoteTokenAmount?.isEmptyOrZero ?? true) return quoteTokenAmountController.clear();
+ quoteTokenAmountController.text = newQuoteTokenAmount!;
return;
}
- if (newBaseTokenAmount.isEmptyOrZero) return baseTokenAmountController.clear();
- baseTokenAmountController.text = newBaseTokenAmount;
+ if (newBaseTokenAmount?.isEmptyOrZero ?? true) return baseTokenAmountController.clear();
+ baseTokenAmountController.text = newBaseTokenAmount!;
}
Future<({String title, Widget? icon, Function()? onPressed})> depositButtonState() async {
@@ -319,14 +323,8 @@ class _DepositPageState extends State
maxSlippage: selectedSlippage,
currentYield: _cubit.selectedYield!,
isReversed: areTokensReversed,
- token0DepositAmount: double.tryParse(
- areTokensReversed ? quoteTokenAmountController.text : baseTokenAmountController.text,
- ) ??
- 0,
- token1DepositAmount: double.tryParse(
- areTokensReversed ? baseTokenAmountController.text : quoteTokenAmountController.text,
- ) ??
- 0,
+ token0DepositAmountController: areTokensReversed ? quoteTokenAmountController : baseTokenAmountController,
+ token1DepositAmountController: areTokensReversed ? baseTokenAmountController : quoteTokenAmountController,
maxPrice: (isInfinity: isMaxRangeInfinity, price: maxPrice),
minPrice: (isInfinity: isMinRangeInfinity, price: minPrice),
).show(
@@ -354,6 +352,14 @@ class _DepositPageState extends State
_cubit.getBestPools(token0AddressOrId: token0Address, token1AddressOrId: token1Address);
});
+ _poolTickStreamSubscription = _cubit.poolTickStream.listen((poolTick) {
+ if (poolTick != null) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ setState(() => calculateDepositTokensAmount());
+ });
+ }
+ });
+
super.initState();
}
@@ -361,6 +367,7 @@ class _DepositPageState extends State
void dispose() {
minRangeController.dispose();
maxRangeController.dispose();
+ _poolTickStreamSubscription?.cancel();
super.dispose();
}
@@ -372,9 +379,7 @@ class _DepositPageState extends State
builder: (context, state) {
return state.maybeWhen(
orElse: () => _buildLoadingState(),
- noYields: (minLiquiditySearchedUSD) => _buildNoYieldsState(
- minLiquiditySearchedUSD: minLiquiditySearchedUSD,
- ),
+ noYields: (filtersApplied) => _buildNoYieldsState(filtersApplied: filtersApplied),
error: () => _buildErrorState(),
success: (yields) => StreamBuilder(
stream: _cubit.selectedYieldStream,
@@ -407,9 +412,9 @@ class _DepositPageState extends State
valuePercent: selectedSlippage.value.formatPercent,
)
: null,
- onPressed: (buttonContext) => ZupDropdown.show(
- offset: const Offset(0, 100),
- showBelowContext: buttonContext,
+ onPressed: (buttonContext) => ZupPopover.show(
+ adjustment: const Offset(0, 10),
+ showBasedOnContext: buttonContext,
child: DepositSettingsDropdownChild(
context,
selectedDeadline: selectedDeadline,
@@ -455,7 +460,7 @@ class _DepositPageState extends State
Widget _sectionTitle(String title) => Text(title, style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600));
- Widget _buildNoYieldsState({required num minLiquiditySearchedUSD}) => Center(
+ Widget _buildNoYieldsState({required PoolSearchFiltersDto filtersApplied}) => Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
@@ -470,11 +475,11 @@ class _DepositPageState extends State
description: S.of(context).depositPageEmptyStateDescription,
helpButtonTitle: S.of(context).depositPageEmptyStateHelpButtonTitle,
helpButtonIcon: Assets.icons.arrowLeft.svg(),
- onHelpButtonTap: () => _navigator.back(context),
+ onHelpButtonTap: () => _navigator.navigateToNewPosition(),
),
),
const SizedBox(height: 60),
- if (minLiquiditySearchedUSD > 0)
+ if (filtersApplied.minTvlUsd > 0)
Text.rich(
TextSpan(
children: [
@@ -517,7 +522,7 @@ class _DepositPageState extends State
)
],
),
- )
+ ),
],
),
);
@@ -652,7 +657,7 @@ class _DepositPageState extends State
Flexible(
fit: FlexFit.loose,
child: Text(
- yields.minLiquidityUSD > 0
+ yields.filters.minTvlUsd > 0
? "${S.of(context).depositPageShowingOnlyPoolsWithMoreThan(minLiquidity: NumberFormat.compactSimpleCurrency().format(_cubit.poolSearchSettings.minLiquidityUSD))} "
: "${S.of(context).depositPageShowingAllPools} ",
style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 14, color: ZupColors.gray),
@@ -667,13 +672,13 @@ class _DepositPageState extends State
onPressed: () => _cubit.getBestPools(
token0AddressOrId: token0Address,
token1AddressOrId: token1Address,
- ignoreMinLiquidity: yields.minLiquidityUSD > 0,
+ ignoreMinLiquidity: yields.filters.minTvlUsd > 0,
),
style: ButtonStyle(
padding: WidgetStateProperty.all(const EdgeInsets.all(6)),
),
child: Text(
- yields.minLiquidityUSD > 0
+ yields.filters.minTvlUsd > 0
? S.of(context).depositPageSearchAllPools
: S.of(context).depositPageSearchOnlyForPoolsWithMorethan(
minLiquidity: NumberFormat.compactSimpleCurrency()
@@ -757,8 +762,8 @@ class _DepositPageState extends State
"1 ${baseToken.symbol} ≈ ${() {
final currentPrice = tickToPrice(
tick: poolTickSnapshot.data ?? BigInt.zero,
- poolToken0Decimals: _cubit.selectedYield!.token0.decimals,
- poolToken1Decimals: _cubit.selectedYield!.token1.decimals,
+ poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals,
+ poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals,
);
return areTokensReversed ? currentPrice.priceAsQuoteToken : currentPrice.priceAsBaseToken;
@@ -775,14 +780,14 @@ class _DepositPageState extends State
children: [
ZupMiniButton(
key: const Key("full-range-button"),
- onPressed: () => setFullRange(),
+ onPressed: (_) => setFullRange(),
isSelected: isMaxRangeInfinity && isMinRangeInfinity,
title: S.of(context).depositPageRangeSectionFullRange,
icon: Assets.icons.circleDotted.svg(),
),
ZupMiniButton(
key: const Key("5-percent-range-button"),
- onPressed: () => setPercentageRange(5),
+ onPressed: (_) => setPercentageRange(5),
isSelected: percentRange == 5,
title: "5%",
icon: Assets.icons.plusminus.svg(),
@@ -790,7 +795,7 @@ class _DepositPageState extends State
),
ZupMiniButton(
key: const Key("20-percent-range-button"),
- onPressed: () => setPercentageRange(20),
+ onPressed: (_) => setPercentageRange(20),
isSelected: percentRange == 20,
title: "20%",
icon: Assets.icons.plusminus.svg(),
@@ -798,7 +803,7 @@ class _DepositPageState extends State
),
ZupMiniButton(
key: const Key("50-percent-range-button"),
- onPressed: () => setPercentageRange(50),
+ onPressed: (_) => setPercentageRange(50),
isSelected: percentRange == 50,
title: "50%",
icon: Assets.icons.plusminus.svg(),
@@ -827,8 +832,8 @@ class _DepositPageState extends State
});
},
initialPrice: minPrice,
- poolToken0: _cubit.selectedYield!.token0,
- poolToken1: _cubit.selectedYield!.token1,
+ poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals,
+ poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals,
isReversed: areTokensReversed,
displayBaseTokenSymbol: baseToken.symbol,
displayQuoteTokenSymbol: quoteToken.symbol,
@@ -874,8 +879,8 @@ class _DepositPageState extends State
type: RangeSelectorType.maxPrice,
isInfinity: isMaxRangeInfinity,
initialPrice: maxPrice,
- poolToken0: _cubit.selectedYield!.token0,
- poolToken1: _cubit.selectedYield!.token1,
+ poolToken0Decimals: _cubit.selectedYield!.token0NetworkDecimals,
+ poolToken1Decimals: _cubit.selectedYield!.token1NetworkDecimals,
isReversed: areTokensReversed,
tickSpacing: _cubit.selectedYield!.tickSpacing,
rangeController: maxRangeController,
@@ -909,116 +914,119 @@ 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) {
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- _sectionTitle(S.of(context).depositPageDepositSectionTitle),
- const SizedBox(height: 12),
- TokenAmountInputCard(
- key: const Key("base-token-input-card"),
- token: baseToken,
- isNative: baseToken.addresses[_cubit.selectedYield!.network.chainId]!.lowercasedEquals(
- EthereumConstants.zeroAddress,
- ),
- onRefreshBalance: () => setState(() {}),
- disabledText: () {
- if (!isBaseTokenNeeded) {
- return S.of(context).depositPageDepositSectionTokenNotNeeded(tokenSymbol: baseToken.symbol);
- }
-
- if (!isBaseTokenAmountUserInput &&
- !poolTickSnapshot.hasData &&
- quoteTokenAmountController.text.isNotEmpty) {
- return S.of(context).loading;
- }
- }.call(),
- onInput: (amount) {
- setState(() {
- isBaseTokenAmountUserInput = true;
-
- calculateDepositTokensAmount();
- });
- },
- controller: baseTokenAmountController,
- network: _cubit.selectedYield!.network,
+ stream: _cubit.poolTickStream,
+ initialData: _cubit.latestPoolTick,
+ builder: (context, poolTickSnapshot) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ _sectionTitle(S.of(context).depositPageDepositSectionTitle),
+ const SizedBox(height: 12),
+ TokenAmountInputCard(
+ key: const Key("base-token-input-card"),
+ token: baseToken,
+ isNative: baseToken.addresses[_cubit.selectedYield!.network.chainId]!.lowercasedEquals(
+ EthereumConstants.zeroAddress,
),
- const SizedBox(height: 6),
- TokenAmountInputCard(
- key: const Key("quote-token-input-card"),
- token: quoteToken,
- isNative: quoteToken.addresses[_cubit.selectedYield!.network.chainId]!.lowercasedEquals(
- EthereumConstants.zeroAddress,
- ),
- onRefreshBalance: () => setState(() {}),
- disabledText: () {
- if (!isQuoteTokenNeeded) {
- return S.of(context).depositPageDepositSectionTokenNotNeeded(tokenSymbol: quoteToken.symbol);
- }
-
- if (isBaseTokenAmountUserInput &&
- !poolTickSnapshot.hasData &&
- baseTokenAmountController.text.isNotEmpty) {
- return S.of(context).loading;
- }
- }.call(),
- onInput: (amount) {
- setState(() {
- isBaseTokenAmountUserInput = false;
-
- calculateDepositTokensAmount();
- });
- },
- controller: quoteTokenAmountController,
- network: _cubit.selectedYield!.network,
+ onRefreshBalance: () => setState(() {}),
+ disabledText: () {
+ if (!isBaseTokenNeeded) {
+ return S.of(context).depositPageDepositSectionTokenNotNeeded(tokenSymbol: baseToken.symbol);
+ }
+
+ if (!isBaseTokenAmountUserInput &&
+ !poolTickSnapshot.hasData &&
+ quoteTokenAmountController.text.isNotEmpty) {
+ return S.of(context).loading;
+ }
+ }.call(),
+ onInput: (amount) {
+ setState(() {
+ isBaseTokenAmountUserInput = true;
+
+ calculateDepositTokensAmount();
+ });
+ },
+ controller: baseTokenAmountController,
+ network: _cubit.selectedYield!.network,
+ ),
+ const SizedBox(height: 6),
+ TokenAmountInputCard(
+ key: const Key("quote-token-input-card"),
+ token: quoteToken,
+ isNative: quoteToken.addresses[_cubit.selectedYield!.network.chainId]!.lowercasedEquals(
+ EthereumConstants.zeroAddress,
),
- const SizedBox(height: 20),
- Row(
- children: [
- Expanded(
- child: StreamBuilder(
- key: const Key("deposit-button"),
- stream: wallet.signerStream,
- initialData: wallet.signer,
- builder: (context, signerSnapshot) {
- if (!signerSnapshot.hasData) {
+ onRefreshBalance: () => setState(() {}),
+ disabledText: () {
+ if (!isQuoteTokenNeeded) {
+ return S.of(context).depositPageDepositSectionTokenNotNeeded(tokenSymbol: quoteToken.symbol);
+ }
+
+ if (isBaseTokenAmountUserInput &&
+ !poolTickSnapshot.hasData &&
+ baseTokenAmountController.text.isNotEmpty) {
+ return S.of(context).loading;
+ }
+ }.call(),
+ onInput: (amount) {
+ setState(() {
+ isBaseTokenAmountUserInput = false;
+
+ calculateDepositTokensAmount();
+ });
+ },
+ controller: quoteTokenAmountController,
+ network: _cubit.selectedYield!.network,
+ ),
+ const SizedBox(height: 20),
+ Row(
+ children: [
+ Expanded(
+ child: StreamBuilder(
+ key: const Key("deposit-button"),
+ stream: wallet.signerStream,
+ initialData: wallet.signer,
+ builder: (context, signerSnapshot) {
+ if (!signerSnapshot.hasData) {
+ return ZupPrimaryButton(
+ width: double.maxFinite,
+ title: S.of(context).connectWallet,
+ icon: Assets.icons.walletBifold.svg(),
+ fixedIcon: true,
+ alignCenter: true,
+ hoverElevation: 0,
+ backgroundColor: ZupColors.brand7,
+ foregroundColor: ZupColors.brand,
+ onPressed: (buttonContext) => ConnectModal().show(context),
+ );
+ }
+
+ return FutureBuilder(
+ future: depositButtonState(),
+ builder: (context, stateSnapshot) {
return ZupPrimaryButton(
- width: double.maxFinite,
- title: S.of(context).connectWallet,
- icon: Assets.icons.walletBifold.svg(),
- fixedIcon: true,
alignCenter: true,
- hoverElevation: 0,
- backgroundColor: ZupColors.brand7,
- foregroundColor: ZupColors.brand,
- onPressed: () => ConnectModal().show(context),
+ title: stateSnapshot.data?.title ?? "Loading...",
+ icon: stateSnapshot.data?.icon,
+ isLoading: stateSnapshot.connectionState == ConnectionState.waiting,
+ fixedIcon: true,
+ onPressed: stateSnapshot.data?.onPressed == null
+ ? null
+ : (buttonContext) => stateSnapshot.data?.onPressed!(),
+ width: double.maxFinite,
);
- }
-
- return FutureBuilder(
- future: depositButtonState(),
- builder: (context, stateSnapshot) {
- return ZupPrimaryButton(
- alignCenter: true,
- title: stateSnapshot.data?.title ?? "Loading...",
- icon: stateSnapshot.data?.icon,
- isLoading: stateSnapshot.connectionState == ConnectionState.waiting,
- fixedIcon: true,
- onPressed: stateSnapshot.data?.onPressed,
- width: double.maxFinite,
- );
- },
- );
- },
- ),
+ },
+ );
+ },
),
- ],
- ),
- ],
- );
- }),
+ ),
+ ],
+ ),
+ ],
+ );
+ },
+ ),
),
);
}
diff --git a/lib/app/create/deposit/deposit_state.dart b/lib/app/create/deposit/deposit_state.dart
index 31420d0..38dfa3e 100644
--- a/lib/app/create/deposit/deposit_state.dart
+++ b/lib/app/create/deposit/deposit_state.dart
@@ -6,5 +6,5 @@ class DepositState with _$DepositState {
const factory DepositState.loading() = _Loading;
const factory DepositState.success(YieldsDto yields) = _Success;
const factory DepositState.error() = _Error;
- const factory DepositState.noYields({required num minLiquiditySearched}) = _NoYields;
+ const factory DepositState.noYields({required PoolSearchFiltersDto filtersApplied}) = _NoYields;
}
diff --git a/lib/app/create/deposit/widgets/deposit_success_modal.dart b/lib/app/create/deposit/widgets/deposit_success_modal.dart
index 7cb5396..655a5e2 100644
--- a/lib/app/create/deposit/widgets/deposit_success_modal.dart
+++ b/lib/app/create/deposit/widgets/deposit_success_modal.dart
@@ -122,7 +122,7 @@ class _DepositSuccessModalState extends State {
ZupPrimaryButton(
key: const Key("view-position-button"),
title: S.of(context).depositSuccessModalViewPositionOnDEX(dexName: widget.depositedYield.protocol.name),
- onPressed: () => launchUrl(Uri.parse(widget.depositedYield.protocol.url)),
+ onPressed: (buttonContext) => launchUrl(Uri.parse(widget.depositedYield.protocol.url)),
fontWeight: FontWeight.w500,
icon: Assets.icons.arrowUpRight.svg(),
backgroundColor: Colors.transparent,
@@ -135,7 +135,7 @@ class _DepositSuccessModalState extends State {
key: const Key("close-button"),
title: S.of(context).close,
width: double.infinity,
- onPressed: () => Navigator.of(context).pop(),
+ onPressed: (buttonContext) => Navigator.of(context).pop(),
),
],
);
diff --git a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart
index fca2d4b..dacf233 100644
--- a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart
+++ b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart
@@ -24,6 +24,7 @@ import 'package:zup_app/gen/assets.gen.dart';
import 'package:zup_app/l10n/gen/app_localizations.dart';
import 'package:zup_app/widgets/token_avatar.dart';
import 'package:zup_app/widgets/zup_cached_image.dart';
+import 'package:zup_core/extensions/text_edititing_controller_extension.dart';
import 'package:zup_core/zup_core.dart';
import 'package:zup_ui_kit/zup_ui_kit.dart';
@@ -34,8 +35,8 @@ class PreviewDepositModal extends StatefulWidget with DeviceInfoMixin {
required this.isReversed,
required this.minPrice,
required this.maxPrice,
- required this.token0DepositAmount,
- required this.token1DepositAmount,
+ required this.token0DepositAmountController,
+ required this.token1DepositAmountController,
required this.deadline,
required this.maxSlippage,
required this.yieldTimeFrame,
@@ -46,8 +47,8 @@ class PreviewDepositModal extends StatefulWidget with DeviceInfoMixin {
final bool isReversed;
final ({double price, bool isInfinity}) minPrice;
final ({double price, bool isInfinity}) maxPrice;
- final double token0DepositAmount;
- final double token1DepositAmount;
+ final TextEditingController token0DepositAmountController;
+ final TextEditingController token1DepositAmountController;
final Duration deadline;
final Slippage maxSlippage;
@@ -75,8 +76,8 @@ class PreviewDepositModal extends StatefulWidget with DeviceInfoMixin {
child: PreviewDepositModal(
deadline: deadline,
maxSlippage: maxSlippage,
- token0DepositAmount: token0DepositAmount,
- token1DepositAmount: token1DepositAmount,
+ token0DepositAmountController: token0DepositAmountController,
+ token1DepositAmountController: token1DepositAmountController,
minPrice: minPrice,
maxPrice: maxPrice,
currentYield: currentYield,
@@ -100,6 +101,10 @@ class _PreviewDepositModalState extends State with V3PoolCo
instanceName: InjectInstanceNames.appScrollController,
);
+ late VoidCallback tokenDepositAmountChangeAction = () {
+ WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {}));
+ };
+
TokenDto get baseToken {
if (isReversedLocal) {
return widget.currentYield.token1;
@@ -116,21 +121,29 @@ class _PreviewDepositModalState extends State with V3PoolCo
return widget.currentYield.token1;
}
- double get baseTokenAmount => isReversedLocal ? widget.token1DepositAmount : widget.token0DepositAmount;
- double get quoteTokenAmount => isReversedLocal ? widget.token0DepositAmount : widget.token1DepositAmount;
PreviewDepositModalCubit get cubit => context.read();
- BigInt get token0DepositAmount =>
- widget.token0DepositAmount.parseTokenAmount(decimals: widget.currentYield.token0.decimals);
- BigInt get token1DepositAmount =>
- widget.token1DepositAmount.parseTokenAmount(decimals: widget.currentYield.token1.decimals);
+
+ double get baseTokenAmount => isReversedLocal
+ ? widget.token1DepositAmountController.parseTextToDouble
+ : widget.token0DepositAmountController.parseTextToDouble;
+
+ double get quoteTokenAmount => isReversedLocal
+ ? widget.token0DepositAmountController.parseTextToDouble
+ : widget.token1DepositAmountController.parseTextToDouble;
+
+ BigInt get token0DepositAmount => widget.token0DepositAmountController.parseTextToDouble
+ .parseTokenAmount(decimals: widget.currentYield.token0NetworkDecimals);
+
+ BigInt get token1DepositAmount => widget.token1DepositAmountController.parseTextToDouble
+ .parseTokenAmount(decimals: widget.currentYield.token1NetworkDecimals);
double get currentPrice {
final currentTick = cubit.latestPoolTick;
final price = tickToPrice(
tick: currentTick,
- poolToken0Decimals: widget.currentYield.token0.decimals,
- poolToken1Decimals: widget.currentYield.token1.decimals,
+ poolToken0Decimals: widget.currentYield.token0NetworkDecimals,
+ poolToken1Decimals: widget.currentYield.token1NetworkDecimals,
);
return isReversedLocal ? price.priceAsQuoteToken : price.priceAsBaseToken;
@@ -142,16 +155,16 @@ class _PreviewDepositModalState extends State with V3PoolCo
return priceToTick(
price: (widget.isReversed == !isReversedLocal) ? widget.maxPrice.price : widget.minPrice.price,
- poolToken0Decimals: widget.currentYield.token0.decimals,
- poolToken1Decimals: widget.currentYield.token1.decimals,
+ poolToken0Decimals: widget.currentYield.token0NetworkDecimals,
+ poolToken1Decimals: widget.currentYield.token1NetworkDecimals,
isReversed: widget.isReversed,
);
}
({double priceAsBaseToken, double priceAsQuoteToken}) price() => tickToPrice(
tick: tick(),
- poolToken0Decimals: widget.currentYield.token0.decimals,
- poolToken1Decimals: widget.currentYield.token1.decimals,
+ poolToken0Decimals: widget.currentYield.token0NetworkDecimals,
+ poolToken1Decimals: widget.currentYield.token1NetworkDecimals,
);
return isReversedLocal ? price().priceAsQuoteToken : price().priceAsBaseToken;
@@ -163,16 +176,16 @@ class _PreviewDepositModalState extends State with V3PoolCo
return priceToTick(
price: (widget.isReversed == !isReversedLocal) ? widget.minPrice.price : widget.maxPrice.price,
- poolToken0Decimals: widget.currentYield.token0.decimals,
- poolToken1Decimals: widget.currentYield.token1.decimals,
+ poolToken0Decimals: widget.currentYield.token0NetworkDecimals,
+ poolToken1Decimals: widget.currentYield.token1NetworkDecimals,
isReversed: widget.isReversed,
);
}
({double priceAsBaseToken, double priceAsQuoteToken}) price() => tickToPrice(
tick: tick(),
- poolToken0Decimals: widget.currentYield.token0.decimals,
- poolToken1Decimals: widget.currentYield.token1.decimals,
+ poolToken0Decimals: widget.currentYield.token0NetworkDecimals,
+ poolToken1Decimals: widget.currentYield.token1NetworkDecimals,
);
return isReversedLocal ? price().priceAsQuoteToken : price().priceAsBaseToken;
@@ -316,9 +329,21 @@ class _PreviewDepositModalState extends State with V3PoolCo
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) => cubit.setup());
+
+ widget.token0DepositAmountController.addListener(tokenDepositAmountChangeAction);
+ widget.token1DepositAmountController.addListener(tokenDepositAmountChangeAction);
+
super.initState();
}
+ @override
+ void dispose() {
+ widget.token0DepositAmountController.removeListener(tokenDepositAmountChangeAction);
+ widget.token1DepositAmountController.removeListener(tokenDepositAmountChangeAction);
+
+ super.dispose();
+ }
+
@override
Widget build(BuildContext context) {
return BlocConsumer(
@@ -492,7 +517,7 @@ class _PreviewDepositModalState extends State with V3PoolCo
Text(
"${baseTokenAmount.maybeFormatCompactCurrency(
isUSD: false,
- useLessThan: true,
+ useLessThan: false,
useMoreThan: true,
)} ${baseToken.symbol}",
style: const TextStyle(fontWeight: FontWeight.w500)),
@@ -519,7 +544,7 @@ class _PreviewDepositModalState extends State with V3PoolCo
Text(
"${quoteTokenAmount.maybeFormatCompactCurrency(
isUSD: false,
- useLessThan: true,
+ useLessThan: false,
useMoreThan: true,
)} ${quoteToken.symbol}",
style: const TextStyle(fontWeight: FontWeight.w500)),
@@ -580,7 +605,9 @@ class _PreviewDepositModalState extends State with V3PoolCo
fixedIcon: true,
alignCenter: true,
title: depositButtonState.title,
- onPressed: depositButtonState.onPressed,
+ onPressed: depositButtonState.onPressed == null
+ ? null
+ : (buttonContext) => depositButtonState.onPressed!(),
icon: depositButtonState.icon,
isLoading: depositButtonState.isLoading ?? false,
width: double.maxFinite,
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 e537ec9..6836217 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
@@ -129,6 +129,8 @@ class PreviewDepositModalCubit extends Cubit with V3Po
Future checkOrApprovePermit2ForV4Pool(BigInt approveValue, TokenDto token) async {
final tokenAddressInNetwork = token.addresses[_yield.network.chainId]!;
+ if (tokenAddressInNetwork == EthereumConstants.zeroAddress) return;
+
final permit2Contract = _permit2.fromSigner(
contractAddress: _yield.permit2!,
signer: _wallet.signer!,
@@ -175,8 +177,8 @@ class PreviewDepositModalCubit extends Cubit with V3Po
return priceToTick(
price: isReversed ? maxPrice : minPrice,
- poolToken0Decimals: _yield.token0.decimals,
- poolToken1Decimals: _yield.token1.decimals,
+ poolToken0Decimals: _yield.token0NetworkDecimals,
+ poolToken1Decimals: _yield.token1NetworkDecimals,
isReversed: isReversed,
);
}
@@ -194,8 +196,8 @@ class PreviewDepositModalCubit extends Cubit with V3Po
return priceToTick(
price: isReversed ? minPrice : maxPrice,
- poolToken0Decimals: _yield.token0.decimals,
- poolToken1Decimals: _yield.token1.decimals,
+ poolToken0Decimals: _yield.token0NetworkDecimals,
+ poolToken1Decimals: _yield.token1NetworkDecimals,
isReversed: isReversed,
);
}
@@ -242,7 +244,6 @@ class PreviewDepositModalCubit extends Cubit with V3Po
maxAmount0ToDeposit: slippage.calculateMaxTokenAmountFromSlippage(amount0Desired),
maxAmount1ToDeposit: slippage.calculateMaxTokenAmountFromSlippage(amount1Desired),
recipient: recipient,
- currentPoolTick: _latestPoolTick,
);
}.call();
@@ -253,8 +254,8 @@ class PreviewDepositModalCubit extends Cubit with V3Po
emit(PreviewDepositModalState.depositSuccess(txId: tx.hash));
_zupAnalytics.logDeposit(
depositedYield: _yield,
- amount0Formatted: amount0Desired.parseTokenAmount(decimals: _yield.token0.decimals),
- amount1Formatted: amount1Desired.parseTokenAmount(decimals: _yield.token1.decimals),
+ amount0Formatted: amount0Desired.parseTokenAmount(decimals: _yield.token0NetworkDecimals),
+ amount1Formatted: amount1Desired.parseTokenAmount(decimals: _yield.token1NetworkDecimals),
walletAddress: recipient,
);
} catch (e) {
@@ -322,15 +323,15 @@ class PreviewDepositModalCubit extends Cubit with V3Po
}
}
- void _updateTick() {
+ Future _updateTick() async {
try {
- _poolRepository.getPoolTick(_yield).then((tick) {
- _latestPoolTick = tick;
- _poolTickStreamController.add(tick);
- });
+ _latestPoolTick = await _poolRepository.getPoolTick(_yield);
+ _poolTickStreamController.add(_latestPoolTick);
} catch (_) {
// DO NOTHING
}
+
+ return _latestPoolTick;
}
void _waitTransactionFinishBeforeClosing() {
diff --git a/lib/app/create/deposit/widgets/range_selector.dart b/lib/app/create/deposit/widgets/range_selector.dart
index 9f25473..a797454 100644
--- a/lib/app/create/deposit/widgets/range_selector.dart
+++ b/lib/app/create/deposit/widgets/range_selector.dart
@@ -1,6 +1,5 @@
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
-import 'package:zup_app/core/dtos/token_dto.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';
@@ -55,8 +54,8 @@ class RangeController extends ChangeNotifier {
class RangeSelector extends StatefulWidget {
const RangeSelector({
super.key,
- required this.poolToken0,
- required this.poolToken1,
+ required this.poolToken0Decimals,
+ required this.poolToken1Decimals,
required this.displayBaseTokenSymbol,
required this.displayQuoteTokenSymbol,
required this.isReversed,
@@ -70,8 +69,8 @@ class RangeSelector extends StatefulWidget {
this.state = const RangeSelectorState(type: RangeSelectorStateType.regular),
});
- final TokenDto poolToken0;
- final TokenDto poolToken1;
+ final int poolToken0Decimals;
+ final int poolToken1Decimals;
final String displayBaseTokenSymbol;
final String displayQuoteTokenSymbol;
final bool isReversed;
@@ -116,8 +115,8 @@ class _RangeSelectorState extends State with V3PoolConversorsMixi
double getAdjustedPrice(double price) {
final adjustedPrice = priceToClosestValidPrice(
price: price,
- poolToken0Decimals: widget.poolToken0.decimals,
- poolToken1Decimals: widget.poolToken1.decimals,
+ poolToken0Decimals: widget.poolToken0Decimals,
+ poolToken1Decimals: widget.poolToken1Decimals,
tickSpacing: widget.tickSpacing,
isReversed: widget.isReversed,
);
@@ -131,13 +130,16 @@ class _RangeSelectorState extends State with V3PoolConversorsMixi
if (currentPrice == 0 && !increasing) return;
if ((currentPrice == 0 || widget.isInfinity) && increasing) {
- final minimumPrice = tickToPrice(
- tick: BigInt.from(widget.tickSpacing),
- poolToken0Decimals: widget.poolToken0.decimals,
- poolToken1Decimals: widget.poolToken1.decimals,
+ final minimumPrice = priceToClosestValidPrice(
+ price: 0.000000000000000001,
+ poolToken0Decimals: widget.poolToken0Decimals,
+ poolToken1Decimals: widget.poolToken1Decimals,
+ tickSpacing: widget.tickSpacing,
+ isReversed: widget.isReversed,
);
- userTypedValue = minimumPrice.priceAsBaseToken.toString();
+ userTypedValue = minimumPrice.price.toString();
+
return adjustTypedAmountAndCallback();
}
@@ -145,8 +147,8 @@ class _RangeSelectorState extends State with V3PoolConversorsMixi
final BigInt currentTick = tickToClosestValidTick(
tick: priceToTick(
price: currentPrice,
- poolToken0Decimals: widget.poolToken0.decimals,
- poolToken1Decimals: widget.poolToken1.decimals,
+ poolToken0Decimals: widget.poolToken0Decimals,
+ poolToken1Decimals: widget.poolToken1Decimals,
isReversed: widget.isReversed,
),
tickSpacing: widget.tickSpacing,
@@ -163,8 +165,8 @@ class _RangeSelectorState extends State with V3PoolConversorsMixi
double nextPrice() {
final nextPrice = tickToPrice(
tick: nextTick(),
- poolToken0Decimals: widget.poolToken0.decimals,
- poolToken1Decimals: widget.poolToken1.decimals,
+ poolToken0Decimals: widget.poolToken0Decimals,
+ poolToken1Decimals: widget.poolToken1Decimals,
);
if (widget.isReversed) return nextPrice.priceAsQuoteToken;
@@ -179,8 +181,8 @@ class _RangeSelectorState extends State with V3PoolConversorsMixi
if (widget.initialPrice != null) {
final adjustedInitialPrice = priceToClosestValidPrice(
price: widget.initialPrice ?? 0,
- poolToken0Decimals: widget.poolToken0.decimals,
- poolToken1Decimals: widget.poolToken1.decimals,
+ poolToken0Decimals: widget.poolToken0Decimals,
+ poolToken1Decimals: widget.poolToken1Decimals,
tickSpacing: widget.tickSpacing,
isReversed: widget.isReversed,
);
diff --git a/lib/app/create/widgets/create_page_settings_dropdown.dart b/lib/app/create/widgets/create_page_settings_dropdown/create_page_settings_dropdown.dart
similarity index 93%
rename from lib/app/create/widgets/create_page_settings_dropdown.dart
rename to lib/app/create/widgets/create_page_settings_dropdown/create_page_settings_dropdown.dart
index 8692fc7..b79e67a 100644
--- a/lib/app/create/widgets/create_page_settings_dropdown.dart
+++ b/lib/app/create/widgets/create_page_settings_dropdown/create_page_settings_dropdown.dart
@@ -18,9 +18,9 @@ class CreatePageSettingsDropdown extends StatefulWidget {
BuildContext showBelowContext, {
required void Function() onClose,
}) =>
- ZupDropdown.show(
- showBelowContext: showBelowContext,
- offset: const Offset(0, 90),
+ ZupPopover.show(
+ showBasedOnContext: showBelowContext,
+ adjustment: const Offset(0, 10),
child: CreatePageSettingsDropdown(onClose: onClose),
);
@@ -47,6 +47,14 @@ class _CreatePageSettingsDropdownState extends State
}
}
+ Widget sectionTitle(String title) => Text(
+ title,
+ style: const TextStyle(
+ fontWeight: FontWeight.w600,
+ fontSize: 15,
+ ),
+ );
+
@override
void initState() {
minTVLController.text = cache.getPoolSearchSettings().minLiquidityUSD.formatCurrency(isUSD: false);
@@ -69,9 +77,7 @@ class _CreatePageSettingsDropdownState extends State
decoration: BoxDecoration(
color: ZupColors.white,
borderRadius: BorderRadius.circular(12),
- border: Border.all(
- color: ZupColors.gray5,
- ),
+ border: Border.all(color: ZupColors.gray5),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -80,10 +86,7 @@ class _CreatePageSettingsDropdownState extends State
Row(
mainAxisSize: MainAxisSize.min,
children: [
- Text(
- S.of(context).createPageSettingsDropdownMinimumLiquidity,
- style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 15),
- ),
+ sectionTitle(S.of(context).createPageSettingsDropdownMinimumLiquidity),
const SizedBox(width: 8),
ZupTooltip(
key: const Key("min-liquidity-tooltip"),
@@ -165,10 +168,7 @@ class _CreatePageSettingsDropdownState extends State
const SizedBox(height: 10),
Row(
children: [
- Text(
- S.of(context).createPageSettingsDropdownAllowedPoolTypes,
- style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 15),
- ),
+ sectionTitle(S.of(context).createPageSettingsDropdownAllowedPoolTypes),
const SizedBox(width: 8),
ZupTooltip(
key: const Key("pool-types-allowed-tooltip"),
diff --git a/lib/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button.dart b/lib/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button.dart
new file mode 100644
index 0000000..0092138
--- /dev/null
+++ b/lib/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button.dart
@@ -0,0 +1,139 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:zup_app/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_cubit.dart';
+import 'package:zup_app/core/cache.dart';
+import 'package:zup_app/core/injections.dart';
+import 'package:zup_app/core/repositories/protocol_repository.dart';
+import 'package:zup_app/gen/assets.gen.dart';
+import 'package:zup_app/l10n/gen/app_localizations.dart';
+import 'package:zup_app/widgets/zup_cached_image.dart';
+import 'package:zup_core/zup_singleton_cache.dart';
+import 'package:zup_ui_kit/zup_ui_kit.dart';
+
+class ExchangesFilterDropdownButton extends StatefulWidget {
+ const ExchangesFilterDropdownButton({super.key});
+
+ @override
+ State createState() => _ExchangesFilterDropdownButtonState();
+}
+
+class _ExchangesFilterDropdownButtonState extends State {
+ final zupSingletonCache = inject();
+ final protocolRepository = inject();
+ final zupCachedImage = inject();
+ final cache = inject();
+
+ ExchangesFilterDropdownButtonCubit? cubit;
+
+ num get allowedProtocolsCount => cubit!.protocols
+ .where(
+ (protocol) => !cache.blockedProtocolsIds.contains(protocol.rawId),
+ )
+ .length;
+
+ Color get buttonForegroundColor {
+ if (allowedProtocolsCount == 0 && cubit!.protocols.isNotEmpty) return ZupColors.red;
+
+ if (allowedProtocolsCount == cubit!.protocols.length) return ZupColors.gray;
+ return ZupColors.brand;
+ }
+
+ String get protocolCounter {
+ if (allowedProtocolsCount == 0) return "0";
+
+ if (allowedProtocolsCount == cubit!.protocols.length) return "${cubit!.protocols.length}";
+
+ return "$allowedProtocolsCount/${cubit!.protocols.length}";
+ }
+
+ @override
+ void initState() {
+ cubit = ExchangesFilterDropdownButtonCubit(protocolRepository, zupSingletonCache);
+
+ WidgetsBinding.instance.addPostFrameCallback((_) => cubit!.getSupportedProtocols());
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocBuilder(
+ bloc: cubit,
+ builder: (context, state) {
+ return ZupPrimaryButton(
+ key: const Key("exchanges-filter-dropdown-button"),
+ backgroundColor: Colors.transparent,
+ foregroundColor: buttonForegroundColor,
+ border: const BorderSide(color: ZupColors.gray4),
+ hoverElevation: 0,
+ icon: Assets.icons.switch2.svg(),
+ title: state.maybeWhen(
+ success: (protocols) => S.of(context).exchangesFilterDropdownButtonTitleNumered(
+ exchangesCount: protocolCounter,
+ ),
+ orElse: () => S.of(context).exchangesFilterDropdownButtonTitle,
+ ),
+ height: 40,
+ isLoading: state.maybeWhen(
+ loading: () => true,
+ orElse: () => false,
+ ),
+ onPressed: state == const ExchangesFilterDropdownButtonState.loading()
+ ? null
+ : (buttonContext) => state.whenOrNull(
+ error: () async {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ ZupSnackBar(
+ context,
+ message: S.of(context).exchangesFilterDropdownButtonErrorSnackBarMessage,
+ type: ZupSnackBarType.error,
+ maxWidth: 400,
+ ),
+ );
+ });
+ return null;
+ },
+ success: (protocols) => ZupCheckboxListPopover.show(
+ buttonContext,
+ positionAdjustment: const Offset(-130, 10),
+ allSelectionButtonText: (
+ clearAll: S.of(context).exchangesFilterDropdownButtonDropdownClearAll,
+ selectAll: S.of(context).exchangesFilterDropdownButtonDropdownSelectAll
+ ),
+ searchHintText: S.of(context).exchangesFilterDropdownButtonDropdownSearchHint,
+ searchNotFoundStateText: (
+ description: S.of(context).exchangesFilterDropdownButtonDropdownNotFoundStateDescription,
+ title: S.of(context).exchangesFilterDropdownButtonDropdownNotFoundStateTitle
+ ),
+ onValueChanged: (items) {
+ setState(
+ () {
+ cache.saveBlockedProtocolIds(
+ blockedProtocolIds: items
+ .where((item) => !item.isChecked)
+ .map(
+ (item) => item.id!,
+ )
+ .toList(),
+ );
+ },
+ );
+ },
+ items: protocols
+ .map(
+ (protocol) => ZupCheckboxItem(
+ id: protocol.rawId,
+ title: protocol.name,
+ icon: zupCachedImage.build(protocol.logo, radius: 50),
+ isChecked: !cache.blockedProtocolsIds.contains(protocol.rawId),
+ isDisabled: false,
+ ),
+ )
+ .toList(),
+ ),
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/lib/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_cubit.dart b/lib/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_cubit.dart
new file mode 100644
index 0000000..86234e7
--- /dev/null
+++ b/lib/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_cubit.dart
@@ -0,0 +1,37 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:zup_app/core/dtos/protocol_dto.dart';
+import 'package:zup_app/core/mixins/keys_mixin.dart';
+import 'package:zup_app/core/repositories/protocol_repository.dart';
+import 'package:zup_core/zup_core.dart';
+
+part 'exchanges_filter_dropdown_button_cubit.freezed.dart';
+part 'exchanges_filter_dropdown_button_state.dart';
+
+class ExchangesFilterDropdownButtonCubit extends Cubit with KeysMixin {
+ ExchangesFilterDropdownButtonCubit(this._protocolRepository, this._zupSingletonCache)
+ : super(const ExchangesFilterDropdownButtonState.initial());
+
+ final ProtocolRepository _protocolRepository;
+ final ZupSingletonCache _zupSingletonCache;
+
+ List _supportedProtocols = [];
+ List get protocols => _supportedProtocols;
+
+ Future getSupportedProtocols() async {
+ try {
+ emit(const ExchangesFilterDropdownButtonState.loading());
+
+ _supportedProtocols = await _zupSingletonCache.run(
+ () async => await _protocolRepository.getAllSupportedProtocols(),
+ key: protocolsListKey,
+ );
+
+ _supportedProtocols.sort((a, b) => a.name.compareTo(b.name));
+
+ emit(ExchangesFilterDropdownButtonState.success(protocols));
+ } catch (e) {
+ emit(const ExchangesFilterDropdownButtonState.error());
+ }
+ }
+}
diff --git a/lib/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_state.dart b/lib/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_state.dart
new file mode 100644
index 0000000..84b15fc
--- /dev/null
+++ b/lib/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_state.dart
@@ -0,0 +1,9 @@
+part of 'exchanges_filter_dropdown_button_cubit.dart';
+
+@freezed
+class ExchangesFilterDropdownButtonState with _$ExchangesFilterDropdownButtonState {
+ const factory ExchangesFilterDropdownButtonState.initial() = _Initial;
+ const factory ExchangesFilterDropdownButtonState.loading() = _Loading;
+ const factory ExchangesFilterDropdownButtonState.error() = _Error;
+ const factory ExchangesFilterDropdownButtonState.success(List protocols) = _Success;
+}
diff --git a/lib/core/cache.dart b/lib/core/cache.dart
index 9b7dce5..cce223b 100644
--- a/lib/core/cache.dart
+++ b/lib/core/cache.dart
@@ -9,6 +9,7 @@ enum CacheKey {
depositSettings,
poolSearchSettings,
areCookiesConsented,
+ blockedProtocolsIds,
isTestnetMode;
String get key => name;
@@ -47,6 +48,14 @@ class Cache {
return _cache.getBool(CacheKey.isTestnetMode.key) ?? false;
}
+ Future saveBlockedProtocolIds({required List blockedProtocolIds}) async {
+ await _cache.setStringList(CacheKey.blockedProtocolsIds.key, blockedProtocolIds);
+ }
+
+ List get blockedProtocolsIds {
+ return _cache.getStringList(CacheKey.blockedProtocolsIds.key) ?? [];
+ }
+
Future savePoolSearchSettings({required PoolSearchSettingsDto settings}) async {
await _cache.setString(CacheKey.poolSearchSettings.key, jsonEncode(settings.toJson()));
}
diff --git a/lib/core/dtos/pool_search_filters_dto.dart b/lib/core/dtos/pool_search_filters_dto.dart
new file mode 100644
index 0000000..4ce4f3d
--- /dev/null
+++ b/lib/core/dtos/pool_search_filters_dto.dart
@@ -0,0 +1,26 @@
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+part 'pool_search_filters_dto.freezed.dart';
+part 'pool_search_filters_dto.g.dart';
+
+@freezed
+class PoolSearchFiltersDto with _$PoolSearchFiltersDto {
+ @JsonSerializable(explicitToJson: true)
+ const factory PoolSearchFiltersDto({
+ @Default(0) num minTvlUsd,
+ @Default(false) bool testnetMode,
+ @Default([]) List allowedPoolTypes,
+ @Default([]) List blockedProtocols,
+ }) = _PoolSearchFiltersDto;
+
+ const PoolSearchFiltersDto._();
+
+ factory PoolSearchFiltersDto.fromJson(Map json) => _$PoolSearchFiltersDtoFromJson(json);
+
+ factory PoolSearchFiltersDto.fixture() => const PoolSearchFiltersDto(
+ allowedPoolTypes: ["V3", "V4"],
+ blockedProtocols: ["nuri-exchange"],
+ minTvlUsd: 121782617,
+ testnetMode: false,
+ );
+}
diff --git a/lib/core/dtos/protocol_dto.dart b/lib/core/dtos/protocol_dto.dart
index 78c7f44..3c23722 100644
--- a/lib/core/dtos/protocol_dto.dart
+++ b/lib/core/dtos/protocol_dto.dart
@@ -1,14 +1,19 @@
import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:zup_app/core/enums/protocol_id.dart';
part 'protocol_dto.freezed.dart';
part 'protocol_dto.g.dart';
+String _readRawProtocolId(Map map, String key) => map['id'];
+
@freezed
class ProtocolDto with _$ProtocolDto {
const ProtocolDto._();
@JsonSerializable(explicitToJson: true)
const factory ProtocolDto({
+ @Default("") @JsonKey(readValue: _readRawProtocolId) String rawId,
+ @Default(ProtocolId.unknown) @JsonKey(unknownEnumValue: ProtocolId.unknown) ProtocolId id,
@Default("") String name,
@Default("") String url,
@Default("") String logo,
@@ -17,6 +22,8 @@ class ProtocolDto with _$ProtocolDto {
factory ProtocolDto.fromJson(Map json) => _$ProtocolDtoFromJson(json);
factory ProtocolDto.fixture() => const ProtocolDto(
+ rawId: "1",
+ id: ProtocolId.unknown,
name: "Uniswap",
url: "https://app.uniswap.org/pool",
logo: "https://raw.githubusercontent.com/trustwallet/assets/master/dapps/app.uniswap.org.png",
diff --git a/lib/core/dtos/token_dto.dart b/lib/core/dtos/token_dto.dart
index e69ddef..2c20e2a 100644
--- a/lib/core/dtos/token_dto.dart
+++ b/lib/core/dtos/token_dto.dart
@@ -13,7 +13,7 @@ class TokenDto with _$TokenDto {
@Default("") String name,
@Default("") String logoUrl,
@Default({}) Map addresses,
- @Default(0) int decimals,
+ @Default({}) Map decimals,
}) = _TokenDto;
factory TokenDto.fromJson(Map json) => _$TokenDtoFromJson(json);
@@ -23,6 +23,13 @@ class TokenDto with _$TokenDto {
factory TokenDto.fixture() => TokenDto(
symbol: 'WETH',
name: 'Wrapped Ether',
+ decimals: Map.fromEntries(
+ AppNetworks.values.where((network) => !network.isAllNetworks).map(
+ (network) {
+ return MapEntry(network.chainId, 18);
+ },
+ ),
+ ),
addresses: Map.fromEntries(
AppNetworks.values.where((network) => !network.isAllNetworks).map(
(network) {
diff --git a/lib/core/dtos/yield_dto.dart b/lib/core/dtos/yield_dto.dart
index 191d414..fb3ef57 100644
--- a/lib/core/dtos/yield_dto.dart
+++ b/lib/core/dtos/yield_dto.dart
@@ -48,7 +48,7 @@ class YieldDto with _$YieldDto {
required num yield30d,
required num yield90d,
required int chainId,
- required PoolType poolType,
+ @Default(PoolType.unknown) @JsonKey(unknownEnumValue: PoolType.unknown) PoolType poolType,
@Default("0") String latestTick,
@Default(0) num totalValueLockedUSD,
@Default(EthereumConstants.zeroAddress) @JsonKey(name: "hooksAddress") String v4Hooks,
@@ -62,6 +62,9 @@ class YieldDto with _$YieldDto {
bool get isToken0Native => token0.addresses[network.chainId] == EthereumConstants.zeroAddress;
bool get isToken1Native => token1.addresses[network.chainId] == EthereumConstants.zeroAddress;
+ int get token0NetworkDecimals => token0.decimals[network.chainId]!;
+ int get token1NetworkDecimals => token1.decimals[network.chainId]!;
+
factory YieldDto.fromJson(Map json) => _$YieldDtoFromJson(json);
factory YieldDto.fixture() => YieldDto(
@@ -75,7 +78,9 @@ class YieldDto with _$YieldDto {
poolType: PoolType.v3,
token0: TokenDto.fixture().copyWith(
symbol: "USDC",
- decimals: 6,
+ decimals: {
+ AppNetworks.sepolia.chainId: 6,
+ },
addresses: {
AppNetworks.sepolia.chainId: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
},
@@ -84,7 +89,9 @@ class YieldDto with _$YieldDto {
),
token1: TokenDto.fixture().copyWith(
symbol: "WETH",
- decimals: 18,
+ decimals: {
+ AppNetworks.sepolia.chainId: 18,
+ },
addresses: {
AppNetworks.sepolia.chainId: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
},
diff --git a/lib/core/dtos/yields_dto.dart b/lib/core/dtos/yields_dto.dart
index 2bda1bc..ac83d41 100644
--- a/lib/core/dtos/yields_dto.dart
+++ b/lib/core/dtos/yields_dto.dart
@@ -1,8 +1,10 @@
import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:zup_app/core/dtos/pool_search_filters_dto.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/pool_type.dart';
+import 'package:zup_app/core/enums/protocol_id.dart';
part 'yields_dto.freezed.dart';
part 'yields_dto.g.dart';
@@ -14,7 +16,7 @@ class YieldsDto with _$YieldsDto {
@JsonSerializable(explicitToJson: true)
const factory YieldsDto({
@Default([]) @JsonKey(name: "pools") List pools,
- @Default(0) @JsonKey(name: "minTvlUsd") num minLiquidityUSD,
+ @Default(PoolSearchFiltersDto()) PoolSearchFiltersDto filters,
}) = _YieldsDto;
bool get isEmpty => pools.isEmpty;
@@ -27,26 +29,26 @@ class YieldsDto with _$YieldsDto {
factory YieldsDto.empty() => const YieldsDto(
pools: [],
- minLiquidityUSD: 0,
);
- factory YieldsDto.fixture() => const YieldsDto(
+ factory YieldsDto.fixture() => YieldsDto(
+ filters: PoolSearchFiltersDto.fixture(),
pools: [
YieldDto(
latestTick: "637812562",
positionManagerAddress: "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4",
poolType: PoolType.v3,
- token0: TokenDto(
+ token0: const TokenDto(
addresses: {11155111: "0x02a3e7E0480B668bD46b42852C58363F93e3bA5C"},
- decimals: 6,
+ decimals: {11155111: 6},
logoUrl:
"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/scroll/assets/0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4/logo.png",
name: "USDC",
symbol: "USDC",
),
- token1: TokenDto(
+ token1: const TokenDto(
addresses: {11155111: "0x5300000000000000000000000000000000000004"},
- decimals: 18,
+ decimals: {11155111: 18},
logoUrl:
"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/scroll/assets/0x5300000000000000000000000000000000000004/logo.png",
name: "Wrapped Ether",
@@ -61,6 +63,8 @@ class YieldsDto with _$YieldsDto {
totalValueLockedUSD: 65434567890.21,
feeTier: 500,
protocol: ProtocolDto(
+ id: ProtocolId.pancakeSwapInfinityCL,
+ rawId: ProtocolId.pancakeSwapInfinityCL.toRawJsonValue,
name: "PancakeSwap",
logo:
"https://raw.githubusercontent.com/trustwallet/assets/master/dapps/exchange.pancakeswap.finance.png",
diff --git a/lib/core/enums/networks.dart b/lib/core/enums/networks.dart
index a29915a..428c45b 100644
--- a/lib/core/enums/networks.dart
+++ b/lib/core/enums/networks.dart
@@ -2,13 +2,13 @@ import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:web3kit/web3kit.dart';
-import 'package:zup_app/core/dtos/token_dto.dart';
import 'package:zup_app/gen/assets.gen.dart';
enum AppNetworks {
allNetworks,
mainnet,
// base,
+ // bnb,
unichain,
scroll,
sepolia;
@@ -47,6 +47,7 @@ enum AppNetworks {
allNetworks => false,
// base => false,
unichain => false,
+ // bnb => false
};
String get label => switch (this) {
@@ -56,6 +57,7 @@ enum AppNetworks {
allNetworks => "All Networks",
// base => "Base",
unichain => "Unichain",
+ // bnb => "BNB Chain",
};
Widget get icon => switch (this) {
@@ -65,6 +67,7 @@ enum AppNetworks {
// base => Assets.logos.base.svg(),
unichain => Assets.logos.unichain.svg(),
allNetworks => Assets.icons.all.svg(),
+ // bnb => Assets.logos.bnbChain.svg()
};
ChainInfo get chainInfo => switch (this) {
@@ -100,10 +103,17 @@ enum AppNetworks {
unichain => ChainInfo(
hexChainId: "0x82",
chainName: label,
- blockExplorerUrls: const ["https://uniscan.xyz/"],
+ blockExplorerUrls: const ["https://uniscan.xyz"],
nativeCurrency: NativeCurrencies.eth.currencyInfo,
rpcUrls: [rpcUrl],
),
+ // bnb => ChainInfo(
+ // hexChainId => "0x38",
+ // chainName => label,
+ // blockExplorerUrls => const ["https://bscscan.com"],
+ // nativeCurrency => NativeCurrencies.bnb.currencyInfo,
+ // rpcUrls => [rpcUrl],
+ // ),
};
String get wrappedNativeTokenAddress => switch (this) {
@@ -112,48 +122,8 @@ enum AppNetworks {
mainnet => "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
scroll => "0x5300000000000000000000000000000000000004",
// base => "0x4200000000000000000000000000000000000006",
- unichain => "0x4200000000000000000000000000000000000006"
- };
-
- TokenDto get wrappedNative => switch (this) {
- allNetworks => throw UnimplementedError("allNetworks is not a valid network"),
- sepolia => TokenDto(
- addresses: {chainId: wrappedNativeTokenAddress},
- name: "Wrapped Ether",
- decimals: NativeCurrencies.eth.currencyInfo.decimals,
- symbol: "WETH",
- logoUrl: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
- ),
- mainnet => TokenDto(
- addresses: {chainId: wrappedNativeTokenAddress},
- decimals: NativeCurrencies.eth.currencyInfo.decimals,
- name: "Wrapped Ether",
- symbol: "WETH",
- logoUrl: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
- ),
- scroll => TokenDto(
- addresses: {chainId: wrappedNativeTokenAddress},
- decimals: NativeCurrencies.eth.currencyInfo.decimals,
- name: "Wrapped Ether",
- symbol: "WETH",
- logoUrl:
- "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/scroll/assets/0x5300000000000000000000000000000000000004/logo.png",
- ),
- // base => TokenDto(
- // addresses: {chainId: wrappedNativeTokenAddress},
- // decimals: NativeCurrencies.eth.currencyInfo.decimals,
- // name: "Wrapped Ether",
- // symbol: "WETH",
- // logoUrl:
- // "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/base/assets/0x4200000000000000000000000000000000000006/logo.png",
- // ),
- unichain => TokenDto(
- addresses: {chainId: wrappedNativeTokenAddress},
- decimals: NativeCurrencies.eth.currencyInfo.decimals,
- name: "Wrapped Ether",
- symbol: "WETH",
- logoUrl: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/unichain/logo.png",
- ),
+ unichain => "0x4200000000000000000000000000000000000006",
+ // bnb => "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
};
String get rpcUrl => switch (this) {
@@ -163,6 +133,7 @@ enum AppNetworks {
scroll => "https://scroll-rpc.publicnode.com",
// base => "https://base-rpc.publicnode.com",
unichain => "https://unichain-rpc.publicnode.com",
+ // bnb => "https://bsc-rpc.publicnode.com"
};
Future openTx(String txHash) async {
diff --git a/lib/core/enums/pool_type.dart b/lib/core/enums/pool_type.dart
index b8945e3..9690241 100644
--- a/lib/core/enums/pool_type.dart
+++ b/lib/core/enums/pool_type.dart
@@ -4,7 +4,8 @@ enum PoolType {
@JsonValue("V3")
v3,
@JsonValue("V4")
- v4;
+ v4,
+ unknown;
bool get isV3 => this == PoolType.v3;
bool get isV4 => this == PoolType.v4;
@@ -12,5 +13,6 @@ enum PoolType {
String get label => switch (this) {
PoolType.v3 => "V3",
PoolType.v4 => "V4",
+ PoolType.unknown => "Unknown",
};
}
diff --git a/lib/core/enums/protocol_id.dart b/lib/core/enums/protocol_id.dart
new file mode 100644
index 0000000..529166a
--- /dev/null
+++ b/lib/core/enums/protocol_id.dart
@@ -0,0 +1,14 @@
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+part 'protocol_id.g.dart';
+
+@JsonEnum(alwaysCreate: true)
+enum ProtocolId {
+ @JsonValue("pancake-v4-cl")
+ pancakeSwapInfinityCL,
+ unknown;
+
+ bool get isPancakeSwapInfinityCL => this == ProtocolId.pancakeSwapInfinityCL;
+
+ String get toRawJsonValue => _$ProtocolIdEnumMap[this]!;
+}
diff --git a/lib/core/extensions/string_extension.dart b/lib/core/extensions/string_extension.dart
index dcc2fe3..46afd09 100644
--- a/lib/core/extensions/string_extension.dart
+++ b/lib/core/extensions/string_extension.dart
@@ -1,5 +1,5 @@
extension StringExtension on String {
- bool get isEmptyOrZero => isEmpty || this == "0";
+ bool get isEmptyOrZero => isEmpty || num.tryParse(this) == 0;
bool get isNotEmptyOrZero => !isEmptyOrZero;
}
diff --git a/lib/core/injections.dart b/lib/core/injections.dart
index ec51a59..c4a2e38 100644
--- a/lib/core/injections.dart
+++ b/lib/core/injections.dart
@@ -7,6 +7,7 @@ import 'package:lottie/lottie.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:web3kit/web3kit.dart';
import 'package:zup_app/abis/erc_20.abi.g.dart';
+import 'package:zup_app/abis/pancake_swap_infinity_cl_pool_manager.abi.g.dart';
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';
@@ -18,6 +19,7 @@ import 'package:zup_app/core/debouncer.dart';
import 'package:zup_app/core/enums/app_environment.dart';
import 'package:zup_app/core/pool_service.dart';
import 'package:zup_app/core/repositories/positions_repository.dart';
+import 'package:zup_app/core/repositories/protocol_repository.dart';
import 'package:zup_app/core/repositories/tokens_repository.dart';
import 'package:zup_app/core/repositories/yield_repository.dart';
import 'package:zup_app/core/zup_analytics.dart';
@@ -120,14 +122,13 @@ Future setupInjections() async {
inject.registerLazySingleton(() => EthereumAbiCoder());
+ inject.registerLazySingleton(
+ () => PancakeSwapInfinityClPoolManager(),
+ );
+
inject.registerLazySingleton(
- () => PoolService(
- inject(),
- inject(),
- inject(),
- inject(),
- inject(),
- ),
+ () => PoolService(inject(), inject(), inject(),
+ inject(), inject(), inject()),
);
inject.registerLazySingleton(
@@ -152,6 +153,10 @@ Future setupInjections() async {
inject.registerLazySingleton(() => UniswapV3Pool());
+ inject.registerLazySingleton(
+ () => ProtocolRepository(zupApiDio: inject(instanceName: InjectInstanceNames.zupAPIDio)),
+ );
+
// WARNING: this should be factory, as it's a controller and can/should be disposed
inject.registerFactory(
() => ConfettiController(duration: const Duration(seconds: 10)),
diff --git a/lib/core/mixins/keys_mixin.dart b/lib/core/mixins/keys_mixin.dart
index e4fe989..2c78c40 100644
--- a/lib/core/mixins/keys_mixin.dart
+++ b/lib/core/mixins/keys_mixin.dart
@@ -16,4 +16,6 @@ mixin KeysMixin {
String tokenPriceCacheKey({required String tokenAddress, required AppNetworks network}) {
return 'tokenPrice-$tokenAddress-${network.name}';
}
+
+ String get protocolsListKey => 'zup-supported-protocols';
}
diff --git a/lib/core/mixins/v3_pool_liquidity_calculations_mixin.dart b/lib/core/mixins/v3_pool_liquidity_calculations_mixin.dart
index 2462a1d..80760ad 100644
--- a/lib/core/mixins/v3_pool_liquidity_calculations_mixin.dart
+++ b/lib/core/mixins/v3_pool_liquidity_calculations_mixin.dart
@@ -21,9 +21,9 @@ mixin V3PoolLiquidityCalculationsMixin {
double priceUpper,
) {
final liquidity = tokenYAmount / (sqrt(currentPrice) - sqrt(priceLower));
- final token1Amount =
+ final token0Amount =
liquidity * ((sqrt(priceUpper) - sqrt(currentPrice)) / (sqrt(priceUpper) * sqrt(currentPrice)));
- return token1Amount;
+ return token0Amount;
}
}
diff --git a/lib/core/mixins/v4_pool_liquidity_calculations_mixin.dart b/lib/core/mixins/v4_pool_liquidity_calculations_mixin.dart
index 4f1def4..298d5bc 100644
--- a/lib/core/mixins/v4_pool_liquidity_calculations_mixin.dart
+++ b/lib/core/mixins/v4_pool_liquidity_calculations_mixin.dart
@@ -1,15 +1,26 @@
mixin V4PoolLiquidityCalculationsMixin {
- final _q96 = BigInt.parse("0x1000000000000000000000000");
+ final _q96 = BigInt.from(2).pow(96);
BigInt getLiquidityForAmount0(BigInt sqrtPriceAX96, BigInt sqrtPriceBX96, BigInt amount0) {
- if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
+ if (sqrtPriceAX96 > sqrtPriceBX96) {
+ final sqrtPriceAX96Before = sqrtPriceAX96;
+ sqrtPriceAX96 = sqrtPriceBX96;
+ sqrtPriceBX96 = sqrtPriceAX96Before;
+ }
+
+ final numerator = (amount0 * sqrtPriceAX96) * sqrtPriceBX96;
+ final denominator = _q96 * (sqrtPriceBX96 - sqrtPriceAX96);
- BigInt intermediate = ((sqrtPriceAX96 * sqrtPriceBX96) ~/ _q96);
- return (amount0 * intermediate) ~/ (sqrtPriceBX96 - sqrtPriceAX96);
+ return numerator ~/ denominator;
}
BigInt getLiquidityForAmount1(BigInt sqrtPriceAX96, BigInt sqrtPriceBX96, BigInt amount1) {
- if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
+ if (sqrtPriceAX96 > sqrtPriceBX96) {
+ final sqrtPriceAX96Before = sqrtPriceAX96;
+ sqrtPriceAX96 = sqrtPriceBX96;
+ sqrtPriceBX96 = sqrtPriceAX96Before;
+ }
+
return (amount1 * _q96) ~/ (sqrtPriceBX96 - sqrtPriceAX96);
}
@@ -20,7 +31,11 @@ mixin V4PoolLiquidityCalculationsMixin {
BigInt amount0,
BigInt amount1,
) {
- if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
+ if (sqrtPriceAX96 > sqrtPriceBX96) {
+ final sqrtPriceAX96Before = sqrtPriceAX96;
+ sqrtPriceAX96 = sqrtPriceBX96;
+ sqrtPriceBX96 = sqrtPriceAX96Before;
+ }
if (sqrtPriceX96 <= sqrtPriceAX96) {
return getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0);
@@ -75,10 +90,9 @@ mixin V4PoolLiquidityCalculationsMixin {
price = maxUint256 ~/ price;
}
- BigInt maxUint32 = (BigInt.one << 32) - BigInt.one;
- price = (price + maxUint32) >> 32;
+ final remainder = price & ((BigInt.one << 32) - BigInt.one);
+ final sqrtPriceX96 = price >> 32;
- BigInt mask160 = (BigInt.one << 160) - BigInt.one;
- return price & mask160;
+ return remainder > BigInt.zero ? sqrtPriceX96 + BigInt.one : sqrtPriceX96;
}
}
diff --git a/lib/core/pool_service.dart b/lib/core/pool_service.dart
index 8a85d1a..02a0d76 100644
--- a/lib/core/pool_service.dart
+++ b/lib/core/pool_service.dart
@@ -1,6 +1,7 @@
import 'package:clock/clock.dart';
import 'package:web3kit/core/dtos/transaction_response.dart';
import 'package:web3kit/web3kit.dart';
+import 'package:zup_app/abis/pancake_swap_infinity_cl_pool_manager.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/abis/uniswap_v4_position_manager.abi.g.dart';
@@ -15,6 +16,7 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
final UniswapV3PositionManager _uniswapV3PositionManager;
final UniswapV4PositionManager _uniswapV4PositionManager;
final EthereumAbiCoder _ethereumAbiCoder;
+ final PancakeSwapInfinityClPoolManager _pancakeSwapInfinityClPoolManager;
PoolService(
this._uniswapV4StateView,
@@ -22,9 +24,19 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
this._uniswapV3PositionManager,
this._uniswapV4PositionManager,
this._ethereumAbiCoder,
+ this._pancakeSwapInfinityClPoolManager,
);
Future getPoolTick(YieldDto forYield) async {
+ if (forYield.protocol.id.isPancakeSwapInfinityCL) {
+ final pancakeSwapInfinityCLPoolManagerContract = _pancakeSwapInfinityClPoolManager.fromRpcProvider(
+ contractAddress: forYield.v4PoolManager!,
+ rpcUrl: forYield.network.rpcUrl,
+ );
+
+ return (await pancakeSwapInfinityCLPoolManagerContract.getSlot0(id: forYield.poolAddress)).tick;
+ }
+
if (forYield.poolType.isV4) {
final stateView = _uniswapV4StateView.fromRpcProvider(
contractAddress: forYield.v4StateView!,
@@ -42,6 +54,37 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
return (await uniswapV3Pool.slot0()).tick;
}
+ Future getSqrtPriceX96(YieldDto forYield) async {
+ if (forYield.protocol.id.isPancakeSwapInfinityCL) {
+ final pancakeSwapInfinityCLPoolManagerContract = _pancakeSwapInfinityClPoolManager.fromRpcProvider(
+ contractAddress: forYield.v4PoolManager!,
+ rpcUrl: forYield.network.rpcUrl,
+ );
+
+ return (await pancakeSwapInfinityCLPoolManagerContract.getSlot0(id: forYield.poolAddress)).sqrtPriceX96;
+ }
+
+ if (forYield.poolType.isV4) {
+ final stateView = _uniswapV4StateView.fromRpcProvider(
+ contractAddress: forYield.v4StateView!,
+ rpcUrl: forYield.network.rpcUrl,
+ );
+
+ return (await stateView.getSlot0(poolId: forYield.poolAddress)).sqrtPriceX96;
+ }
+
+ if (forYield.poolType.isV3) {
+ final uniswapV3Pool = _uniswapV3Pool.fromRpcProvider(
+ contractAddress: forYield.poolAddress,
+ rpcUrl: forYield.network.rpcUrl,
+ );
+
+ return (await uniswapV3Pool.slot0()).sqrtPriceX96;
+ }
+
+ throw Exception('Unknown pool type; Cannot get sqrtPriceX96');
+ }
+
Future sendV3PoolDepositTransaction(
YieldDto depositOnYield,
Signer signer, {
@@ -126,9 +169,18 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
required BigInt maxAmount0ToDeposit,
required BigInt maxAmount1ToDeposit,
required String recipient,
- required BigInt currentPoolTick,
}) 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",
@@ -159,15 +211,9 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
],
tickLower,
tickUpper,
- getLiquidityForAmounts(
- getSqrtPriceAtTick(currentPoolTick),
- getSqrtPriceAtTick(tickLower),
- getSqrtPriceAtTick(tickUpper),
- amount0toDeposit,
- amount1ToDeposit,
- ),
- maxAmount0ToDeposit,
- maxAmount1ToDeposit,
+ liquidity,
+ depositOnYield.isToken0Native ? amount0toDeposit : maxAmount0ToDeposit,
+ depositOnYield.isToken1Native ? amount1ToDeposit : maxAmount1ToDeposit,
recipient,
EthereumConstants.emptyBytes,
]);
diff --git a/lib/core/repositories/protocol_repository.dart b/lib/core/repositories/protocol_repository.dart
new file mode 100644
index 0000000..5233f3a
--- /dev/null
+++ b/lib/core/repositories/protocol_repository.dart
@@ -0,0 +1,20 @@
+import 'package:dio/dio.dart';
+import 'package:zup_app/core/dtos/protocol_dto.dart';
+
+class ProtocolRepository {
+ ProtocolRepository({required this.zupApiDio});
+
+ final Dio zupApiDio;
+
+ Future> getAllSupportedProtocols() async {
+ final protocolsResponse = await zupApiDio.get("/protocols").onError((_, __) async {
+ return await zupApiDio.get("/protocols");
+ });
+
+ return (protocolsResponse.data as List)
+ .map(
+ (protocol) => ProtocolDto.fromJson(protocol),
+ )
+ .toList();
+ }
+}
diff --git a/lib/core/repositories/yield_repository.dart b/lib/core/repositories/yield_repository.dart
index cde644d..0f2ac4b 100644
--- a/lib/core/repositories/yield_repository.dart
+++ b/lib/core/repositories/yield_repository.dart
@@ -13,6 +13,7 @@ class YieldRepository {
required String token1Address,
required AppNetworks network,
required PoolSearchSettingsDto searchSettings,
+ required List blockedProtocolIds,
}) async {
final response = await _zupAPIDio.post("/pools/search/${network.chainId}", queryParameters: {
"token0Address": token0Address,
@@ -20,6 +21,7 @@ class YieldRepository {
}, data: {
"filters": {
"minTvlUsd": searchSettings.minLiquidityUSD,
+ "blockedProtocols": blockedProtocolIds,
"allowedPoolTypes": [
if (searchSettings.allowV3Search) "V3",
if (searchSettings.allowV4Search) "V4",
@@ -34,6 +36,7 @@ class YieldRepository {
required String token0InternalId,
required String token1InternalId,
required PoolSearchSettingsDto searchSettings,
+ required List blockedProtocolIds,
bool testnetMode = false,
}) async {
final response = await _zupAPIDio.post("/pools/search/all", queryParameters: {
@@ -43,6 +46,7 @@ class YieldRepository {
"filters": {
"minTvlUsd": searchSettings.minLiquidityUSD,
"testnetMode": testnetMode,
+ "blockedProtocols": blockedProtocolIds,
"allowedPoolTypes": [
if (searchSettings.allowV3Search) "V3",
if (searchSettings.allowV4Search) "V4",
diff --git a/lib/l10n/en.arb b/lib/l10n/en.arb
index bdea6df..c5e8609 100644
--- a/lib/l10n/en.arb
+++ b/lib/l10n/en.arb
@@ -34,8 +34,8 @@
}
}
},
- "depositPageMinLiquiditySearchAlert": "Searched only for pools with more than {minLiquidity} TVL.",
"depositPageTrySearchAllPools": "Try search all pools?",
+ "depositPageMinLiquiditySearchAlert": "You’ve set the search to only show pools with more than {minLiquidity}.",
"@depositPageMinLiquiditySearchAlert": {
"placeholders": {
"minLiquidity": {
@@ -166,6 +166,24 @@
"rangeSelectorMinRange": "Min Range",
"rangeSelectorMaxRange": "Max Range",
"loading": "Loading...",
+ "exchangesFilterDropdownButtonDropdownClearAll": "Clear All",
+ "exchangesFilterDropdownButtonDropdownSelectAll": "Select All",
+ "exchangesFilterDropdownButtonDropdownSearchHint": "Search by name",
+ "exchangesFilterDropdownButtonDropdownNotFoundStateTitle": "Not found",
+ "exchangesFilterDropdownButtonDropdownNotFoundStateDescription": "No supported exchanges found with this name",
+ "exchangesFilterDropdownButtonErrorSnackBarMessage": "Uh-oh! Something went wrong loading the exchanges. Please try refreshing the page.",
+ "exchangesFilterDropdownButtonTitle": "Exchanges",
+ "exchangesFilterDropdownButtonTitleNumered": "Exchanges ({exchangesCount})",
+ "@exchangesFilterDropdownButtonTitleNumered": {
+ "placeholders": {
+ "exchangesCount": {
+ "type": "String"
+ }
+ }
+ },
+ "createPageSelectTokensStageTokenA": "Token A",
+ "createPageSelectTokensStageTokenB": "Token B",
+ "createPageSelectTokensStageSearchSettings": "Search Settings",
"depositPageLoadingStep1Title": "Matching Tokens...",
"depositPageLoadingStep1Description": "Pairing Token A and Token B to kick off the search for top yields!",
"depositPageLoadingStep2Title": "Scanning the Pools...",
@@ -175,8 +193,8 @@
"depositPageErrorStateTitle": "Oops! Something went wrong!",
"depositPageErrorStateDescription": "We ran into a issue while trying to find the best pool. Give it another shot, and if it keeps happening, don’t hesitate to reach out to us!",
"depositPageEmptyStateTitle": "No Pools Found",
- "depositPageEmptyStateDescription": "Seems like that there are no pools on our supported protocols matching your selected tokens. Would you like to try another combination?",
- "depositPageEmptyStateHelpButtonTitle": "Try another combination",
+ "depositPageEmptyStateDescription": "Seems like that there are no pools matching your defined settings at the moment. Would you like to either change your settings or try another combination?",
+ "depositPageEmptyStateHelpButtonTitle": "Go Back to New Position",
"depositPageBackButtonTitle": "Select Pair",
"depositPageTitle": "Add liquidity",
"depositPageTimeFrameTooltipMessage": "Select a time-frame that matches your goal with this pool: a quick win (Short term), a balanced approach (Medium term), or a long haul (Long term).",
diff --git a/lib/l10n/gen/app_localizations.dart b/lib/l10n/gen/app_localizations.dart
index e0f6eac..69e8044 100644
--- a/lib/l10n/gen/app_localizations.dart
+++ b/lib/l10n/gen/app_localizations.dart
@@ -173,18 +173,18 @@ abstract class S {
String depositPageSearchOnlyForPoolsWithMorethan(
{required String minLiquidity});
- /// No description provided for @depositPageMinLiquiditySearchAlert.
- ///
- /// In en, this message translates to:
- /// **'Searched only for pools with more than {minLiquidity} TVL.'**
- String depositPageMinLiquiditySearchAlert({required String minLiquidity});
-
/// No description provided for @depositPageTrySearchAllPools.
///
/// In en, this message translates to:
/// **'Try search all pools?'**
String get depositPageTrySearchAllPools;
+ /// No description provided for @depositPageMinLiquiditySearchAlert.
+ ///
+ /// In en, this message translates to:
+ /// **'You’ve set the search to only show pools with more than {minLiquidity}.'**
+ String depositPageMinLiquiditySearchAlert({required String minLiquidity});
+
/// No description provided for @slippageExplanation.
///
/// In en, this message translates to:
@@ -496,6 +496,73 @@ abstract class S {
/// **'Loading...'**
String get loading;
+ /// No description provided for @exchangesFilterDropdownButtonDropdownClearAll.
+ ///
+ /// In en, this message translates to:
+ /// **'Clear All'**
+ String get exchangesFilterDropdownButtonDropdownClearAll;
+
+ /// No description provided for @exchangesFilterDropdownButtonDropdownSelectAll.
+ ///
+ /// In en, this message translates to:
+ /// **'Select All'**
+ String get exchangesFilterDropdownButtonDropdownSelectAll;
+
+ /// No description provided for @exchangesFilterDropdownButtonDropdownSearchHint.
+ ///
+ /// In en, this message translates to:
+ /// **'Search by name'**
+ String get exchangesFilterDropdownButtonDropdownSearchHint;
+
+ /// No description provided for @exchangesFilterDropdownButtonDropdownNotFoundStateTitle.
+ ///
+ /// In en, this message translates to:
+ /// **'Not found'**
+ String get exchangesFilterDropdownButtonDropdownNotFoundStateTitle;
+
+ /// No description provided for @exchangesFilterDropdownButtonDropdownNotFoundStateDescription.
+ ///
+ /// In en, this message translates to:
+ /// **'No supported exchanges found with this name'**
+ String get exchangesFilterDropdownButtonDropdownNotFoundStateDescription;
+
+ /// No description provided for @exchangesFilterDropdownButtonErrorSnackBarMessage.
+ ///
+ /// In en, this message translates to:
+ /// **'Uh-oh! Something went wrong loading the exchanges. Please try refreshing the page.'**
+ String get exchangesFilterDropdownButtonErrorSnackBarMessage;
+
+ /// No description provided for @exchangesFilterDropdownButtonTitle.
+ ///
+ /// In en, this message translates to:
+ /// **'Exchanges'**
+ String get exchangesFilterDropdownButtonTitle;
+
+ /// No description provided for @exchangesFilterDropdownButtonTitleNumered.
+ ///
+ /// In en, this message translates to:
+ /// **'Exchanges ({exchangesCount})'**
+ String exchangesFilterDropdownButtonTitleNumered(
+ {required String exchangesCount});
+
+ /// No description provided for @createPageSelectTokensStageTokenA.
+ ///
+ /// In en, this message translates to:
+ /// **'Token A'**
+ String get createPageSelectTokensStageTokenA;
+
+ /// No description provided for @createPageSelectTokensStageTokenB.
+ ///
+ /// In en, this message translates to:
+ /// **'Token B'**
+ String get createPageSelectTokensStageTokenB;
+
+ /// No description provided for @createPageSelectTokensStageSearchSettings.
+ ///
+ /// In en, this message translates to:
+ /// **'Search Settings'**
+ String get createPageSelectTokensStageSearchSettings;
+
/// No description provided for @depositPageLoadingStep1Title.
///
/// In en, this message translates to:
@@ -553,13 +620,13 @@ abstract class S {
/// No description provided for @depositPageEmptyStateDescription.
///
/// In en, this message translates to:
- /// **'Seems like that there are no pools on our supported protocols matching your selected tokens. Would you like to try another combination?'**
+ /// **'Seems like that there are no pools matching your defined settings at the moment. Would you like to either change your settings or try another combination?'**
String get depositPageEmptyStateDescription;
/// No description provided for @depositPageEmptyStateHelpButtonTitle.
///
/// In en, this message translates to:
- /// **'Try another combination'**
+ /// **'Go Back to New Position'**
String get depositPageEmptyStateHelpButtonTitle;
/// No description provided for @depositPageBackButtonTitle.
diff --git a/lib/l10n/gen/app_localizations_en.dart b/lib/l10n/gen/app_localizations_en.dart
index b4ec1ad..5ef9c0a 100644
--- a/lib/l10n/gen/app_localizations_en.dart
+++ b/lib/l10n/gen/app_localizations_en.dart
@@ -57,12 +57,12 @@ class SEn extends S {
}
@override
- String depositPageMinLiquiditySearchAlert({required String minLiquidity}) {
- return 'Searched only for pools with more than $minLiquidity TVL.';
- }
+ String get depositPageTrySearchAllPools => 'Try search all pools?';
@override
- String get depositPageTrySearchAllPools => 'Try search all pools?';
+ String depositPageMinLiquiditySearchAlert({required String minLiquidity}) {
+ return 'You’ve set the search to only show pools with more than $minLiquidity.';
+ }
@override
String get slippageExplanation =>
@@ -254,6 +254,46 @@ class SEn extends S {
@override
String get loading => 'Loading...';
+ @override
+ String get exchangesFilterDropdownButtonDropdownClearAll => 'Clear All';
+
+ @override
+ String get exchangesFilterDropdownButtonDropdownSelectAll => 'Select All';
+
+ @override
+ String get exchangesFilterDropdownButtonDropdownSearchHint =>
+ 'Search by name';
+
+ @override
+ String get exchangesFilterDropdownButtonDropdownNotFoundStateTitle =>
+ 'Not found';
+
+ @override
+ String get exchangesFilterDropdownButtonDropdownNotFoundStateDescription =>
+ 'No supported exchanges found with this name';
+
+ @override
+ String get exchangesFilterDropdownButtonErrorSnackBarMessage =>
+ 'Uh-oh! Something went wrong loading the exchanges. Please try refreshing the page.';
+
+ @override
+ String get exchangesFilterDropdownButtonTitle => 'Exchanges';
+
+ @override
+ String exchangesFilterDropdownButtonTitleNumered(
+ {required String exchangesCount}) {
+ return 'Exchanges ($exchangesCount)';
+ }
+
+ @override
+ String get createPageSelectTokensStageTokenA => 'Token A';
+
+ @override
+ String get createPageSelectTokensStageTokenB => 'Token B';
+
+ @override
+ String get createPageSelectTokensStageSearchSettings => 'Search Settings';
+
@override
String get depositPageLoadingStep1Title => 'Matching Tokens...';
@@ -288,10 +328,10 @@ class SEn extends S {
@override
String get depositPageEmptyStateDescription =>
- 'Seems like that there are no pools on our supported protocols matching your selected tokens. Would you like to try another combination?';
+ 'Seems like that there are no pools matching your defined settings at the moment. Would you like to either change your settings or try another combination?';
@override
- String get depositPageEmptyStateHelpButtonTitle => 'Try another combination';
+ String get depositPageEmptyStateHelpButtonTitle => 'Go Back to New Position';
@override
String get depositPageBackButtonTitle => 'Select Pair';
diff --git a/lib/widgets/app_cookies_consent_widget.dart b/lib/widgets/app_cookies_consent_widget.dart
index 8a35946..36cf04c 100644
--- a/lib/widgets/app_cookies_consent_widget.dart
+++ b/lib/widgets/app_cookies_consent_widget.dart
@@ -69,7 +69,7 @@ class AppCookieConsentWidget extends StatelessWidget {
hoverElevation: 0,
backgroundColor: ZupColors.brand6,
foregroundColor: ZupColors.brand,
- onPressed: () {
+ onPressed: (buttonContext) {
onAccept();
cache.saveCookiesConsentStatus(status: true);
},
diff --git a/lib/widgets/app_settings_dropdown.dart b/lib/widgets/app_settings_dropdown.dart
index 2a72b7d..11c4959 100644
--- a/lib/widgets/app_settings_dropdown.dart
+++ b/lib/widgets/app_settings_dropdown.dart
@@ -8,9 +8,9 @@ import 'package:zup_ui_kit/zup_ui_kit.dart';
class AppSettingsDropdown extends StatefulWidget {
const AppSettingsDropdown({super.key});
- static void show(BuildContext showBelowContext) => ZupDropdown.show(
- showBelowContext: showBelowContext,
- offset: const Offset(0, 16),
+ static void show(BuildContext showBelowContext) => ZupPopover.show(
+ showBasedOnContext: showBelowContext,
+ adjustment: const Offset(0, 16),
child: const AppSettingsDropdown(),
);
diff --git a/lib/widgets/token_avatar.dart b/lib/widgets/token_avatar.dart
index 4a114f7..2d7a945 100644
--- a/lib/widgets/token_avatar.dart
+++ b/lib/widgets/token_avatar.dart
@@ -30,23 +30,17 @@ class TokenAvatar extends StatelessWidget {
Widget build(BuildContext context) {
return asset.logoUrl.isEmpty
? genericAvatar()
- : zupCachedImage.build(
- asset.logoUrl,
+ : zupCachedImage.build(asset.logoUrl,
height: size,
width: size,
radius: 50,
errorWidget: (_, __, ___) => genericAvatar(),
- loadingBuilder: (context, child, loadingProgress) {
- if (loadingProgress == null) return child;
-
- return Skeleton.ignore(
- child: ZupCircularLoadingIndicator(
- size: size,
- backgroundColor: ZupColors.brand5,
- indicatorColor: ZupColors.brand,
- ),
- );
- },
- );
+ placeholder: Skeleton.ignore(
+ child: ZupCircularLoadingIndicator(
+ size: size,
+ backgroundColor: ZupColors.brand5,
+ indicatorColor: ZupColors.brand,
+ ),
+ ));
}
}
diff --git a/lib/widgets/zup_cached_image.dart b/lib/widgets/zup_cached_image.dart
index 573462b..aedfc61 100644
--- a/lib/widgets/zup_cached_image.dart
+++ b/lib/widgets/zup_cached_image.dart
@@ -15,7 +15,7 @@ class ZupCachedImage {
double? height,
double? width,
double? radius,
- ImageLoadingBuilder? loadingBuilder,
+ Widget? placeholder,
ImageErrorWidgetBuilder? errorWidget,
}) {
return ClipRRect(
@@ -26,14 +26,17 @@ class ZupCachedImage {
borderRadius: BorderRadius.circular(radius ?? 0),
border: Border.all(width: 0.5, color: ZupColors.gray5),
),
- // cache not implemented yet because of web issue rendering images from other domains
+ // cache not implemented yet because of web issue rendering images from other domains (https://github.com/Baseflow/flutter_cached_network_image/issues/972)
child: Image.network(
_parseImageUrl(url),
height: height,
width: width,
fit: BoxFit.cover,
errorBuilder: errorWidget,
- loadingBuilder: loadingBuilder,
+ frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
+ if (frame == null) return placeholder ?? ZupCircularLoadingIndicator(size: height ?? 20);
+ return child;
+ },
webHtmlElementStrategy: WebHtmlElementStrategy.fallback,
),
),
diff --git a/pubspec.lock b/pubspec.lock
index f39ed55..b542fc9 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -542,10 +542,10 @@ packages:
dependency: transitive
description:
name: hashlib
- sha256: f00cbea036b8a8ea19be5df1e233fb2e250858639d3488776c32f0bd60b41cc4
+ sha256: a7b34c92005e9ccf462b71bcab40b5d5cff53669c7e87e6c7277f18bb075bf05
url: "https://pub.dev"
source: hosted
- version: "1.21.2"
+ version: "1.21.3"
hashlib_codecs:
dependency: transitive
description:
@@ -1293,7 +1293,7 @@ packages:
description:
path: "."
ref: main
- resolved-ref: "96c38241bbd55f27820c0fbe0e62ed53f2febed7"
+ resolved-ref: "50b4737ccfa02d8b657173e430ca197dc18b5993"
url: "https://github.com/Zup-Protocol/web3kit.git"
source: git
version: "0.0.1"
@@ -1342,7 +1342,7 @@ packages:
description:
path: "."
ref: main
- resolved-ref: "2fb18c6a9212718d0bb72d13f255436800d34c4a"
+ resolved-ref: "93b849fffe3a50e116c28d45530ffb28a007c5e1"
url: "https://github.com/Zup-Protocol/zup-core.git"
source: git
version: "0.0.1"
@@ -1351,7 +1351,7 @@ packages:
description:
path: "."
ref: main
- resolved-ref: cd1e5f42c34c93ec91f8da476ec19cc2d2435c36
+ resolved-ref: "1d2a3b3890032536df60a14db88bf7cd8fe7e52e"
url: "https://github.com/Zup-Protocol/zup-ui-kit.git"
source: git
version: "0.0.1"
diff --git a/test/app/app_layout_test.dart b/test/app/app_layout_test.dart
index af0f33e..7af2fba 100644
--- a/test/app/app_layout_test.dart
+++ b/test/app/app_layout_test.dart
@@ -59,13 +59,15 @@ void main() {
initialPath: ZupNavigatorPaths.newPosition.path,
routeBuilder: (context, settings, child) => PageRouteBuilder(
settings: settings,
- pageBuilder: (context, __, ___) => const AppPage(),
+ pageBuilder: (context, __, ___) => const SizedBox(
+ height: 500,
+ child: AppPage(),
+ ),
),
),
),
device: isMobile ? GoldenDevice.mobile : GoldenDevice.pc,
);
-
zGoldenTest("When the device size is a mobile, it should have a bottom navbar instead of a top app bar",
goldenFileName: "app_layout_navbar", (tester) async {
await tester.pumpDeviceBuilder(await goldenBuilder(isMobile: true), wrapper: GoldenConfig.localizationsWrapper());
diff --git a/test/app/create/create_page_select_token_stage_test.dart b/test/app/create/create_page_select_token_stage_test.dart
index 238a8c0..1e167ae 100644
--- a/test/app/create/create_page_select_token_stage_test.dart
+++ b/test/app/create/create_page_select_token_stage_test.dart
@@ -13,11 +13,13 @@ import 'package:zup_app/core/dtos/pool_search_settings_dto.dart';
import 'package:zup_app/core/dtos/token_dto.dart';
import 'package:zup_app/core/enums/networks.dart';
import 'package:zup_app/core/injections.dart';
+import 'package:zup_app/core/repositories/protocol_repository.dart';
import 'package:zup_app/core/repositories/tokens_repository.dart';
import 'package:zup_app/core/zup_navigator.dart';
import 'package:zup_app/widgets/token_card.dart';
import 'package:zup_app/widgets/token_selector_modal/token_selector_modal_cubit.dart';
import 'package:zup_app/widgets/zup_cached_image.dart';
+import 'package:zup_core/zup_core.dart';
import '../../golden_config.dart';
import '../../mocks.dart';
@@ -28,12 +30,16 @@ void main() {
late Wallet wallet;
late Cache cache;
late ZupNavigator zupNavigator;
+ late ProtocolRepository protocolRepository;
+ late ZupSingletonCache zupSingletonCache;
setUp(() {
appCubit = AppCubitMock();
tokensRepository = TokensRepositoryMock();
wallet = WalletMock();
zupNavigator = ZupNavigatorMock();
+ protocolRepository = ProtocolRepositoryMock();
+ zupSingletonCache = ZupSingletonCache.shared;
registerFallbackValue(AppNetworks.sepolia);
@@ -43,6 +49,8 @@ void main() {
inject.registerFactory(() => Debouncer(milliseconds: 0));
inject.registerFactory(() => zupNavigator);
inject.registerFactory(() => cache);
+ inject.registerFactory(() => zupSingletonCache);
+ inject.registerFactory(() => protocolRepository);
inject.registerLazySingleton(
() => TokenSelectorModalCubit(tokensRepository, appCubit, wallet),
@@ -84,7 +92,7 @@ void main() {
"When selecting the B token with the same address as A token, it should change the A token to null, and the B token to the selected token",
goldenFileName: "create_page_select_tokens_stage_change_b_token_to_same_token_as_a", (tester) async {
const selectedNetwork = AppNetworks.sepolia;
- final token0 = selectedNetwork.wrappedNative;
+ final token0 = TokenDto.fixture();
when(() => tokensRepository.getPopularTokens(any())).thenAnswer(
(_) async => [token0],
@@ -104,7 +112,7 @@ void main() {
"When selecting the A token with the same address as B token, it should change the B token to null and the A token to the selected token",
goldenFileName: "create_page_select_tokens_stage_change_a_token_to_same_token_as_b", (tester) async {
const selectedNetwork = AppNetworks.sepolia;
- final token0 = selectedNetwork.wrappedNative;
+ final token0 = TokenDto.fixture();
when(() => appCubit.currentChainId).thenReturn(selectedNetwork.chainId);
when(() => tokensRepository.getPopularTokens(any())).thenAnswer(
diff --git a/test/app/create/create_page_test.dart b/test/app/create/create_page_test.dart
index 49a6888..8658efa 100644
--- a/test/app/create/create_page_test.dart
+++ b/test/app/create/create_page_test.dart
@@ -7,8 +7,10 @@ import 'package:zup_app/core/cache.dart';
import 'package:zup_app/core/dtos/pool_search_settings_dto.dart';
import 'package:zup_app/core/enums/networks.dart';
import 'package:zup_app/core/injections.dart';
+import 'package:zup_app/core/repositories/protocol_repository.dart';
import 'package:zup_app/core/zup_navigator.dart';
import 'package:zup_app/widgets/zup_cached_image.dart';
+import 'package:zup_core/zup_core.dart';
import '../../golden_config.dart';
import '../../mocks.dart';
@@ -25,6 +27,8 @@ void main() {
inject.registerFactory(() => mockZupCachedImage());
inject.registerFactory(() => appCubit);
inject.registerFactory(() => ZupNavigatorMock());
+ inject.registerFactory(() => ZupSingletonCache.shared);
+ inject.registerFactory(() => ProtocolRepositoryMock());
when(() => cache.getPoolSearchSettings()).thenReturn(PoolSearchSettingsDto.fixture());
when(() => appCubit.selectedNetwork).thenAnswer((_) => AppNetworks.sepolia);
diff --git a/test/app/create/deposit/deposit_cubit_test.dart b/test/app/create/deposit/deposit_cubit_test.dart
index 551aed1..541c0bf 100644
--- a/test/app/create/deposit/deposit_cubit_test.dart
+++ b/test/app/create/deposit/deposit_cubit_test.dart
@@ -8,6 +8,7 @@ import 'package:zup_app/app/app_cubit/app_cubit.dart';
import 'package:zup_app/app/create/deposit/deposit_cubit.dart';
import 'package:zup_app/core/cache.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';
import 'package:zup_app/core/dtos/yield_dto.dart';
import 'package:zup_app/core/dtos/yields_dto.dart';
@@ -60,11 +61,12 @@ void main() {
);
when(() => appCubit.isTestnetMode).thenReturn(false);
-
+ when(() => cache.blockedProtocolsIds).thenReturn([]);
when(() => yieldRepository.getAllNetworksYield(
token0InternalId: any(named: "token0InternalId"),
token1InternalId: any(named: "token1InternalId"),
searchSettings: any(named: "searchSettings"),
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
testnetMode: any(named: "testnetMode"))).thenAnswer((_) async => YieldsDto.fixture());
when(() => appCubit.selectedNetwork).thenAnswer((_) => AppNetworks.sepolia);
@@ -99,7 +101,7 @@ void main() {
await zupSingletonCache.clear();
});
- group("When calling `setup`, the cubit should register a periodic task to get the pool tick every minute. ", () {
+ 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;
@@ -120,7 +122,7 @@ void main() {
async.elapse(const Duration(minutes: minutesPassed));
expect(actualLastEmittedPoolTick, poolTick);
- expect(eventsCounter, minutesPassed);
+ expect(eventsCounter, minutesPassed * 2);
});
});
@@ -181,6 +183,7 @@ void main() {
token0Address: any(named: "token0Address"),
token1Address: any(named: "token1Address"),
searchSettings: any(named: "searchSettings"),
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
network: any(named: "network"))).thenAnswer(
(_) async => YieldsDto.fixture(),
);
@@ -195,6 +198,7 @@ void main() {
token1Address: token1Address,
searchSettings: any(named: "searchSettings"),
network: any(named: "network"),
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
)).called(1);
});
@@ -204,18 +208,21 @@ void main() {
const minLiquidityUSD = 123;
when(() => yieldRepository.getSingleNetworkYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0Address: any(named: "token0Address"),
token1Address: any(named: "token1Address"),
searchSettings: any(named: "searchSettings"),
network: any(named: "network"))).thenAnswer(
- (_) async => const YieldsDto(pools: [], minLiquidityUSD: minLiquidityUSD),
+ (_) async => const YieldsDto(pools: [], filters: PoolSearchFiltersDto(minTvlUsd: minLiquidityUSD)),
);
expectLater(
sut.stream,
emitsInOrder([
const DepositState.loading(),
- const DepositState.noYields(minLiquiditySearched: minLiquidityUSD),
+ const DepositState.noYields(
+ filtersApplied: PoolSearchFiltersDto(minTvlUsd: minLiquidityUSD),
+ ),
]));
await sut.getBestPools(token0AddressOrId: "", token1AddressOrId: "");
@@ -225,6 +232,7 @@ void main() {
final pools = YieldsDto.fixture();
when(() => yieldRepository.getSingleNetworkYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0Address: any(named: "token0Address"),
token1Address: any(named: "token1Address"),
searchSettings: any(named: "searchSettings"),
@@ -237,6 +245,7 @@ void main() {
test("When calling `getBestPools` and receiving an error, it should emit the error state", () async {
when(() => yieldRepository.getSingleNetworkYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0Address: any(named: "token0Address"),
token1Address: any(named: "token1Address"),
searchSettings: any(named: "searchSettings"),
@@ -454,7 +463,8 @@ void main() {
);
test(
- """When calling 'getSelectedPoolTick', it should use the zup singleton cache with a expiration of 1 minute""",
+ """When calling 'getSelectedPoolTick', 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();
@@ -475,7 +485,7 @@ void main() {
verify(() => zupSingletonCache.run(
any(),
key: "poolTick-${selectedYield.poolAddress}-${selectedYield.network.name}",
- expiration: const Duration(minutes: 1),
+ expiration: const Duration(seconds: 30 - 1),
ignoreCache: false,
)).called(1);
},
@@ -689,6 +699,7 @@ void main() {
when(() => cache.getPoolSearchSettings()).thenReturn(PoolSearchSettingsDto(minLiquidityUSD: 129816));
when(() => yieldRepository.getSingleNetworkYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0Address: any(named: "token0Address"),
token1Address: any(named: "token1Address"),
network: any(named: "network"),
@@ -698,6 +709,7 @@ void main() {
await sut.getBestPools(token0AddressOrId: "0x", token1AddressOrId: "0x", ignoreMinLiquidity: true);
verify(() => yieldRepository.getSingleNetworkYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0Address: any(named: "token0Address"),
token1Address: any(named: "token1Address"),
network: any(named: "network"),
@@ -710,6 +722,7 @@ void main() {
when(() => appCubit.selectedNetwork).thenReturn(AppNetworks.allNetworks);
when(() => cache.getPoolSearchSettings()).thenReturn(PoolSearchSettingsDto(minLiquidityUSD: 129816));
when(() => yieldRepository.getAllNetworksYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0InternalId: any(named: "token0InternalId"),
token1InternalId: any(named: "token1InternalId"),
searchSettings: any(named: "searchSettings"),
@@ -718,6 +731,7 @@ void main() {
await sut.getBestPools(token0AddressOrId: "0x", token1AddressOrId: "0x", ignoreMinLiquidity: true);
verify(() => yieldRepository.getAllNetworksYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0InternalId: any(named: "token0InternalId"),
token1InternalId: any(named: "token1InternalId"),
searchSettings: PoolSearchSettingsDto.fixture().copyWith(minLiquidityUSD: 0),
@@ -730,6 +744,7 @@ void main() {
when(() => cache.getPoolSearchSettings()).thenReturn(PoolSearchSettingsDto(minLiquidityUSD: minLiquiditySaved));
when(() => yieldRepository.getSingleNetworkYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0Address: any(named: "token0Address"),
token1Address: any(named: "token1Address"),
network: any(named: "network"),
@@ -739,6 +754,7 @@ void main() {
await sut.getBestPools(token0AddressOrId: "0x", token1AddressOrId: "0x", ignoreMinLiquidity: false);
verify(() => yieldRepository.getSingleNetworkYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0Address: any(named: "token0Address"),
token1Address: any(named: "token1Address"),
network: any(named: "network"),
@@ -773,6 +789,7 @@ void main() {
await sut.getBestPools(token0AddressOrId: token0Address, token1AddressOrId: token1Address);
verify(() => yieldRepository.getAllNetworksYield(
+ blockedProtocolIds: any(named: "blockedProtocolIds"),
token0InternalId: token0Address,
token1InternalId: token1Address,
searchSettings: any(named: "searchSettings"),
@@ -787,4 +804,39 @@ void main() {
expect(sut.selectedYieldTimeframe, selectedYieldTimeFrame);
});
+
+ test("""When calling 'getBestPools' and all networks is the selected network,
+ it should call the repository to get it passing the blocked protocol ids got
+ from the cache""", () async {
+ final cachedBlockedProtocolIds = ["0x1", "0x2", "ababa"];
+ when(() => cache.blockedProtocolsIds).thenReturn(cachedBlockedProtocolIds);
+ when(() => appCubit.selectedNetwork).thenReturn(AppNetworks.allNetworks);
+
+ await sut.getBestPools(token0AddressOrId: "0x", token1AddressOrId: "0x");
+
+ verify(() => yieldRepository.getAllNetworksYield(
+ blockedProtocolIds: cachedBlockedProtocolIds,
+ token0InternalId: any(named: "token0InternalId"),
+ token1InternalId: any(named: "token1InternalId"),
+ searchSettings: any(named: "searchSettings"),
+ )).called(1);
+ });
+
+ test("""When calling 'getBestPools' and all networks is not the selected network,
+ it should call the repository to get it passing the blocked protocol ids got
+ from the cache""", () async {
+ final cachedBlockedProtocolIds = ["017628761", "asaas", "ababa"];
+ when(() => cache.blockedProtocolsIds).thenReturn(cachedBlockedProtocolIds);
+ when(() => appCubit.selectedNetwork).thenReturn(AppNetworks.sepolia);
+
+ await sut.getBestPools(token0AddressOrId: "0x", token1AddressOrId: "0x");
+
+ verify(() => yieldRepository.getSingleNetworkYield(
+ blockedProtocolIds: cachedBlockedProtocolIds,
+ network: any(named: "network"),
+ token0Address: any(named: "token0Address"),
+ token1Address: any(named: "token1Address"),
+ searchSettings: any(named: "searchSettings"),
+ )).called(1);
+ });
}
diff --git a/test/app/create/deposit/deposit_page_test.dart b/test/app/create/deposit/deposit_page_test.dart
index f042d3f..43b85ea 100644
--- a/test/app/create/deposit/deposit_page_test.dart
+++ b/test/app/create/deposit/deposit_page_test.dart
@@ -18,6 +18,7 @@ import 'package:zup_app/app/create/deposit/deposit_page.dart';
import 'package:zup_app/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart';
import 'package:zup_app/core/cache.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';
import 'package:zup_app/core/dtos/token_price_dto.dart';
import 'package:zup_app/core/dtos/yield_dto.dart';
@@ -154,6 +155,7 @@ void main() {
zGoldenTest("When initializing the page it should call setup in the cubit", (tester) async {
await tester.runAsync(() async {
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
});
verify(() => cubit.setup()).called(1);
@@ -169,6 +171,7 @@ void main() {
await tester.runAsync(() async {
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
});
verify(
@@ -185,6 +188,7 @@ void main() {
await tester.runAsync(() async {
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
});
await tester.pumpAndSettle();
@@ -192,9 +196,14 @@ void main() {
zGoldenTest("When the cubit state is noYields with no min liquidity searched, it should just show the noYields state",
goldenFileName: "deposit_page_no_yields", (tester) async {
- when(() => cubit.state).thenReturn(const DepositState.noYields(minLiquiditySearched: 0));
+ when(() => cubit.state).thenReturn(
+ const DepositState.noYields(
+ filtersApplied: PoolSearchFiltersDto(minTvlUsd: 0),
+ ),
+ );
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.pumpAndSettle();
});
@@ -204,9 +213,14 @@ void main() {
with a helper text saying it, and a button to search all pools""",
goldenFileName: "deposit_page_no_yields_filtered_by_min_liquidity",
(tester) async {
- when(() => cubit.state).thenReturn(const DepositState.noYields(minLiquiditySearched: 97654));
+ when(() => cubit.state).thenReturn(
+ const DepositState.noYields(
+ filtersApplied: PoolSearchFiltersDto(minTvlUsd: 97654),
+ ),
+ );
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.pumpAndSettle();
},
@@ -222,9 +236,14 @@ void main() {
ignoreMinLiquidity: any(named: "ignoreMinLiquidity")),
).thenAnswer((_) async {});
- when(() => cubit.state).thenReturn(const DepositState.noYields(minLiquiditySearched: 97654));
+ when(() => cubit.state).thenReturn(
+ const DepositState.noYields(
+ filtersApplied: PoolSearchFiltersDto(minTvlUsd: 97654),
+ ),
+ );
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("search-all-pools-button")));
await tester.pumpAndSettle();
@@ -241,16 +260,17 @@ void main() {
zGoldenTest("""When clicking the helper button in the no yields state,
it should navigate back to choose tokens stage""", (tester) async {
- when(() => navigator.back(any())).thenAnswer((_) async {});
+ when(() => navigator.navigateToNewPosition()).thenAnswer((_) async {});
- when(() => cubit.state).thenReturn(const DepositState.noYields(minLiquiditySearched: 0));
+ when(() => cubit.state).thenReturn(const DepositState.noYields(filtersApplied: PoolSearchFiltersDto()));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("help-button")));
await tester.pumpAndSettle();
- verify(() => navigator.back(any())).called(1);
+ verify(() => navigator.navigateToNewPosition()).called(1);
});
zGoldenTest("When the cubit state is error, it should show the error state", goldenFileName: "deposit_page_error",
@@ -258,6 +278,7 @@ void main() {
when(() => cubit.state).thenReturn(const DepositState.error());
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.pumpAndSettle();
});
@@ -272,6 +293,7 @@ void main() {
when(() => cubit.state).thenReturn(const DepositState.error());
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("help-button")));
await tester.pumpAndSettle();
@@ -287,6 +309,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(yields));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.pumpAndSettle();
});
@@ -299,6 +322,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(yields));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.pumpAndSettle();
});
@@ -311,6 +335,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(yields));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.pumpAndSettle();
});
@@ -319,11 +344,14 @@ void main() {
search has zero, but the user has a local filter set, it should show a text and a button to search only pools
with the local filter amount set""",
goldenFileName: "deposit_page_success_filtered_by_min_liquidity_local_filter_set", (tester) async {
- final yields = YieldsDto.fixture().copyWith(minLiquidityUSD: 0); // api filter returns 0
+ final yields = YieldsDto.fixture().copyWith(
+ filters: const PoolSearchFiltersDto(minTvlUsd: 0),
+ ); // api filter returns 0
when(() => cubit.poolSearchSettings).thenReturn(PoolSearchSettingsDto(minLiquidityUSD: 2189)); // local filter set
when(() => cubit.state).thenReturn(DepositState.success(yields));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.pumpAndSettle();
});
@@ -331,7 +359,10 @@ void main() {
zGoldenTest("""When clicking in the button to search all pools in the success state
that is with a filter for min liquidity, it should call the cubit to get pools with
the ignore min liquidity flag""", (tester) async {
- final yields = YieldsDto.fixture().copyWith(minLiquidityUSD: 12675);
+ final yields = YieldsDto.fixture().copyWith(
+ filters: const PoolSearchFiltersDto(minTvlUsd: 12675),
+ );
+
when(() => cubit.poolSearchSettings).thenReturn(PoolSearchSettingsDto(minLiquidityUSD: 12675));
when(() => cubit.state).thenReturn(DepositState.success(yields));
when(() => cubit.getBestPools(
@@ -340,6 +371,7 @@ void main() {
ignoreMinLiquidity: any(named: "ignoreMinLiquidity"))).thenAnswer((_) async {});
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("hide-show-all-pools-button")));
await tester.pumpAndSettle();
@@ -356,7 +388,10 @@ void main() {
zGoldenTest("""When clicking in the button to search only pools with more than x amount in
the success state that is without a filter for min liquidity, it should call the cubit to get pools with
the min liquidity set to not be ignored""", (tester) async {
- final yields = YieldsDto.fixture().copyWith(minLiquidityUSD: 0); // api filter returns 0
+ final yields = YieldsDto.fixture().copyWith(
+ filters: const PoolSearchFiltersDto(minTvlUsd: 0),
+ ); // api filter returns 0
+
when(() => cubit.poolSearchSettings).thenReturn(PoolSearchSettingsDto(minLiquidityUSD: 12675)); // local filter set
when(() => cubit.state).thenReturn(DepositState.success(yields));
when(() => cubit.getBestPools(
@@ -365,6 +400,7 @@ void main() {
ignoreMinLiquidity: any(named: "ignoreMinLiquidity"))).thenAnswer((_) async {});
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("hide-show-all-pools-button")));
await tester.pumpAndSettle();
@@ -428,6 +464,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture()));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("back-button")));
await tester.pumpAndSettle();
@@ -440,6 +477,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture()));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.hover(find.byKey(const Key("timeframe-tooltip")));
await tester.pumpAndSettle();
@@ -451,6 +489,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture()));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.hover(find.byKey(const Key("timeframe-tooltip")));
await tester.pumpAndSettle();
@@ -476,6 +515,7 @@ void main() {
await tester.pumpDeviceBuilder(await goldenBuilder());
await tester.pumpAndSettle();
+ await tester.pumpAndSettle();
});
});
@@ -484,6 +524,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture()));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("yield-card-24h")));
await tester.pumpAndSettle();
@@ -502,6 +543,7 @@ void main() {
when(() => cubit.selectedYield).thenReturn(selectedYield);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("yield-card-30d")));
await tester.pumpAndSettle();
@@ -521,6 +563,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture()));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("reverse-tokens-reversed")));
await tester.pumpAndSettle();
@@ -538,6 +581,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture()));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("reverse-tokens-reversed")));
await tester.pumpAndSettle();
@@ -558,6 +602,7 @@ void main() {
when(() => cubit.state).thenReturn(DepositState.success(YieldsDto.fixture()));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("reverse-tokens-reversed")));
await tester.pumpAndSettle();
@@ -580,6 +625,7 @@ void main() {
await tester.pumpDeviceBuilder(await goldenBuilder());
await tester.pumpAndSettle();
+ await tester.pumpAndSettle();
});
});
@@ -595,6 +641,7 @@ void main() {
when(() => cubit.poolTickStream).thenAnswer((_) => Stream.value(BigInt.from(174072)));
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("reverse-tokens-reversed")));
await tester.pumpAndSettle();
@@ -616,6 +663,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("min-price-selector")), "1000");
FocusManager.instance.primaryFocus?.unfocus();
@@ -643,6 +691,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("min-price-selector")), "1000");
FocusManager.instance.primaryFocus?.unfocus();
@@ -671,6 +720,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("min-price-selector")), "90000000000");
FocusManager.instance.primaryFocus?.unfocus();
@@ -694,6 +744,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("min-price-selector")), "1200");
FocusManager.instance.primaryFocus?.unfocus();
@@ -721,6 +773,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("min-price-selector")), "0.000000001");
FocusManager.instance.primaryFocus?.unfocus();
@@ -745,6 +798,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("min-price-selector")), "1");
FocusManager.instance.primaryFocus?.unfocus();
@@ -776,6 +830,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("min-price-selector")), "1");
FocusManager.instance.primaryFocus?.unfocus();
@@ -799,6 +854,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("5-percent-range-button")));
await tester.pumpAndSettle();
@@ -823,6 +879,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("5-percent-range-button")));
await tester.pumpAndSettle();
@@ -849,6 +906,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("5-percent-range-button")));
await tester.pumpAndSettle();
@@ -871,6 +929,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("5-percent-range-button")));
await tester.pumpAndSettle();
@@ -894,6 +953,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("20-percent-range-button")));
await tester.pumpAndSettle();
@@ -916,6 +976,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("20-percent-range-button")));
await tester.pumpAndSettle();
@@ -939,6 +1000,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("50-percent-range-button")));
await tester.pumpAndSettle();
@@ -961,6 +1023,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("50-percent-range-button")));
await tester.pumpAndSettle();
@@ -983,6 +1046,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("max-price-selector")), "1");
FocusManager.instance.primaryFocus?.unfocus();
@@ -1007,6 +1071,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("50-percent-range-button")));
await tester.pumpAndSettle();
@@ -1034,6 +1099,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("50-percent-range-button")));
await tester.pumpAndSettle();
@@ -1060,6 +1126,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("min-price-selector")), "1");
FocusManager.instance.primaryFocus?.unfocus();
@@ -1086,14 +1153,18 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+ await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key("min-price-selector")), "2");
FocusManager.instance.primaryFocus?.unfocus();
+ await tester.pumpAndSettle();
+
await tester.enterText(find.byKey(const Key("max-price-selector")), "1");
FocusManager.instance.primaryFocus?.unfocus();
- await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
+ await tester.drag(find.byKey(const Key("deposit-settings-button")), const Offset(0, -500));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key("deposit-button")));
await tester.pumpAndSettle();
@@ -1115,6 +1186,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1139,6 +1211,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1165,6 +1238,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1194,6 +1268,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1221,6 +1296,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1248,6 +1324,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1275,6 +1352,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1304,6 +1382,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1333,6 +1412,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1369,6 +1449,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1404,6 +1485,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1441,6 +1523,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1479,6 +1562,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1515,6 +1599,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1550,6 +1635,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1592,6 +1678,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1632,6 +1719,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1663,6 +1751,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1692,6 +1781,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1727,6 +1817,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -1761,6 +1852,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
});
@@ -1818,7 +1910,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
- await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
+ await tester.pumpAndSettle();
+ await tester.drag(find.byKey(const Key("deposit-settings-button")), const Offset(0, -500));
await tester.pumpAndSettle();
});
},
@@ -1847,7 +1940,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
- await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
+ 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("base-token-input-card")), "1");
@@ -1885,7 +1979,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
- await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
+ 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("quote-token-input-card")), "1");
@@ -1922,7 +2017,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
- await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
+ 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("quote-token-input-card")), "1");
@@ -1962,6 +2058,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -2002,7 +2099,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
- await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
+ 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("quote-token-input-card")), "1");
@@ -2037,7 +2135,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
- await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
+ 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")), "1");
@@ -2074,7 +2173,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
await tester.pumpDeviceBuilder(await goldenBuilder());
- await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
+ 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")), "0.0000001");
@@ -2145,6 +2245,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(null);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -2169,6 +2270,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(null);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -2194,6 +2296,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(null);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -2219,6 +2322,7 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(null);
await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
await tester.drag(find.byKey(const Key("deposit-section")), const Offset(0, -500));
await tester.pumpAndSettle();
@@ -2484,4 +2588,50 @@ void main() {
verifyNever(() => appCubit.updateAppNetwork(any()));
},
);
+
+ zGoldenTest(
+ """When emitting a new pool tick, 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().best24hYield;
+ final currentPriceAsTick = BigInt.from(174072);
+ final nextPriceAsTick = BigInt.from(261892);
+ final poolTickStreamController = StreamController.broadcast();
+
+ 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),
+ );
+ when(() => cubit.selectYield(any(), any())).thenAnswer((_) => Future.value());
+ 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);
+
+ await tester.pumpDeviceBuilder(await goldenBuilder(), wrapper: GoldenConfig.localizationsWrapper());
+ await tester.tap(find.byKey(const Key("yield-card-24h")));
+ 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("quote-token-input-card")), "1");
+ await tester.pumpAndSettle();
+
+ poolTickStreamController.add(nextPriceAsTick);
+ when(() => cubit.latestPoolTick).thenReturn(nextPriceAsTick);
+ await tester.pumpAndSettle();
+ });
+ },
+ );
}
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 be0223a..6241290 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 289d19d..82dbc33 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_base_token_input_enabled_after_loading.png b/test/app/create/deposit/goldens/deposit_page_base_token_input_enabled_after_loading.png
index bebcbfa..b9d38eb 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 4ec6333..6e693b5 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 6ad5752..6241290 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 289d19d..82dbc33 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 3df86de..b75a826 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 56eabef..3ccf344 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 653c1fb..309e2d0 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 49ca770..b4afc0f 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 575cddb..dc9e34d 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 3b331ac..2828102 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 28717d0..2f2d337 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 80f1dcb..39695b3 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 a2c75ad..f7c5856 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 bf3ea4a..0e0361b 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 c639997..3f8898d 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 a2c1227..5328a13 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 c61387a..3d2511a 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 345ae45..b5184a2 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 38a96bf..37e357e 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 eb652be..ff31ff4 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 2d6032b..b9a9a7b 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 e6264d8..93c1b24 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 120641e..5af7b96 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 d88d40b..3383d7a 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 82f0518..a5251f7 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 de57a46..7e93329 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 db55603..0197fa0 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 6d6f6a8..cc44599 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 486c054..2deeea8 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 d88d40b..3383d7a 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 a2c1227..5328a13 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 bf53d2e..ece93f4 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 724ffd1..2f3612a 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 9d9f4f7..33080a1 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 be0223a..6241290 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 d6fc6a2..93bfdee 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 6d7a20b..00fcd6e 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 be0223a..6241290 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 5879452..6fb3f2b 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 5fd0a0d..ce2b92a 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 5a93f42..eac4708 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 be0223a..6241290 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 7c0ce6a..0d835e1 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 cd6b0cf..074c735 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_no_yields.png b/test/app/create/deposit/goldens/deposit_page_no_yields.png
index 1b85c95..b1f0508 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_no_yields.png and b/test/app/create/deposit/goldens/deposit_page_no_yields.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_no_yields_filtered_by_min_liquidity.png b/test/app/create/deposit/goldens/deposit_page_no_yields_filtered_by_min_liquidity.png
index 1460754..8ac83d1 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_no_yields_filtered_by_min_liquidity.png and b/test/app/create/deposit/goldens/deposit_page_no_yields_filtered_by_min_liquidity.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 f1a28c5..6c622f5 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 2301361..a17e4a9 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 5b16a4b..a2ba963 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 80c12b8..af62a99 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 62b0533..d0e52e2 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 62b0533..1e30bd0 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
new file mode 100644
index 0000000..681c5f1
Binary files /dev/null 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_quote_token_input_enabled_after_loading.png b/test/app/create/deposit/goldens/deposit_page_quote_token_input_enabled_after_loading.png
index a2c187d..19e7205 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 df0b72f..a9a8899 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 1483027..8a04412 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 cb1afb5..582b944 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 1ef9298..6b81ddd 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 23c587b..228603c 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 10d90e4..6b81ddd 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 f2d614e..6fb62de 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 b3e6105..cf766ae 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 fdad4a6..304e7a0 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 7b6e3d0..ca9ff06 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 ac07fcd..658d8b5 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 e1be2b9..600413b 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 2796c6b..20cbbfb 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 e2959c3..6706285 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 8b6285c..1d7bfc1 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 7b3bed1..0e2e1ea 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_mobile.png b/test/app/create/deposit/goldens/deposit_page_success_mobile.png
index d4c4086..a6db298 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_timeframe_tooltip.png b/test/app/create/deposit/goldens/deposit_page_timeframe_tooltip.png
index 567291f..e3dd6a7 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/range_selector_is_infinity_increase_price.png b/test/app/create/deposit/widgets/goldens/range_selector_is_infinity_increase_price.png
index ad2038b..5aa5a7c 100644
Binary files a/test/app/create/deposit/widgets/goldens/range_selector_is_infinity_increase_price.png and b/test/app/create/deposit/widgets/goldens/range_selector_is_infinity_increase_price.png differ
diff --git a/test/app/create/deposit/widgets/goldens/range_selector_is_infinity_increase_price_reversed.png b/test/app/create/deposit/widgets/goldens/range_selector_is_infinity_increase_price_reversed.png
index 5c9e4af..5aa5a7c 100644
Binary files a/test/app/create/deposit/widgets/goldens/range_selector_is_infinity_increase_price_reversed.png and b/test/app/create/deposit/widgets/goldens/range_selector_is_infinity_increase_price_reversed.png differ
diff --git a/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_approve_token0_state.png b/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_approve_token0_state.png
index d9caebd..5c0b7c5 100644
Binary files a/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_approve_token0_state.png and b/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_approve_token0_state.png differ
diff --git a/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_token_amounts_change.png b/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_token_amounts_change.png
new file mode 100644
index 0000000..2a1cb5f
Binary files /dev/null and b/test/app/create/deposit/widgets/preview_deposit_modal/goldens/preview_deposit_modal_token_amounts_change.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 7334694..b5849dc 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
@@ -1004,8 +1004,8 @@ void main() {
tickLower: V3PoolConversorsMixinWrapper().tickToClosestValidTick(
tick: V3PoolConversorsMixinWrapper().priceToTick(
price: minPrice,
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
isReversed: false,
),
tickSpacing: currentYield.tickSpacing,
@@ -1052,8 +1052,8 @@ void main() {
tickLower: V3PoolConversorsMixinWrapper().tickToClosestValidTick(
tick: V3PoolConversorsMixinWrapper().priceToTick(
price: maxPrice,
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
isReversed: isReversed,
),
tickSpacing: currentYield.tickSpacing,
@@ -1177,8 +1177,8 @@ void main() {
tickUpper: V3PoolConversorsMixinWrapper().tickToClosestValidTick(
tick: V3PoolConversorsMixinWrapper().priceToTick(
price: maxPrice,
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
isReversed: false,
),
tickSpacing: currentYield.tickSpacing,
@@ -1224,8 +1224,8 @@ void main() {
tickUpper: V3PoolConversorsMixinWrapper().tickToClosestValidTick(
tick: V3PoolConversorsMixinWrapper().priceToTick(
price: minPrice,
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
isReversed: isReversed,
),
tickSpacing: currentYield.tickSpacing,
@@ -1702,8 +1702,8 @@ void main() {
verify(() => zupAnalytics.logDeposit(
depositedYield: currentYield,
- amount0Formatted: token0amount.parseTokenAmount(decimals: currentYield.token0.decimals),
- amount1Formatted: token1amount.parseTokenAmount(decimals: currentYield.token1.decimals),
+ amount0Formatted: token0amount.parseTokenAmount(decimals: currentYield.token0NetworkDecimals),
+ amount1Formatted: token1amount.parseTokenAmount(decimals: currentYield.token1NetworkDecimals),
walletAddress: userAddress,
)).called(1);
},
@@ -1936,16 +1936,16 @@ void main() {
final tickLower = V3PoolConversorsMixinWrapper().tickToClosestValidTick(
tick: V3PoolConversorsMixinWrapper().priceToTick(
price: minPrice,
- poolToken0Decimals: currentYield0.token0.decimals,
- poolToken1Decimals: currentYield0.token1.decimals,
+ poolToken0Decimals: currentYield0.token0NetworkDecimals,
+ poolToken1Decimals: currentYield0.token1NetworkDecimals,
),
tickSpacing: currentYield0.tickSpacing);
final tickUpper = V3PoolConversorsMixinWrapper().tickToClosestValidTick(
tick: V3PoolConversorsMixinWrapper().priceToTick(
price: maxPrice,
- poolToken0Decimals: currentYield0.token0.decimals,
- poolToken1Decimals: currentYield0.token1.decimals,
+ poolToken0Decimals: currentYield0.token0NetworkDecimals,
+ poolToken1Decimals: currentYield0.token1NetworkDecimals,
),
tickSpacing: currentYield0.tickSpacing);
@@ -1985,7 +1985,6 @@ void main() {
tickLower: tickLower,
tickUpper: tickUpper,
recipient: recipient,
- currentPoolTick: initialPoolTick,
),
).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 1581893..3315a32 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
@@ -122,8 +122,8 @@ void main() {
bool isReversed = false,
({bool isInfinity, double price}) minPrice = (isInfinity: false, price: 1200),
({bool isInfinity, double price}) maxPrice = (isInfinity: false, price: 3000),
- double token0DepositAmount = 1,
- double token1DepositAmount = 3,
+ TextEditingController? token0DepositAmountController,
+ TextEditingController? token1DepositAmountController,
Duration deadline = const Duration(minutes: 30),
Slippage slippage = Slippage.halfPercent,
}) =>
@@ -144,8 +144,8 @@ void main() {
isReversed: isReversed,
minPrice: minPrice,
maxPrice: maxPrice,
- token0DepositAmount: token0DepositAmount,
- token1DepositAmount: token1DepositAmount,
+ token0DepositAmountController: token0DepositAmountController ?? TextEditingController(text: "1"),
+ token1DepositAmountController: token1DepositAmountController ?? TextEditingController(text: "3"),
),
));
});
@@ -309,8 +309,8 @@ void main() {
final currentPriceAsTick = V3PoolConversorsMixinWrapper().priceToTick(
price: currentPrice,
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
);
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
@@ -335,8 +335,8 @@ void main() {
final currentPriceAsTick = V3PoolConversorsMixinWrapper().priceToTick(
price: currentPrice,
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
);
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
@@ -364,8 +364,8 @@ void main() {
final currentPriceAsTick = V3PoolConversorsMixinWrapper().priceToTick(
price: currentPrice,
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
);
when(() => cubit.latestPoolTick).thenReturn(currentPriceAsTick);
@@ -497,7 +497,9 @@ void main() {
});
await tester.pumpDeviceBuilder(
- await goldenBuilder(token0DepositAmount: depositAmount, token1DepositAmount: 0),
+ await goldenBuilder(
+ token0DepositAmountController: TextEditingController(text: depositAmount.toString()),
+ token1DepositAmountController: TextEditingController(text: "0")),
wrapper: GoldenConfig.localizationsWrapper(),
);
await tester.pumpAndSettle();
@@ -530,7 +532,9 @@ void main() {
});
await tester.pumpDeviceBuilder(
- await goldenBuilder(token0DepositAmount: depositAmount, token1DepositAmount: 0),
+ await goldenBuilder(
+ token0DepositAmountController: TextEditingController(text: depositAmount.toString()),
+ token1DepositAmountController: TextEditingController(text: "0")),
wrapper: GoldenConfig.localizationsWrapper(),
);
await tester.pumpAndSettle();
@@ -541,7 +545,7 @@ void main() {
verify(
() => cubit.approveToken(
currentYield.token0,
- depositAmount.parseTokenAmount(decimals: currentYield.token0.decimals),
+ depositAmount.parseTokenAmount(decimals: currentYield.token0NetworkDecimals),
),
).called(1);
},
@@ -558,20 +562,22 @@ void main() {
when(() => cubit.state).thenReturn(
PreviewDepositModalState.initial(
- token0Allowance: depositAmount.parseTokenAmount(decimals: currentYield.token0.decimals),
+ token0Allowance: depositAmount.parseTokenAmount(decimals: currentYield.token0NetworkDecimals),
token1Allowance: token1Allowance,
),
);
when(() => cubit.stream).thenAnswer((_) {
return Stream.value(PreviewDepositModalState.initial(
- token0Allowance: depositAmount.parseTokenAmount(decimals: currentYield.token0.decimals),
+ token0Allowance: depositAmount.parseTokenAmount(decimals: currentYield.token0NetworkDecimals),
token1Allowance: token1Allowance,
));
});
await tester.pumpDeviceBuilder(
- await goldenBuilder(token0DepositAmount: depositAmount, token1DepositAmount: depositAmount),
+ await goldenBuilder(
+ token0DepositAmountController: TextEditingController(text: depositAmount.toString()),
+ token1DepositAmountController: TextEditingController(text: depositAmount.toString())),
wrapper: GoldenConfig.localizationsWrapper(),
);
await tester.pumpAndSettle();
@@ -593,20 +599,22 @@ void main() {
when(() => cubit.state).thenReturn(
PreviewDepositModalState.initial(
- token0Allowance: depositAmount.parseTokenAmount(decimals: currentYield.token0.decimals),
+ token0Allowance: depositAmount.parseTokenAmount(decimals: currentYield.token0NetworkDecimals),
token1Allowance: token1Allowance,
),
);
when(() => cubit.stream).thenAnswer((_) {
return Stream.value(PreviewDepositModalState.initial(
- token0Allowance: depositAmount.parseTokenAmount(decimals: currentYield.token0.decimals),
+ token0Allowance: depositAmount.parseTokenAmount(decimals: currentYield.token0NetworkDecimals),
token1Allowance: token1Allowance,
));
});
await tester.pumpDeviceBuilder(
- await goldenBuilder(token0DepositAmount: depositAmount, token1DepositAmount: depositAmount),
+ await goldenBuilder(
+ token0DepositAmountController: TextEditingController(text: depositAmount.toString()),
+ token1DepositAmountController: TextEditingController(text: depositAmount.toString())),
wrapper: GoldenConfig.localizationsWrapper(),
);
await tester.pumpAndSettle();
@@ -617,7 +625,7 @@ void main() {
verify(
() => cubit.approveToken(
currentYield.token1,
- depositAmount.parseTokenAmount(decimals: currentYield.token1.decimals),
+ depositAmount.parseTokenAmount(decimals: currentYield.token1NetworkDecimals),
),
).called(1);
},
@@ -629,8 +637,8 @@ void main() {
in the deposit state""",
goldenFileName: "preview_deposit_modal_deposit_state",
(tester) async {
- final token0Allowance = 400.parseTokenAmount(decimals: currentYield.token0.decimals);
- final token1Allowance = 1200.parseTokenAmount(decimals: currentYield.token1.decimals);
+ final token0Allowance = 400.parseTokenAmount(decimals: currentYield.token0NetworkDecimals);
+ final token1Allowance = 1200.parseTokenAmount(decimals: currentYield.token1NetworkDecimals);
const deposit0Amount = 100.2;
const deposit1Amount = 110.2;
@@ -650,7 +658,9 @@ void main() {
});
await tester.pumpDeviceBuilder(
- await goldenBuilder(token0DepositAmount: deposit0Amount, token1DepositAmount: deposit1Amount),
+ await goldenBuilder(
+ token0DepositAmountController: TextEditingController(text: deposit0Amount.toString()),
+ token1DepositAmountController: TextEditingController(text: deposit1Amount.toString())),
wrapper: GoldenConfig.localizationsWrapper(),
);
await tester.pumpAndSettle();
@@ -663,8 +673,8 @@ void main() {
in the deposit state. Once the deposit button is clicked, it should call
the deposit function in the cubit passing the correct params (got from the constructor)""",
(tester) async {
- final token0Allowance = 400.parseTokenAmount(decimals: currentYield.token0.decimals);
- final token1Allowance = 1200.parseTokenAmount(decimals: currentYield.token1.decimals);
+ final token0Allowance = 400.parseTokenAmount(decimals: currentYield.token0NetworkDecimals);
+ final token1Allowance = 1200.parseTokenAmount(decimals: currentYield.token1NetworkDecimals);
const deposit0Amount = 100.2;
const deposit1Amount = 110.2;
@@ -692,8 +702,8 @@ void main() {
await tester.pumpDeviceBuilder(
await goldenBuilder(
- token0DepositAmount: deposit0Amount,
- token1DepositAmount: deposit1Amount,
+ token0DepositAmountController: TextEditingController(text: deposit0Amount.toString()),
+ token1DepositAmountController: TextEditingController(text: deposit1Amount.toString()),
deadline: deadline,
isReversed: isReversed,
minPrice: (isInfinity: isMinPriceInfinity, price: minPrice),
@@ -716,8 +726,8 @@ void main() {
maxPrice: maxPrice,
minPrice: minPrice,
slippage: slippage,
- token0Amount: deposit0Amount.parseTokenAmount(decimals: currentYield.token0.decimals),
- token1Amount: deposit1Amount.parseTokenAmount(decimals: currentYield.token1.decimals),
+ token0Amount: deposit0Amount.parseTokenAmount(decimals: currentYield.token0NetworkDecimals),
+ token1Amount: deposit1Amount.parseTokenAmount(decimals: currentYield.token1NetworkDecimals),
),
).called(1);
},
@@ -730,8 +740,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(
V3PoolConversorsMixinWrapper().priceToTick(
price: 0.01, // It should be shown in the card (or very close to it)
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
isReversed: false,
),
);
@@ -748,8 +758,8 @@ void main() {
when(() => cubit.latestPoolTick).thenReturn(
V3PoolConversorsMixinWrapper().priceToTick(
price: 1200, // It should be shown in the card (or very close to it)
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
isReversed: true,
),
);
@@ -768,8 +778,8 @@ void main() {
const newPrice = 0.02632; // It should be shown in the card (or very close to it)
final newPriceAsTick = V3PoolConversorsMixinWrapper().priceToTick(
price: newPrice,
- poolToken0Decimals: currentYield.token0.decimals,
- poolToken1Decimals: currentYield.token1.decimals,
+ poolToken0Decimals: currentYield.token0NetworkDecimals,
+ poolToken1Decimals: currentYield.token1NetworkDecimals,
isReversed: false,
);
@@ -929,8 +939,8 @@ void main() {
isReversed: true,
minPrice: (isInfinity: true, price: 0),
maxPrice: (isInfinity: true, price: 0),
- token0DepositAmount: 1200,
- token1DepositAmount: 4300,
+ token0DepositAmountController: TextEditingController(text: "1200"),
+ token1DepositAmountController: TextEditingController(text: "4300"),
deadline: const Duration(minutes: 30),
maxSlippage: Slippage.halfPercent,
).show(context, currentPoolTick: BigInt.from(121475));
@@ -962,8 +972,8 @@ void main() {
isReversed: true,
minPrice: (isInfinity: true, price: 0),
maxPrice: (isInfinity: true, price: 0),
- token0DepositAmount: 1200,
- token1DepositAmount: 4300,
+ token0DepositAmountController: TextEditingController(text: "1200"),
+ token1DepositAmountController: TextEditingController(text: "4300"),
deadline: const Duration(minutes: 30),
maxSlippage: Slippage.halfPercent,
).show(context, currentPoolTick: BigInt.from(121475));
@@ -1019,4 +1029,37 @@ void main() {
await tester.pumpAndSettle();
},
);
+
+ zGoldenTest("When the token amounts controllers change its amount, it should reflect in the UI",
+ goldenFileName: "preview_deposit_modal_token_amounts_change", (tester) async {
+ final token0DepositAmountController = TextEditingController(text: "0");
+ final token1DepositAmountController = TextEditingController(text: "0");
+
+ when(() => cubit.state).thenReturn(
+ PreviewDepositModalState.initial(
+ token0Allowance: EthereumConstants.uint256Max,
+ token1Allowance: EthereumConstants.uint256Max,
+ ),
+ );
+
+ when(() => cubit.stream).thenAnswer((_) {
+ return Stream.value(PreviewDepositModalState.initial(
+ token0Allowance: EthereumConstants.uint256Max,
+ token1Allowance: EthereumConstants.uint256Max,
+ ));
+ });
+
+ await tester.pumpDeviceBuilder(
+ await goldenBuilder(
+ token0DepositAmountController: token0DepositAmountController,
+ token1DepositAmountController: token1DepositAmountController,
+ ),
+ wrapper: GoldenConfig.localizationsWrapper(scaffoldMessengerKey: scaffoldMessengerKey));
+
+ await tester.pumpAndSettle();
+
+ token0DepositAmountController.text = "1200";
+ token1DepositAmountController.text = "4300";
+ await tester.pumpAndSettle();
+ });
}
diff --git a/test/app/create/deposit/widgets/range_selector_test.dart b/test/app/create/deposit/widgets/range_selector_test.dart
index 00d56cb..2464733 100644
--- a/test/app/create/deposit/widgets/range_selector_test.dart
+++ b/test/app/create/deposit/widgets/range_selector_test.dart
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:zup_app/app/create/deposit/widgets/range_selector.dart';
-import 'package:zup_app/core/dtos/token_dto.dart';
import '../../../../golden_config.dart';
@@ -11,8 +10,8 @@ void main() {
Key? key,
bool isReversed = false,
Function(double price)? onPriceChanged,
- TokenDto? poolToken0,
- TokenDto? poolToken1,
+ int? poolToken0Decimals,
+ int? poolToken1Decimals,
int tickSpacing = 10,
RangeSelectorType type = RangeSelectorType.minPrice,
double? initialPrice,
@@ -32,8 +31,8 @@ void main() {
displayQuoteTokenSymbol: "Token B",
isReversed: isReversed,
onPriceChanged: onPriceChanged ?? (_) {},
- poolToken0: poolToken0 ?? TokenDto.fixture().copyWith(symbol: "Token A"),
- poolToken1: poolToken1 ?? TokenDto.fixture().copyWith(symbol: "Token B"),
+ poolToken0Decimals: poolToken0Decimals ?? 18,
+ poolToken1Decimals: poolToken0Decimals ?? 18,
tickSpacing: tickSpacing,
type: type,
initialPrice: initialPrice,
@@ -58,11 +57,7 @@ void main() {
zGoldenTest("When the `isReversed` param is true, it should reverse the tokens in the widget",
goldenFileName: "range_selector_reversed", (tester) async {
return tester.pumpDeviceBuilder(
- await goldenBuilder(
- isReversed: true,
- poolToken0: TokenDto.fixture().copyWith(symbol: "Token 0"),
- poolToken1: TokenDto.fixture().copyWith(symbol: "Token 1"),
- ),
+ await goldenBuilder(isReversed: true),
);
});
@@ -304,13 +299,13 @@ void main() {
"When the price is infinity, and click to increase, the price should increase to the minimum price based on the tick spacing",
goldenFileName: "range_selector_is_infinity_increase_price",
(tester) async {
- const expectedIncreasedPrice = 1.0010004501200209e-12;
+ const expectedIncreasedPrice = 9.996040641477102e-19;
double actualIncreasedPrice = 0;
await tester.pumpDeviceBuilder(await goldenBuilder(
isInfinity: true,
- poolToken0: TokenDto.fixture().copyWith(decimals: 6),
- poolToken1: TokenDto.fixture().copyWith(decimals: 18),
+ poolToken0Decimals: 6,
+ poolToken1Decimals: 18,
onPriceChanged: (price) {
actualIncreasedPrice = price;
},
@@ -328,14 +323,14 @@ void main() {
the price should increase to the minimum price based on the tick spacing""",
goldenFileName: "range_selector_is_infinity_increase_price_reversed",
(tester) async {
- const expectedIncreasedPrice = 1.0008055719626048e-12;
+ const expectedIncreasedPrice = 9.996040641477102e-19;
double actualIncreasedPrice = 0;
await tester.pumpDeviceBuilder(await goldenBuilder(
isInfinity: true,
isReversed: true,
- poolToken0: TokenDto.fixture().copyWith(decimals: 6),
- poolToken1: TokenDto.fixture().copyWith(decimals: 18),
+ poolToken0Decimals: 6,
+ poolToken1Decimals: 18,
onPriceChanged: (price) {
actualIncreasedPrice = price;
},
@@ -359,8 +354,8 @@ void main() {
await tester.pumpDeviceBuilder(await goldenBuilder(
isInfinity: true,
isReversed: true,
- poolToken0: TokenDto.fixture().copyWith(decimals: 6),
- poolToken1: TokenDto.fixture().copyWith(decimals: 18),
+ poolToken0Decimals: 6,
+ poolToken1Decimals: 18,
onPriceChanged: (price) {
actualIncreasedPrice = price;
},
@@ -382,8 +377,8 @@ void main() {
await tester.pumpDeviceBuilder(await goldenBuilder(
isInfinity: true,
- poolToken0: TokenDto.fixture().copyWith(decimals: 6),
- poolToken1: TokenDto.fixture().copyWith(decimals: 18),
+ poolToken0Decimals: 6,
+ poolToken1Decimals: 18,
onPriceChanged: (price) {
actualIncreasedPrice = price;
},
diff --git a/test/app/create/goldens/create_page_initial_stage.png b/test/app/create/goldens/create_page_initial_stage.png
index 2c36037..3a276bb 100644
Binary files a/test/app/create/goldens/create_page_initial_stage.png and b/test/app/create/goldens/create_page_initial_stage.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_change_a_token_to_same_token_as_b.png b/test/app/create/goldens/create_page_select_tokens_stage_change_a_token_to_same_token_as_b.png
index 013ee4c..10918e7 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_change_a_token_to_same_token_as_b.png and b/test/app/create/goldens/create_page_select_tokens_stage_change_a_token_to_same_token_as_b.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_change_b_token_to_same_token_as_a.png b/test/app/create/goldens/create_page_select_tokens_stage_change_b_token_to_same_token_as_a.png
index 42a26ae..6af423e 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_change_b_token_to_same_token_as_a.png and b/test/app/create/goldens/create_page_select_tokens_stage_change_b_token_to_same_token_as_a.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_default_a_token.png b/test/app/create/goldens/create_page_select_tokens_stage_default_a_token.png
index 2c36037..3a276bb 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_default_a_token.png and b/test/app/create/goldens/create_page_select_tokens_stage_default_a_token.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_mobile.png b/test/app/create/goldens/create_page_select_tokens_stage_mobile.png
index 1c452b6..502018b 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_mobile.png and b/test/app/create/goldens/create_page_select_tokens_stage_mobile.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_add_badge.png b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_add_badge.png
index 9f74f5e..bd3a0a6 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_add_badge.png and b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_add_badge.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_default.png b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_default.png
index 50a4715..282e363 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_default.png and b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_default.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_not_default.png b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_not_default.png
index 9f74f5e..bd3a0a6 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_not_default.png and b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_not_default.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_open.png b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_open.png
index ebcd14b..9bd5edf 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_open.png and b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_open.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_remove_badge.png b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_remove_badge.png
index 50a4715..282e363 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_remove_badge.png and b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_remove_badge.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_reset_tokens_from_network.png b/test/app/create/goldens/create_page_select_tokens_stage_reset_tokens_from_network.png
index 9f74f5e..bd3a0a6 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_reset_tokens_from_network.png and b/test/app/create/goldens/create_page_select_tokens_stage_reset_tokens_from_network.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_token_a_selected_disabled_button.png b/test/app/create/goldens/create_page_select_tokens_stage_token_a_selected_disabled_button.png
index 013ee4c..10918e7 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_token_a_selected_disabled_button.png and b/test/app/create/goldens/create_page_select_tokens_stage_token_a_selected_disabled_button.png differ
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_token_enabled_button.png b/test/app/create/goldens/create_page_select_tokens_stage_token_enabled_button.png
index 1ca3ee3..d03fc5e 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_token_enabled_button.png and b/test/app/create/goldens/create_page_select_tokens_stage_token_enabled_button.png differ
diff --git a/test/app/create/widgets/create_page_settings_dropdown_test.dart b/test/app/create/widgets/create_page_settings_dropdown_test.dart
index ebfe786..4518a9d 100644
--- a/test/app/create/widgets/create_page_settings_dropdown_test.dart
+++ b/test/app/create/widgets/create_page_settings_dropdown_test.dart
@@ -2,7 +2,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:mocktail/mocktail.dart';
-import 'package:zup_app/app/create/widgets/create_page_settings_dropdown.dart';
+import 'package:zup_app/app/create/widgets/create_page_settings_dropdown/create_page_settings_dropdown.dart';
import 'package:zup_app/core/cache.dart';
import 'package:zup_app/core/debouncer.dart';
import 'package:zup_app/core/dtos/pool_search_settings_dto.dart';
diff --git a/test/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_cubit_test.dart b/test/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_cubit_test.dart
new file mode 100644
index 0000000..0e248c0
--- /dev/null
+++ b/test/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_cubit_test.dart
@@ -0,0 +1,108 @@
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mocktail/mocktail.dart';
+import 'package:zup_app/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_cubit.dart';
+import 'package:zup_app/core/dtos/protocol_dto.dart';
+import 'package:zup_app/core/repositories/protocol_repository.dart';
+import 'package:zup_core/zup_singleton_cache.dart';
+
+import '../../../../mocks.dart';
+
+void main() {
+ late ExchangesFilterDropdownButtonCubit sut;
+ late ProtocolRepository protocolRepository;
+ late ZupSingletonCache zupSingletonCache;
+
+ setUp(() {
+ protocolRepository = ProtocolRepositoryMock();
+ zupSingletonCache = ZupSingletonCache.shared;
+
+ sut = ExchangesFilterDropdownButtonCubit(protocolRepository, zupSingletonCache);
+
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer((_) => Future.value([]));
+ });
+
+ tearDown(() => zupSingletonCache.clear());
+
+ test("When calling 'getSupportedProtocols' it should emit the loading state", () async {
+ expectLater(sut.stream, emits(const ExchangesFilterDropdownButtonState.loading()));
+
+ await sut.getSupportedProtocols();
+ });
+
+ test(
+ "When calling `getSupportedProtocols` and it succeds, it should sort the list by name",
+ () async {
+ final protocolListAnswer = [
+ const ProtocolDto(name: "C"),
+ const ProtocolDto(name: "A"),
+ const ProtocolDto(name: "B"),
+ const ProtocolDto(name: "A"),
+ ];
+
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer((_) => Future.value(protocolListAnswer));
+
+ await sut.getSupportedProtocols();
+
+ expect(
+ sut.protocols,
+ protocolListAnswer..sort((a, b) => a.name.compareTo(b.name)),
+ );
+ },
+ );
+
+ test(
+ """When calling `getSupportedProtocols` and it succeds, it should emit success state with
+ the sorted list by name""",
+ () async {
+ final protocolListAnswer = [
+ const ProtocolDto(name: "C"),
+ const ProtocolDto(name: "A"),
+ const ProtocolDto(name: "B"),
+ const ProtocolDto(name: "A"),
+ ];
+
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer((_) => Future.value(protocolListAnswer));
+
+ await sut.getSupportedProtocols();
+
+ expect(
+ sut.state,
+ ExchangesFilterDropdownButtonState.success(protocolListAnswer..sort((a, b) => a.name.compareTo(b.name))),
+ );
+ },
+ );
+
+ test("When an error happens while calling `getSupportedProtocols`, it should emit error state`", () async {
+ when(() => protocolRepository.getAllSupportedProtocols()).thenThrow(Exception());
+
+ await sut.getSupportedProtocols();
+
+ expect(sut.state, const ExchangesFilterDropdownButtonState.error());
+ });
+
+ test(
+ """When calling `getSupportedProtocols` it should use the zupSingletonCache
+ to make the request ands cache it with no experation""",
+ () async {
+ zupSingletonCache = ZupSingletonCacheMock();
+ sut = ExchangesFilterDropdownButtonCubit(protocolRepository, zupSingletonCache);
+
+ when(() => zupSingletonCache.clear()).thenAnswer((_) => Future.value());
+ when(() => zupSingletonCache.run>(
+ any(),
+ key: any(named: "key"),
+ expiration: any(named: "expiration"),
+ ignoreCache: any(named: "ignoreCache"),
+ )).thenAnswer((_) => Future.value([]));
+
+ await sut.getSupportedProtocols();
+
+ verify(() => zupSingletonCache.run>(
+ any(),
+ key: "zup-supported-protocols",
+ expiration: null,
+ ignoreCache: false,
+ )).called(1);
+ },
+ );
+}
diff --git a/test/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_test.dart b/test/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_test.dart
new file mode 100644
index 0000000..073d8ae
--- /dev/null
+++ b/test/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button_test.dart
@@ -0,0 +1,227 @@
+import 'package:flutter/widgets.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:golden_toolkit/golden_toolkit.dart';
+import 'package:mocktail/mocktail.dart';
+import 'package:zup_app/app/create/widgets/exchanges_filter_dropdown_button/exchanges_filter_dropdown_button.dart';
+import 'package:zup_app/core/cache.dart';
+import 'package:zup_app/core/dtos/protocol_dto.dart';
+import 'package:zup_app/core/injections.dart';
+import 'package:zup_app/core/repositories/protocol_repository.dart';
+import 'package:zup_app/widgets/zup_cached_image.dart';
+import 'package:zup_core/zup_singleton_cache.dart';
+
+import '../../../../golden_config.dart';
+import '../../../../mocks.dart';
+
+void main() {
+ late ZupSingletonCache zupSingletonCache;
+ late ProtocolRepository protocolRepository;
+ late ZupCachedImage zupCachedImage;
+ late Cache cache;
+
+ setUp(() {
+ zupSingletonCache = ZupSingletonCache.shared;
+ protocolRepository = ProtocolRepositoryMock();
+ zupCachedImage = mockZupCachedImage();
+ cache = CacheMock();
+
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer((_) => Future.value([]));
+ when(() => cache.blockedProtocolsIds).thenReturn([]);
+
+ inject.registerFactory(() => zupSingletonCache);
+ inject.registerFactory(() => protocolRepository);
+ inject.registerFactory(() => zupCachedImage);
+ inject.registerFactory(() => cache);
+ });
+
+ tearDown(() {
+ inject.reset();
+ zupSingletonCache.clear();
+ });
+
+ Future goldenBuilder() async => await goldenDeviceBuilder(
+ const Center(child: ExchangesFilterDropdownButton()),
+ );
+
+ zGoldenTest("""When the widget is created, it should call the cubit to get the exchanges
+ and show a preview of the exchanges count""", goldenFileName: "exchanges_filter_dropdown_button", (tester) async {
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer((_) async => [
+ const ProtocolDto(name: "C"),
+ const ProtocolDto(name: "A"),
+ const ProtocolDto(name: "B"),
+ const ProtocolDto(name: "A"),
+ ]);
+
+ await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+
+ verify(() => protocolRepository.getAllSupportedProtocols()).called(1);
+ });
+
+ zGoldenTest(
+ """When the widget is created, it should call the cubit to get the exchanges.
+ If some of the exchanges are blocked by the user, the button should show a counter with
+ the number of total exchanages slash blocked exchanges""",
+ goldenFileName: "exchanges_filter_dropdown_button_blocked_exchanges_counter",
+ (tester) async {
+ final blockedProtocolsIds = ["32983", "sag", "nnnn", "dale"];
+ when(() => cache.blockedProtocolsIds).thenReturn(blockedProtocolsIds);
+
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer((_) async => [
+ ProtocolDto(name: "C", rawId: blockedProtocolsIds[0]),
+ ProtocolDto(name: "A", rawId: blockedProtocolsIds[1]),
+ ProtocolDto(name: "B", rawId: blockedProtocolsIds[2]),
+ const ProtocolDto(name: "A", rawId: "some other id not blocked"),
+ ]);
+
+ await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+ },
+ );
+
+ zGoldenTest(
+ """When the cubit state is error, it should show only "Exchanges" in the button,
+ without the counter""",
+ goldenFileName: "exchanges_filter_dropdown_button_error_counter",
+ (tester) async {
+ when(() => protocolRepository.getAllSupportedProtocols()).thenThrow(Exception());
+
+ await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+ },
+ );
+ zGoldenTest(
+ """When the cubit state is error, and the user clicks the button,
+ it should show a snackbar saying to try to refresh the page""",
+ goldenFileName: "exchanges_filter_dropdown_button_error_click",
+ (tester) async {
+ when(() => protocolRepository.getAllSupportedProtocols()).thenThrow(Exception());
+
+ await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+
+ await tester.tap(find.byKey(const Key("exchanges-filter-dropdown-button")));
+ await tester.pumpAndSettle();
+ },
+ );
+
+ zGoldenTest(
+ """When the state is success, and the user clicks the button, it should
+ show a dropdown to select and unselect exchanges""",
+ goldenFileName: "exchanges_filter_dropdown_button_click",
+ (tester) async {
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer(
+ (_) async => [
+ const ProtocolDto(name: "C"),
+ const ProtocolDto(name: "A"),
+ const ProtocolDto(name: "B"),
+ const ProtocolDto(name: "A"),
+ ],
+ );
+
+ await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+
+ await tester.tap(find.byKey(const Key("exchanges-filter-dropdown-button")));
+ await tester.pumpAndSettle();
+ },
+ );
+
+ zGoldenTest(
+ """When the state is success, and the user clicks the button, it should
+ show a dropdown to select and unselect exchanges. The exchanges that
+ are blocked already in the cache, should be unchecked""",
+ goldenFileName: "exchanges_filter_dropdown_button_click_with_blocked_exchanges",
+ (tester) async {
+ final blockedProtocolsIds = ["32983", "sag", "nnnn", "dale"];
+ when(() => cache.blockedProtocolsIds).thenReturn(blockedProtocolsIds);
+
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer(
+ (_) async => [
+ ProtocolDto(name: "A", rawId: blockedProtocolsIds[0]),
+ const ProtocolDto(name: "B", rawId: "some other id not blocked"),
+ ProtocolDto(name: "C", rawId: blockedProtocolsIds[2]),
+ const ProtocolDto(name: "D", rawId: "some other id not blocked"),
+ ],
+ );
+
+ await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+
+ await tester.tap(find.byKey(const Key("exchanges-filter-dropdown-button")));
+ await tester.pumpAndSettle();
+ },
+ );
+
+ zGoldenTest(
+ """When the state is success, and the user clicks the button, it should
+ show a dropdown to select and unselect exchanges. When the user clicks
+ on a checked exchange, it should save to the cache as blocked exchange""",
+ (tester) async {
+ final blockedProtocolsIds = ["32983", "sag", "nnnn", "dale"];
+ final allProtocols = [
+ ProtocolDto(name: "A", rawId: blockedProtocolsIds[0]),
+ const ProtocolDto(name: "B", rawId: "some other id not blocked"),
+ ProtocolDto(name: "C", rawId: blockedProtocolsIds[2]),
+ const ProtocolDto(name: "D", rawId: "some other id not blocked"),
+ ];
+
+ when(() => cache.saveBlockedProtocolIds(blockedProtocolIds: any(named: "blockedProtocolIds"))).thenAnswer(
+ (_) async => {},
+ );
+ when(() => cache.blockedProtocolsIds).thenReturn(blockedProtocolsIds);
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer((_) async => allProtocols);
+
+ await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+
+ await tester.tap(find.byKey(const Key("exchanges-filter-dropdown-button")));
+ await tester.pumpAndSettle();
+
+ await tester.tap(find.byKey(const Key("checkbox-item-1")));
+ await tester.pumpAndSettle();
+
+ verify(
+ () => cache.saveBlockedProtocolIds(blockedProtocolIds: [
+ blockedProtocolsIds[0],
+ "some other id not blocked",
+ blockedProtocolsIds[2],
+ ]),
+ ).called(1);
+ },
+ );
+
+ zGoldenTest(
+ """When the state is success, and the user clicks the button, it should
+ show a dropdown to select and unselect exchanges. When the user clicks
+ on a unchecked exchange, it should remove it from the saved cached""",
+ (tester) async {
+ final blockedProtocolsIds = ["32983", "sag", "nnnn", "dale"];
+ final allProtocols = [
+ ProtocolDto(name: "A", rawId: blockedProtocolsIds[0]),
+ const ProtocolDto(name: "B", rawId: "some other id not blocked"),
+ ProtocolDto(name: "C", rawId: blockedProtocolsIds[2]),
+ const ProtocolDto(name: "D", rawId: "some other id not blocked"),
+ ];
+
+ when(() => cache.saveBlockedProtocolIds(blockedProtocolIds: any(named: "blockedProtocolIds"))).thenAnswer(
+ (_) async => {},
+ );
+ when(() => cache.blockedProtocolsIds).thenReturn(blockedProtocolsIds);
+ when(() => protocolRepository.getAllSupportedProtocols()).thenAnswer((_) async => allProtocols);
+
+ await tester.pumpDeviceBuilder(await goldenBuilder());
+ await tester.pumpAndSettle();
+
+ await tester.tap(find.byKey(const Key("exchanges-filter-dropdown-button")));
+ await tester.pumpAndSettle();
+
+ await tester.tap(find.byKey(const Key("checkbox-item-0")));
+ await tester.pumpAndSettle();
+
+ verify(
+ () => cache.saveBlockedProtocolIds(blockedProtocolIds: ["nnnn"]),
+ ).called(1);
+ },
+ );
+}
diff --git a/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button.png b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button.png
new file mode 100644
index 0000000..5ef1e99
Binary files /dev/null and b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button.png differ
diff --git a/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_blocked_exchanges_counter.png b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_blocked_exchanges_counter.png
new file mode 100644
index 0000000..5c14597
Binary files /dev/null and b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_blocked_exchanges_counter.png differ
diff --git a/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_click.png b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_click.png
new file mode 100644
index 0000000..6047457
Binary files /dev/null and b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_click.png differ
diff --git a/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_click_with_blocked_exchanges.png b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_click_with_blocked_exchanges.png
new file mode 100644
index 0000000..963cf9a
Binary files /dev/null and b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_click_with_blocked_exchanges.png differ
diff --git a/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_error_click.png b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_error_click.png
new file mode 100644
index 0000000..cf703ac
Binary files /dev/null and b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_error_click.png differ
diff --git a/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_error_counter.png b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_error_counter.png
new file mode 100644
index 0000000..79c6c06
Binary files /dev/null and b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_error_counter.png differ
diff --git a/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_loading.png b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_loading.png
new file mode 100644
index 0000000..763cf1d
Binary files /dev/null and b/test/app/create/widgets/exchanges_filter_dropdown_button/goldens/exchanges_filter_dropdown_button_loading.png differ
diff --git a/test/core/cache_test.dart b/test/core/cache_test.dart
index abb79ef..db7635d 100644
--- a/test/core/cache_test.dart
+++ b/test/core/cache_test.dart
@@ -162,4 +162,22 @@ void main() {
expect(result, true);
verify(() => sharedPreferencesWithCache.getBool(CacheKey.areCookiesConsented.key)).called(1);
});
+
+ test("when calling 'blockedProtocolsIds' it should get under the correct key", () {
+ when(() => sharedPreferencesWithCache.getStringList(any())).thenReturn(["1", "2"]);
+
+ final result = sut.blockedProtocolsIds;
+
+ expect(result, ["1", "2"]);
+ verify(() => sharedPreferencesWithCache.getStringList(CacheKey.blockedProtocolsIds.key)).called(1);
+ });
+
+ test("when calling 'saveBlockedProtocolsIds' it should save under the correct key", () async {
+ when(() => sharedPreferencesWithCache.setStringList(any(), any())).thenAnswer((_) async => true);
+
+ final ids = ["1", "2"];
+ await sut.saveBlockedProtocolIds(blockedProtocolIds: ids);
+
+ verify(() => sharedPreferencesWithCache.setStringList(CacheKey.blockedProtocolsIds.key, ids)).called(1);
+ });
}
diff --git a/test/core/enums/goldens/bnb_network_icon.png b/test/core/enums/goldens/bnb_network_icon.png
new file mode 100644
index 0000000..198aeeb
Binary files /dev/null and b/test/core/enums/goldens/bnb_network_icon.png differ
diff --git a/test/core/enums/networks_test.dart b/test/core/enums/networks_test.dart
index 41fa609..1e77904 100644
--- a/test/core/enums/networks_test.dart
+++ b/test/core/enums/networks_test.dart
@@ -3,7 +3,6 @@ import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
import 'package:web3kit/core/dtos/chain_info.dart';
import 'package:web3kit/core/enums/native_currencies.dart';
-import 'package:zup_app/core/dtos/token_dto.dart';
import 'package:zup_app/core/enums/networks.dart';
import '../../golden_config.dart';
@@ -24,6 +23,7 @@ void main() {
expect(AppNetworks.fromValue("allNetworks"), AppNetworks.allNetworks, reason: "All networks should match");
// expect(AppNetworks.fromValue("base"), AppNetworks.base, reason: "Base should match");
expect(AppNetworks.fromValue("unichain"), AppNetworks.unichain, reason: "Unichain should match");
+ // expect(AppNetworks.fromValue("bnb"), AppNetworks.bnb, reason: "BNB should match");
});
test("Label extension should match for all networks", () {
@@ -33,6 +33,7 @@ void main() {
expect(AppNetworks.allNetworks.label, "All Networks", reason: "All Networks Label should match");
// expect(AppNetworks.base.label, "Base", reason: "Base Label should match");
expect(AppNetworks.unichain.label, "Unichain", reason: "Unichain Label should match");
+ // expect(AppNetworks.bnb.label, "BNB Chain", reason: "BNB Chain Label should match");
});
test("`testnets` method should return all testnets in the enum, excluding the 'all networks'", () {
@@ -48,6 +49,7 @@ void main() {
AppNetworks.scroll,
// AppNetworks.base,
AppNetworks.unichain,
+ // AppNetworks.bnb
]),
);
});
@@ -72,6 +74,10 @@ void main() {
expect(AppNetworks.unichain.isTestnet, false);
});
+ test("`isTestnet` method should return false for bnb", () {
+ // expect(AppNetworks.bnb.isTestnet, false);
+ });
+
test("Chain info extension should match for all networks", () {
expect(
AppNetworks.sepolia.chainInfo,
@@ -125,12 +131,24 @@ void main() {
ChainInfo(
hexChainId: "0x82",
chainName: "Unichain",
- blockExplorerUrls: const ["https://uniscan.xyz/"],
+ blockExplorerUrls: const ["https://uniscan.xyz"],
nativeCurrency: NativeCurrencies.eth.currencyInfo,
rpcUrls: const ["https://unichain-rpc.publicnode.com"],
),
reason: "Unichain ChainInfo should match",
);
+
+ // expect(
+ // AppNetworks.bnb.chainInfo,
+ // ChainInfo(
+ // hexChainId: "0x38",
+ // chainName: "BNB Chain",
+ // blockExplorerUrls: const ["https://bscscan.com"],
+ // nativeCurrency: NativeCurrencies.bnb.currencyInfo,
+ // rpcUrls: const ["https://bsc-rpc.publicnode.com"],
+ // ),
+ // reason: "BNB Chain ChainInfo should match",
+ // );
});
test("wrapped native token address should match for all networks", () {
@@ -165,80 +183,6 @@ void main() {
);
});
- test("wrapped native token should match for all networks", () {
- expect(
- AppNetworks.sepolia.wrappedNative,
- TokenDto(
- addresses: {
- AppNetworks.sepolia.chainId: "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
- },
- name: "Wrapped Ether",
- decimals: 18,
- symbol: "WETH",
- logoUrl: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
- ),
- reason: "Sepolia default token should match",
- );
-
- expect(
- AppNetworks.mainnet.wrappedNative,
- TokenDto(
- addresses: {
- AppNetworks.mainnet.chainId: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
- },
- name: "Wrapped Ether",
- decimals: 18,
- symbol: "WETH",
- logoUrl: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
- ),
- reason: "Ethereum default token should match",
- );
-
- expect(
- AppNetworks.scroll.wrappedNative,
- TokenDto(
- addresses: {
- AppNetworks.scroll.chainId: "0x5300000000000000000000000000000000000004",
- },
- name: "Wrapped Ether",
- decimals: 18,
- symbol: "WETH",
- logoUrl:
- "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/scroll/assets/0x5300000000000000000000000000000000000004/logo.png",
- ),
- reason: "Scroll default token should match",
- );
-
- // expect(
- // AppNetworks.base.wrappedNative,
- // TokenDto(
- // addresses: {
- // AppNetworks.base.chainId: "0x4200000000000000000000000000000000000006",
- // },
- // name: "Wrapped Ether",
- // decimals: 18,
- // symbol: "WETH",
- // logoUrl:
- // "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/base/assets/0x4200000000000000000000000000000000000006/logo.png",
- // ),
- // reason: "Base default token should match",
- // );
-
- expect(
- AppNetworks.unichain.wrappedNative,
- TokenDto(
- addresses: {
- AppNetworks.unichain.chainId: "0x4200000000000000000000000000000000000006",
- },
- name: "Wrapped Ether",
- decimals: 18,
- symbol: "WETH",
- logoUrl: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/unichain/logo.png",
- ),
- reason: "Unichain default token should match",
- );
- });
-
test("RpcUrl extension should return the correct rpc url", () {
expect(
AppNetworks.sepolia.rpcUrl,
@@ -269,6 +213,12 @@ void main() {
"https://unichain-rpc.publicnode.com",
reason: "Unichain rpc url should match",
);
+
+ // expect(
+ // AppNetworks.bnb.rpcUrl,
+ // "https://bsc-rpc.publicnode.com",
+ // reason: "BNB rpc url should match",
+ // );
});
test("openTx should open the correct url for each network", () async {
@@ -350,4 +300,11 @@ void main() {
device: GoldenDevice.square,
));
});
+
+ // zGoldenTest("BNB network icon should match", goldenFileName: "bnb_network_icon", (tester) async {
+ // await tester.pumpDeviceBuilder(await goldenDeviceBuilder(
+ // AppNetworks.bnb.icon,
+ // device: GoldenDevice.square,
+ // ));
+ // });
}
diff --git a/test/core/enums/protocol_id_test.dart b/test/core/enums/protocol_id_test.dart
new file mode 100644
index 0000000..b2d22a2
--- /dev/null
+++ b/test/core/enums/protocol_id_test.dart
@@ -0,0 +1,18 @@
+import 'package:flutter_test/flutter_test.dart';
+import 'package:zup_app/core/enums/protocol_id.dart';
+
+void main() {
+ test(
+ "When calling `isPancakeSwapInfinityCL` and the protocol is indeed pancakeSwapInfinityCL, it should return true",
+ () {
+ expect(ProtocolId.pancakeSwapInfinityCL.isPancakeSwapInfinityCL, true);
+ },
+ );
+
+ test(
+ "When calling `isPancakeSwapInfinityCL` and the protocol is not pancakeSwapInfinityCL, it should return false",
+ () {
+ expect(ProtocolId.unknown.isPancakeSwapInfinityCL, false);
+ },
+ );
+}
diff --git a/test/core/mixins/keys_mixin_test.dart b/test/core/mixins/keys_mixin_test.dart
index 4210281..57ba489 100644
--- a/test/core/mixins/keys_mixin_test.dart
+++ b/test/core/mixins/keys_mixin_test.dart
@@ -44,4 +44,10 @@ void main() {
expect(key, 'tokenPrice-$tokenAddress-${network.name}');
});
+
+ test("protocolsListKey should return correct key", () {
+ final key = _KeysMixinWrapper().protocolsListKey;
+
+ expect(key, 'zup-supported-protocols');
+ });
}
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 e71d746..d47280a 100644
--- a/test/core/mixins/v4_pool_liquidity_calculations_mixin_test.dart
+++ b/test/core/mixins/v4_pool_liquidity_calculations_mixin_test.dart
@@ -13,7 +13,7 @@ void main() {
expect(
_V4PoolLiquidityCalculationsMixinTest().getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0),
- BigInt.parse("282021882116526385819866125"),
+ BigInt.parse("282021882116526385820841971"),
);
},
);
@@ -44,7 +44,7 @@ void main() {
expect(
_V4PoolLiquidityCalculationsMixinTest()
.getLiquidityForAmounts(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, amount0, amount1),
- BigInt.parse("282021882116526385819866125"),
+ BigInt.parse("282021882116526385820841971"),
);
},
);
@@ -61,7 +61,7 @@ void main() {
expect(
_V4PoolLiquidityCalculationsMixinTest()
.getLiquidityForAmounts(sqrtPriceX96, sqrtPriceAX96, sqrtPriceBX96, amount0, amount1),
- BigInt.parse("94007294038842128606622041"),
+ BigInt.parse("94007294038842128606947412"),
);
},
);
diff --git a/test/core/pool_service_test.dart b/test/core/pool_service_test.dart
index c19d037..91bf353 100644
--- a/test/core/pool_service_test.dart
+++ b/test/core/pool_service_test.dart
@@ -4,14 +4,17 @@ import 'package:mocktail/mocktail.dart';
import 'package:web3kit/core/dtos/transaction_receipt.dart';
import 'package:web3kit/core/dtos/transaction_response.dart';
import 'package:web3kit/web3kit.dart';
+import 'package:zup_app/abis/pancake_swap_infinity_cl_pool_manager.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/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/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';
@@ -26,6 +29,7 @@ void main() {
late UniswapV3Pool uniswapV3Pool;
late UniswapV3PositionManager positionManagerV3;
late UniswapV4PositionManager positionManagerV4;
+ late PancakeSwapInfinityClPoolManager pancakeSwapInfinityCLPoolManager;
late Signer signer;
late YieldDto currentYield;
late TransactionResponse transactionResponse;
@@ -34,6 +38,7 @@ void main() {
late UniswapV3PoolImpl uniswapV3PoolImpl;
late UniswapV3PositionManagerImpl positionManagerV3Impl;
late UniswapV4PositionManagerImpl positionManagerV4Impl;
+ late PancakeSwapInfinityClPoolManagerImpl pancakeSwapInfinityCLPoolManagerImpl;
late EthereumAbiCoder ethereumAbiCoder;
setUp(() {
@@ -58,9 +63,12 @@ void main() {
uniswapV3Pool = UniswapV3PoolMock();
positionManagerV3 = UniswapV3PositionManagerMock();
positionManagerV4 = UniswapV4PositionManagerMock();
+ pancakeSwapInfinityCLPoolManager = PancakeSwapInfinityCLPoolManagerMock();
ethereumAbiCoder = EthereumAbiCoderMock();
signer = SignerMock();
+ pancakeSwapInfinityCLPoolManagerImpl = PancakeSwapInfinityCLPoolManagerImplMock();
+
stateViewImpl = UniswapV4StateViewImplMock();
uniswapV3PoolImpl = UniswapV3PoolImplMock();
positionManagerV3Impl = UniswapV3PositionManagerImplMock();
@@ -68,10 +76,14 @@ void main() {
currentYield = YieldDto.fixture();
- sut = PoolService(stateView, uniswapV3Pool, positionManagerV3, positionManagerV4, ethereumAbiCoder);
-
- when(() => stateView.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl")))
- .thenReturn(stateViewImpl);
+ sut = PoolService(
+ stateView,
+ uniswapV3Pool,
+ positionManagerV3,
+ positionManagerV4,
+ ethereumAbiCoder,
+ pancakeSwapInfinityCLPoolManager,
+ );
when(() => uniswapV3Pool.fromRpcProvider(
contractAddress: any(named: "contractAddress"),
@@ -90,6 +102,9 @@ void main() {
positionManagerV4.fromSigner(contractAddress: any(named: "contractAddress"), signer: any(named: "signer")))
.thenReturn(positionManagerV4Impl);
+ when(() => stateView.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl")))
+ .thenReturn(stateViewImpl);
+
when(() => positionManagerV4.fromRpcProvider(
contractAddress: any(named: "contractAddress"),
rpcUrl: any(named: "rpcUrl"))).thenReturn(positionManagerV4Impl);
@@ -98,6 +113,12 @@ void main() {
when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async => TransactionReceipt(hash: "0x123"));
when(() => transactionResponse.hash).thenReturn("0x123");
+ when(() => stateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer((_) async => (
+ lpFee: BigInt.from(0),
+ protocolFee: BigInt.from(0),
+ sqrtPriceX96: BigInt.from(0),
+ tick: BigInt.from(0),
+ ));
});
test(
@@ -110,6 +131,12 @@ void main() {
sqrtPriceX96: BigInt.from(0),
tick: expectedTick,
));
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer((_) async => (
+ lpFee: BigInt.from(0),
+ protocolFee: BigInt.from(0),
+ sqrtPriceX96: BigInt.from(0),
+ tick: expectedTick,
+ ));
final currentYield0 = currentYield.copyWith(poolType: PoolType.v4, v4StateView: "0x123");
final result = await sut.getPoolTick(currentYield0);
@@ -254,7 +281,7 @@ void main() {
recipient: recipient,
tickLower: tickLower,
tickUpper: tickUpper,
- token0: network.wrappedNative.addresses[network.chainId]!,
+ token0: network.wrappedNativeTokenAddress,
token1: token1Address,
)),
).called(1);
@@ -517,9 +544,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ poolType: PoolType.v4,
+ v4StateView: "0x1",
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: EthereumConstants.zeroAddress}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x1"}),
);
@@ -535,7 +564,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(() => ethereumAbiCoder.encodePacked([
@@ -568,9 +596,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: EthereumConstants.zeroAddress}),
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x1"}),
);
@@ -586,7 +616,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(() => ethereumAbiCoder.encodePacked([
@@ -619,9 +648,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x2"}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x1"}),
);
@@ -637,7 +668,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(() => ethereumAbiCoder.encodePacked([
@@ -652,13 +682,6 @@ void main() {
test(
"When calling `sendV4PoolDepositTransaction` the mint action params should be correctly encoded",
() async {
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
- when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
- ).thenAnswer((_) async => transactionResponse);
-
const token0Address = "0x1";
const token1Address = "0x2";
const network = AppNetworks.mainnet;
@@ -670,9 +693,26 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+ final sqrtPriceX96 = BigInt.from(2167212171927187);
+
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => positionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
+ ).thenAnswer((_) async => transactionResponse);
+
+ when(() => stateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer((_) async => (
+ lpFee: BigInt.from(0),
+ protocolFee: BigInt.from(0),
+ sqrtPriceX96: sqrtPriceX96,
+ tick: BigInt.from(0),
+ ));
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
@@ -688,7 +728,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(() => ethereumAbiCoder.encode([
@@ -711,7 +750,7 @@ void main() {
tickLower,
tickUpper,
_V4PoolLiquidityCalculationsMixinWrapper().getLiquidityForAmounts(
- _V4PoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick(currentPoolTick),
+ sqrtPriceX96,
_V4PoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick(tickLower),
_V4PoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick(tickUpper),
amount0Desired,
@@ -746,9 +785,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
@@ -764,7 +805,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(() => ethereumAbiCoder.encode(["address", "address"], [token0Address, token1Address])).called(1);
@@ -792,9 +832,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
@@ -810,7 +852,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(
@@ -843,9 +884,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
@@ -861,7 +904,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(
@@ -894,9 +936,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
@@ -942,7 +986,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(
@@ -976,9 +1019,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
@@ -1024,7 +1069,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(
@@ -1057,9 +1101,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
@@ -1102,7 +1148,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(
@@ -1131,9 +1176,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
@@ -1157,7 +1204,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(
@@ -1185,9 +1231,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
@@ -1211,7 +1259,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(
@@ -1239,9 +1286,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
@@ -1265,7 +1314,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(
@@ -1293,9 +1341,11 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
- final currentPoolTick = BigInt.from(123);
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
@@ -1319,7 +1369,6 @@ void main() {
maxAmount0ToDeposit: amount0Max,
maxAmount1ToDeposit: amount1Max,
recipient: recipient,
- currentPoolTick: currentPoolTick,
);
verify(
@@ -1331,4 +1380,128 @@ void main() {
).called(1);
},
);
+
+ test(
+ """"When calling `getPoolTick` and the yield protocol is pancakeswap infinity cl,
+ it should use the pancakeswap inifity cl pool manager to get the tick""",
+ () async {
+ final expectedTick = BigInt.from(318675);
+
+ when(() => pancakeSwapInfinityCLPoolManager.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl"))).thenReturn(
+ pancakeSwapInfinityCLPoolManagerImpl,
+ );
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer((_) async => (
+ sqrtPriceX96: BigInt.from(0),
+ tick: expectedTick,
+ protocolFee: BigInt.from(0),
+ lpFee: BigInt.from(0),
+ ));
+
+ final yield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
+ v4PoolManager: "0x0000001",
+ );
+
+ final receivedPoolTick = await sut.getPoolTick(yield0);
+ expect(receivedPoolTick, expectedTick);
+
+ verify(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: yield0.poolAddress)).called(1);
+ },
+ );
+
+ test("""When calling `getSqrtPriceX96` and the yield protocol is pancakeswap infinity cl,
+ it should use the pancakeswap inifity cl pool manager to get the sqrtPriceX96 from the
+ slot0""", () async {
+ final expectedSqrtPriceX96 = BigInt.parse("3256723627823257362");
+
+ final yield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
+ v4PoolManager: "0x0000001",
+ );
+
+ when(() => pancakeSwapInfinityCLPoolManager.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl"))).thenReturn(
+ pancakeSwapInfinityCLPoolManagerImpl,
+ );
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer((_) async => (
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ protocolFee: BigInt.from(0),
+ lpFee: BigInt.from(0),
+ ));
+
+ final receivedSqrtPriceX96 = await sut.getSqrtPriceX96(yield0);
+
+ expect(receivedSqrtPriceX96, expectedSqrtPriceX96);
+ });
+
+ test("""When calling `getSqrtPriceX96` and the yield pool is v4,
+ it should use the v4 state view get the sqrtPriceX96 from the
+ slot0""", () async {
+ final expectedSqrtPriceX96 = BigInt.parse("1216426515276100");
+
+ final yield0 = currentYield.copyWith(
+ poolType: PoolType.v4,
+ v4StateView: "0x0000001",
+ );
+
+ when(() => stateView.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl")))
+ .thenReturn(
+ stateViewImpl,
+ );
+
+ when(() => stateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer((_) async => (
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ protocolFee: BigInt.from(0),
+ lpFee: BigInt.from(0),
+ ));
+
+ final receivedSqrtPriceX96 = await sut.getSqrtPriceX96(yield0);
+
+ expect(receivedSqrtPriceX96, expectedSqrtPriceX96);
+ });
+
+ test("""When calling `getSqrtPriceX96` and the yield pool is v3,
+ it should use the pool contract get the sqrtPriceX96 from the
+ slot0""", () async {
+ final expectedSqrtPriceX96 = BigInt.parse("907219862715267517621");
+
+ final yield0 = currentYield.copyWith(
+ poolType: PoolType.v3,
+ poolAddress: "0x0000001",
+ );
+
+ when(() =>
+ uniswapV3Pool.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl")))
+ .thenReturn(
+ uniswapV3PoolImpl,
+ );
+
+ when(() => uniswapV3PoolImpl.slot0()).thenAnswer((_) async => (
+ feeProtocol: BigInt.from(0),
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ unlocked: true,
+ ));
+
+ final receivedSqrtPriceX96 = await sut.getSqrtPriceX96(yield0);
+
+ expect(receivedSqrtPriceX96, expectedSqrtPriceX96);
+ });
+
+ test("""When calling `getSqrtPriceX96` and the yield pool type
+ is unknown, it should throw an error""", () async {
+ final yield0 = currentYield.copyWith(
+ poolType: PoolType.unknown,
+ );
+
+ expect(() async => await sut.getSqrtPriceX96(yield0), throwsA(isA()));
+ });
}
diff --git a/test/core/repositories/protocol_repository_test.dart b/test/core/repositories/protocol_repository_test.dart
new file mode 100644
index 0000000..a0cf821
--- /dev/null
+++ b/test/core/repositories/protocol_repository_test.dart
@@ -0,0 +1,50 @@
+import 'package:dio/dio.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mocktail/mocktail.dart';
+import 'package:zup_app/core/dtos/protocol_dto.dart';
+import 'package:zup_app/core/repositories/protocol_repository.dart';
+
+import '../../mocks.dart';
+
+void main() {
+ late Dio zupApiDio;
+ late ProtocolRepository sut;
+
+ setUp(() {
+ zupApiDio = DioMock();
+ sut = ProtocolRepository(zupApiDio: zupApiDio);
+ });
+
+ test("When calling `getAllSupportedProtocols` it should call the correct endpoint", () async {
+ when(() => zupApiDio.get(any())).thenAnswer(
+ (_) async => Response(
+ data: [ProtocolDto.fixture().toJson()],
+ statusCode: 200,
+ requestOptions: RequestOptions(),
+ ),
+ );
+
+ await sut.getAllSupportedProtocols();
+
+ verify(() => zupApiDio.get("/protocols")).called(1);
+ });
+
+ test("When calling `getAllSupportedProtocols` it should return a list of protocols", () async {
+ final protocols = [
+ ProtocolDto.fixture().copyWith(rawId: "1", name: "LULU", logo: "LALA.png", url: "LALA.com"),
+ ProtocolDto.fixture().copyWith(rawId: "2", name: "LALA", logo: "LULU.png", url: "LULU.com"),
+ ];
+
+ when(() => zupApiDio.get(any())).thenAnswer(
+ (_) async => Response(
+ data: protocols.map((protocol) => protocol.toJson()..["id"] = protocol.rawId.toString()).toList(),
+ statusCode: 200,
+ requestOptions: RequestOptions(),
+ ),
+ );
+
+ final result = await sut.getAllSupportedProtocols();
+
+ expect(result, protocols);
+ });
+}
diff --git a/test/core/repositories/yield_repository_test.dart b/test/core/repositories/yield_repository_test.dart
index 2962c19..78355f8 100644
--- a/test/core/repositories/yield_repository_test.dart
+++ b/test/core/repositories/yield_repository_test.dart
@@ -33,8 +33,10 @@ void main() {
const network = AppNetworks.sepolia;
const minTvlUsd = 1213;
final searchSettings = PoolSearchSettingsDto.fixture().copyWith(minLiquidityUSD: minTvlUsd);
+ final blockedProtocolsIds = ["1", "2", "3"];
await sut.getSingleNetworkYield(
+ blockedProtocolIds: blockedProtocolsIds,
token0Address: token0Address,
token1Address: token1Address,
network: network,
@@ -48,6 +50,7 @@ void main() {
}, data: {
"filters": {
"minTvlUsd": searchSettings.minLiquidityUSD,
+ "blockedProtocols": blockedProtocolsIds,
"allowedPoolTypes": [
"V3",
"V4",
@@ -72,8 +75,10 @@ void main() {
const token1Address = "0x456";
const network = AppNetworks.sepolia;
final searchSettings = PoolSearchSettingsDto.fixture().copyWith(allowV3Search: false);
+ final blockedProtocolsIds = ["1", "2", "3"];
await sut.getSingleNetworkYield(
+ blockedProtocolIds: blockedProtocolsIds,
token0Address: token0Address,
token1Address: token1Address,
network: network,
@@ -87,6 +92,7 @@ void main() {
}, data: {
"filters": {
"minTvlUsd": searchSettings.minLiquidityUSD,
+ "blockedProtocols": blockedProtocolsIds,
"allowedPoolTypes": [
"V4",
],
@@ -110,8 +116,10 @@ void main() {
const token1Address = "0x456";
const network = AppNetworks.sepolia;
final searchSettings = PoolSearchSettingsDto.fixture().copyWith(allowV4Search: false);
+ final blockedProtocolIds = ["1", "2", "3"];
await sut.getSingleNetworkYield(
+ blockedProtocolIds: blockedProtocolIds,
token0Address: token0Address,
token1Address: token1Address,
network: network,
@@ -124,6 +132,7 @@ void main() {
"token1Address": token1Address
}, data: {
"filters": {
+ "blockedProtocols": blockedProtocolIds,
"minTvlUsd": searchSettings.minLiquidityUSD,
"allowedPoolTypes": ["V3"],
}
@@ -147,6 +156,7 @@ void main() {
const network = AppNetworks.sepolia;
final response = await sut.getSingleNetworkYield(
+ blockedProtocolIds: [],
token0Address: token0Address,
token1Address: token1Address,
network: network,
@@ -171,8 +181,10 @@ void main() {
const token1Id = "0x456";
const minTvlUsd = 1213;
final searchSettings = PoolSearchSettingsDto.fixture().copyWith(minLiquidityUSD: minTvlUsd);
+ final blockedProtocolsIds = ["1", "2", "3"];
await sut.getAllNetworksYield(
+ blockedProtocolIds: blockedProtocolsIds,
token0InternalId: token0Id,
token1InternalId: token1Id,
searchSettings: searchSettings,
@@ -187,6 +199,7 @@ void main() {
"filters": {
"testnetMode": true,
"minTvlUsd": searchSettings.minLiquidityUSD,
+ "blockedProtocols": blockedProtocolsIds,
"allowedPoolTypes": [
"V3",
"V4",
@@ -213,8 +226,10 @@ void main() {
const token1Id = "0x456";
const minTvlUsd = 1213;
final searchSettings = PoolSearchSettingsDto.fixture().copyWith(minLiquidityUSD: minTvlUsd, allowV4Search: false);
+ final blockedProtocolsIds = ["ai", "be", "cd"];
await sut.getAllNetworksYield(
+ blockedProtocolIds: blockedProtocolsIds,
token0InternalId: token0Id,
token1InternalId: token1Id,
searchSettings: searchSettings,
@@ -229,6 +244,7 @@ void main() {
"filters": {
"testnetMode": true,
"minTvlUsd": searchSettings.minLiquidityUSD,
+ "blockedProtocols": blockedProtocolsIds,
"allowedPoolTypes": [
"V3",
],
@@ -254,8 +270,10 @@ void main() {
const token1Id = "0x456";
const minTvlUsd = 1213;
final searchSettings = PoolSearchSettingsDto.fixture().copyWith(minLiquidityUSD: minTvlUsd, allowV3Search: false);
+ final blockedProtocolsIds = ["ai", "be", "cd"];
await sut.getAllNetworksYield(
+ blockedProtocolIds: blockedProtocolsIds,
token0InternalId: token0Id,
token1InternalId: token1Id,
searchSettings: searchSettings,
@@ -270,6 +288,7 @@ void main() {
"filters": {
"testnetMode": true,
"minTvlUsd": searchSettings.minLiquidityUSD,
+ "blockedProtocols": blockedProtocolsIds,
"allowedPoolTypes": [
"V4",
],
@@ -293,6 +312,7 @@ void main() {
const token1Id = "0x456";
final response = await sut.getAllNetworksYield(
+ blockedProtocolIds: [],
token0InternalId: token0Id,
token1InternalId: token1Id,
searchSettings: PoolSearchSettingsDto.fixture().copyWith(minLiquidityUSD: 0),
diff --git a/test/core/string_extension_test.dart b/test/core/string_extension_test.dart
index 0cc62e4..276a8e7 100644
--- a/test/core/string_extension_test.dart
+++ b/test/core/string_extension_test.dart
@@ -11,6 +11,10 @@ void main() {
expect("0".isEmptyOrZero, true);
});
+ test("`isEmptyOrZero` should return true if the string is zero in double ", () {
+ expect("0.00000".isEmptyOrZero, true);
+ });
+
test("`isNotEmptyOrZero` should return false if the string is literally empty", () {
expect("".isNotEmptyOrZero, false);
});
diff --git a/test/mocks.dart b/test/mocks.dart
index f167e89..38d52f0 100644
--- a/test/mocks.dart
+++ b/test/mocks.dart
@@ -12,6 +12,7 @@ import 'package:url_launcher_platform_interface/url_launcher_platform_interface.
import 'package:web3kit/core/dtos/transaction_response.dart';
import 'package:web3kit/web3kit.dart';
import 'package:zup_app/abis/erc_20.abi.g.dart';
+import 'package:zup_app/abis/pancake_swap_infinity_cl_pool_manager.abi.g.dart';
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';
@@ -24,6 +25,7 @@ import 'package:zup_app/core/cache.dart';
import 'package:zup_app/core/debouncer.dart';
import 'package:zup_app/core/pool_service.dart';
import 'package:zup_app/core/repositories/positions_repository.dart';
+import 'package:zup_app/core/repositories/protocol_repository.dart';
import 'package:zup_app/core/repositories/tokens_repository.dart';
import 'package:zup_app/core/repositories/yield_repository.dart';
import 'package:zup_app/core/zup_analytics.dart';
@@ -87,6 +89,10 @@ class UniswapV4PositionManagerMock extends Mock implements UniswapV4PositionMana
class UniswapV4PositionManagerImplMock extends Mock implements UniswapV4PositionManagerImpl {}
+class PancakeSwapInfinityCLPoolManagerMock extends Mock implements PancakeSwapInfinityClPoolManager {}
+
+class PancakeSwapInfinityCLPoolManagerImplMock extends Mock implements PancakeSwapInfinityClPoolManagerImpl {}
+
class UniswapV3PoolImplMock extends Mock implements UniswapV3PoolImpl {}
class UniswapV3PoolMock extends Mock implements UniswapV3Pool {}
@@ -113,6 +119,8 @@ class FirebaseAnalyticsMock extends Mock implements FirebaseAnalytics {}
class ZupHolderMock extends Mock implements ZupHolder {}
+class ProtocolRepositoryMock extends Mock implements ProtocolRepository {}
+
class ChangeNotifierMock extends Mock with ChangeNotifier {
void notify() => notifyListeners();
}
@@ -172,7 +180,7 @@ ZupCachedImage mockZupCachedImage() {
width: any(named: "width"),
radius: any(named: "radius"),
errorWidget: any(named: "errorWidget"),
- loadingBuilder: any(named: "loadingBuilder"),
+ placeholder: any(named: "placeholder"),
)).thenReturn(const SizedBox(child: Text("IMAGE")));
return zupCachedImage;
diff --git a/test/widgets/token_selector_modal/token_selector_modal_cubit_test.dart b/test/widgets/token_selector_modal/token_selector_modal_cubit_test.dart
index 3f2868a..0ac65fb 100644
--- a/test/widgets/token_selector_modal/token_selector_modal_cubit_test.dart
+++ b/test/widgets/token_selector_modal/token_selector_modal_cubit_test.dart
@@ -279,8 +279,8 @@ void main() {
test("""When calling 'searchToken' and all the tokens in the list returned does not have name and symbol,
it should emit the search not found state""", () async {
final returnedList = [
- const TokenDto(name: "", symbol: "", decimals: 0, logoUrl: "", addresses: {}),
- const TokenDto(name: "", symbol: "", decimals: 0, logoUrl: "", addresses: {}),
+ TokenDto.fixture().copyWith(name: "", symbol: "", logoUrl: "", addresses: {}),
+ TokenDto.fixture().copyWith(name: "", symbol: "", decimals: {}, logoUrl: "", addresses: {}),
];
when(() => tokensRepository.searchToken(any(), any())).thenAnswer((_) async => returnedList);
@@ -294,8 +294,8 @@ void main() {
it should emit the search sucesss state, without the tokens without name and symbol""", () async {
final namedToken = TokenDto.fixture();
final returnedList = [
- const TokenDto(name: "", symbol: "", decimals: 0, logoUrl: "", addresses: {}),
- const TokenDto(name: "", symbol: "", decimals: 0, logoUrl: "", addresses: {}),
+ TokenDto.fixture().copyWith(name: "", symbol: "", logoUrl: "", addresses: {}),
+ TokenDto.fixture().copyWith(name: "", symbol: "", logoUrl: "", addresses: {}),
namedToken,
];
diff --git a/web/index.html b/web/index.html
index 852bc74..92d4cee 100644
--- a/web/index.html
+++ b/web/index.html
@@ -61,6 +61,6 @@
inject();
-
+