Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b2ba712
feat[ZUP-88]: add support for ethereum mainnet
RyanHolanda Apr 4, 2025
b98ff0c
chore: add slippage check error message
RyanHolanda Apr 5, 2025
6123b8e
fix: images not loading on web
RyanHolanda Apr 5, 2025
eb0641b
fix: image not updating when changing the url
RyanHolanda Apr 5, 2025
2f6ad59
feat: add tvl info in the pool && min tvl filter
RyanHolanda Apr 10, 2025
6f117c8
chore: bump flutter bootstrap version
RyanHolanda Apr 10, 2025
abdc5da
ci: update install dependencies command
RyanHolanda Apr 10, 2025
686d1e1
ci: remove make commands from CI
RyanHolanda Apr 10, 2025
06fccdd
Merge branch 'main' into staging
RyanHolanda Apr 17, 2025
74a219c
docs: add instructions to add a new network in readme
RyanHolanda Apr 17, 2025
d9da377
feat: add scroll mainnet
RyanHolanda Apr 28, 2025
3f6e195
feat: add network to the deposit page path
RyanHolanda Apr 29, 2025
79261a4
feat: add privacy policy + terms and coditions
RyanHolanda Apr 29, 2025
46c7b33
fix: tests
RyanHolanda Apr 29, 2025
2050e71
Merge branch 'main' into staging
RyanHolanda Apr 30, 2025
e1e73a1
feat: add cookies consent
RyanHolanda Apr 30, 2025
175d4d0
Merge branch 'main' into staging
RyanHolanda May 13, 2025
58bbeac
feat: allow crosschain search
RyanHolanda May 16, 2025
0539501
feat: does not allow search by address in all networks
RyanHolanda May 17, 2025
326b85b
fix: user token amount not updating correctly when changing yields
RyanHolanda May 18, 2025
c933415
feat: add base network
RyanHolanda May 20, 2025
7ba9fa6
Merge branch 'main' into staging
RyanHolanda May 23, 2025
afad225
feat: calculate USD price of input asset
RyanHolanda May 26, 2025
b8a83cd
feat: allow uniswap v4
RyanHolanda Jun 11, 2025
396eae9
Update flutter version on CI
RyanHolanda Jun 24, 2025
1827998
fix: wrong token amount appearing when connecting wallet with tokens …
RyanHolanda Jul 6, 2025
a9f3dfd
chore: remove base support
RyanHolanda Jul 14, 2025
1da6c94
bump version
RyanHolanda Jul 14, 2025
1da2f67
Merge branch 'main' into staging
RyanHolanda Jul 14, 2025
add2ab8
Merge branch 'main' into staging
RyanHolanda Jul 14, 2025
1729fc4
feat: add prefixed percentage range buttons
RyanHolanda Jul 15, 2025
fe3e2a1
bump version
RyanHolanda Jul 15, 2025
f733f3a
Merge branch 'main' into staging
RyanHolanda Jul 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions assets/icons/plusminus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 17 additions & 6 deletions lib/app/create/deposit/deposit_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,28 @@ class DepositCubit extends Cubit<DepositState> with KeysMixin, V3PoolConversorsM
_selectedYieldTimeframe = yieldTimeFrame;
_selectedYieldStreamController.add(selectedYield);

if (selectedYield != null) await getSelectedPoolTick();
if (selectedYield != null) {
_latestPoolTick = BigInt.parse(yieldDto!.latestTick);
_pooltickStreamController.add(_latestPoolTick);

await getSelectedPoolTick(forceRefresh: true);
}
}

Future<void> getSelectedPoolTick() async {
Future<void> getSelectedPoolTick({bool forceRefresh = false}) async {
if (selectedYield == null) return;

_latestPoolTick = null;
_pooltickStreamController.add(null);

final selectedYieldBeforeCall = selectedYield;
BigInt tick = await _poolService.getPoolTick(selectedYieldBeforeCall!);

final tick = await _zupSingletonCache.run(
() => _poolService.getPoolTick(selectedYieldBeforeCall!),
expiration: const Duration(minutes: 1),
ignoreCache: forceRefresh,
key: poolTickCacheKey(
network: selectedYield!.network,
poolAddress: selectedYield!.poolAddress,
),
);

if (selectedYieldBeforeCall != selectedYield) return await getSelectedPoolTick();

Expand Down
88 changes: 80 additions & 8 deletions lib/app/create/deposit/deposit_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,11 @@ class _DepositPageState extends State<DepositPage>
bool isMaxRangeInfinity = true;
bool isMinRangeInfinity = true;
bool isBaseTokenAmountUserInput = false;
double? percentRange;
double minPrice = 0;
double maxPrice = 0;
RangeController minRangeController = RangeController();
RangeController maxRangeController = RangeController();

late Slippage selectedSlippage = _cubit.depositSettings.slippage;
late Duration selectedDeadline = _cubit.depositSettings.deadline;
Expand Down Expand Up @@ -141,13 +144,38 @@ class _DepositPageState extends State<DepositPage>

void setFullRange() {
setState(() {
percentRange = null;
isMinRangeInfinity = true;
isMaxRangeInfinity = true;
});

minPrice = 0;
maxPrice = 0;

calculateDepositTokensAmount();
}

void setPercentageRange(double percentage) {
if (currentPrice == 0) return;

setState(() {
percentRange = percentage;
isMinRangeInfinity = false;
isMaxRangeInfinity = false;

final percentageDecimals = percentage / 100;
final percentageDifference = currentPrice * percentageDecimals;

minPrice = currentPrice - percentageDifference;
maxPrice = currentPrice + percentageDifference;

minRangeController.setRange(minPrice);
maxRangeController.setRange(maxPrice);

calculateDepositTokensAmount();
});
}

void selectYield(YieldDto? yieldDto, YieldTimeFrame? yieldTimeFrame) async {
_cubit.selectYield(yieldDto, yieldTimeFrame).then((_) => calculateDepositTokensAmount());

Expand All @@ -174,6 +202,7 @@ class _DepositPageState extends State<DepositPage>
quoteTokenAmountController.text = currentBaseTokenDepositAmount;
isBaseTokenAmountUserInput = isReversed && !isBaseTokenAmountUserInput;

if (percentRange != null) setPercentageRange(percentRange!);
calculateDepositTokensAmount();
}

Expand Down Expand Up @@ -328,6 +357,13 @@ class _DepositPageState extends State<DepositPage>
super.initState();
}

@override
void dispose() {
minRangeController.dispose();
maxRangeController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Padding(
Expand Down Expand Up @@ -703,13 +739,6 @@ class _DepositPageState extends State<DepositPage>
children: [
_sectionTitle(S.of(context).depositPageRangeSectionTitle),
const SizedBox(width: 12),
ZupTextButton(
key: const Key("full-range-button"),
onPressed: () => setFullRange(),
label: S.of(context).depositPageRangeSectionFullRange,
icon: Assets.icons.circleDotted.svg(),
alignLeft: false,
),
const Spacer(),
if (!isMobileSize(context)) tokenSwitcher
],
Expand All @@ -722,6 +751,7 @@ class _DepositPageState extends State<DepositPage>
const SizedBox(height: 10),
StreamBuilder(
stream: _cubit.poolTickStream,
initialData: _cubit.latestPoolTick,
builder: (context, poolTickSnapshot) {
return Text(
"1 ${baseToken.symbol} ≈ ${() {
Expand All @@ -738,12 +768,51 @@ class _DepositPageState extends State<DepositPage>
enabled: poolTickSnapshot.data == null,
);
}),
const SizedBox(height: 20),
const SizedBox(height: 10),
Wrap(
spacing: 10,
runSpacing: 10,
children: [
ZupMiniButton(
key: const Key("full-range-button"),
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),
isSelected: percentRange == 5,
title: "5%",
icon: Assets.icons.plusminus.svg(),
// alignLeft: true,
),
ZupMiniButton(
key: const Key("20-percent-range-button"),
onPressed: () => setPercentageRange(20),
isSelected: percentRange == 20,
title: "20%",
icon: Assets.icons.plusminus.svg(),
// alignLeft: true,
),
ZupMiniButton(
key: const Key("50-percent-range-button"),
onPressed: () => setPercentageRange(50),
isSelected: percentRange == 50,
title: "50%",
icon: Assets.icons.plusminus.svg(),
// alignLeft: true,
),
],
),
const SizedBox(height: 10),
StreamBuilder(
stream: _cubit.poolTickStream,
builder: (context, snapshot) {
return RangeSelector(
key: const Key("min-price-selector"),
onUserType: () => percentRange = null,
onPriceChanged: (price) {
setState(() {
if (price == 0) {
Expand All @@ -766,6 +835,7 @@ class _DepositPageState extends State<DepositPage>
tickSpacing: _cubit.selectedYield!.tickSpacing,
type: RangeSelectorType.minPrice,
isInfinity: isMinRangeInfinity,
rangeController: minRangeController,
state: () {
if (isOutOfRange.minPrice) {
return RangeSelectorState(
Expand All @@ -786,6 +856,7 @@ class _DepositPageState extends State<DepositPage>
key: const Key("max-price-selector"),
displayBaseTokenSymbol: baseToken.symbol,
displayQuoteTokenSymbol: quoteToken.symbol,
onUserType: () => percentRange = null,
onPriceChanged: (price) {
setState(() {
if (price == 0) {
Expand All @@ -807,6 +878,7 @@ class _DepositPageState extends State<DepositPage>
poolToken1: _cubit.selectedYield!.token1,
isReversed: areTokensReversed,
tickSpacing: _cubit.selectedYield!.tickSpacing,
rangeController: maxRangeController,
state: () {
if (isRangeInvalid) {
return RangeSelectorState(
Expand Down
32 changes: 27 additions & 5 deletions lib/app/create/deposit/widgets/range_selector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ class RangeSelectorState {
final String? message;
}

class RangeController extends ChangeNotifier {
double currentRange = 0;

void setRange(double range) {
currentRange = range;

notifyListeners();
}
}

class RangeSelector extends StatefulWidget {
const RangeSelector({
super.key,
Expand All @@ -53,8 +63,10 @@ class RangeSelector extends StatefulWidget {
required this.tickSpacing,
required this.onPriceChanged,
required this.type,
this.onUserType,
this.isInfinity = false,
this.initialPrice,
this.rangeController,
this.state = const RangeSelectorState(type: RangeSelectorStateType.regular),
});

Expand All @@ -66,9 +78,11 @@ class RangeSelector extends StatefulWidget {
final double? initialPrice;
final int tickSpacing;
final Function(double price) onPriceChanged;
final Function()? onUserType;
final RangeSelectorState state;
final RangeSelectorType type;
final bool isInfinity;
final RangeController? rangeController;

@override
State<RangeSelector> createState() => _RangeSelectorState();
Expand All @@ -91,12 +105,12 @@ class _RangeSelectorState extends State<RangeSelector> with V3PoolConversorsMixi
}

final typedDecimals = typedPrice.decimals;
final nextPrice = getAdjustedPrice(typedPrice);

controller.text = Decimal.tryParse(getAdjustedPrice(typedPrice).toString())
?.toStringAsFixed(typedDecimals < 4 ? 4 : typedDecimals) ??
"";
controller.text =
Decimal.tryParse(nextPrice.toString())?.toStringAsFixed(typedDecimals < 4 ? 4 : typedDecimals) ?? "";

widget.onPriceChanged(getAdjustedPrice(typedPrice));
widget.onPriceChanged(nextPrice);
}

double getAdjustedPrice(double price) {
Expand Down Expand Up @@ -186,6 +200,11 @@ class _RangeSelectorState extends State<RangeSelector> with V3PoolConversorsMixi
void initState() {
super.initState();

widget.rangeController?.addListener(() {
userTypedValue = widget.rangeController?.currentRange.toString();
adjustTypedAmountAndCallback();
});

WidgetsBinding.instance.addPostFrameCallback((_) {
if (widget.isInfinity) return setInfinity();

Expand Down Expand Up @@ -251,7 +270,10 @@ class _RangeSelectorState extends State<RangeSelector> with V3PoolConversorsMixi
keyboardType: const TextInputType.numberWithOptions(decimal: true),
clipBehavior: Clip.none,
controller: controller,
onChanged: (value) => userTypedValue = value,
onChanged: (value) {
userTypedValue = value;
widget.onUserType?.call();
},
style: const TextStyle(fontSize: 28),
decoration: const InputDecoration(
enabledBorder: InputBorder.none,
Expand Down
2 changes: 2 additions & 0 deletions lib/core/dtos/yield_dto.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class YieldDto with _$YieldDto {
required num yield90d,
required int chainId,
required PoolType poolType,
@Default("0") String latestTick,
@Default(0) num totalValueLockedUSD,
@Default(EthereumConstants.zeroAddress) @JsonKey(name: "hooksAddress") String v4Hooks,
@JsonKey(name: "poolManagerAddress") String? v4PoolManager,
Expand All @@ -68,6 +69,7 @@ class YieldDto with _$YieldDto {
yield24h: 32.2,
yield30d: 32.2,
yield90d: 32.2,
latestTick: "1567241",
positionManagerAddress: "0x5Df2f0aFb5b5bB2Df9D1e9C7b6f5f0DD5f9eD5e0",
poolAddress: "0x5Df2f0aFb5b5bB2Df9D1e9C7b6f5f0DD5f9eD5e0",
poolType: PoolType.v3,
Expand Down
1 change: 1 addition & 0 deletions lib/core/dtos/yields_dto.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class YieldsDto with _$YieldsDto {
factory YieldsDto.fixture() => const YieldsDto(
pools: [
YieldDto(
latestTick: "637812562",
positionManagerAddress: "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4",
poolType: PoolType.v3,
token0: TokenDto(
Expand Down
4 changes: 2 additions & 2 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1293,7 +1293,7 @@ packages:
description:
path: "."
ref: main
resolved-ref: "42dfe9f12673e21d2bc15623a6f58a1094969f2c"
resolved-ref: "96c38241bbd55f27820c0fbe0e62ed53f2febed7"
url: "https://github.com/Zup-Protocol/web3kit.git"
source: git
version: "0.0.1"
Expand Down Expand Up @@ -1351,7 +1351,7 @@ packages:
description:
path: "."
ref: main
resolved-ref: e67c82ded372f740d5b2e7823d4bce070efdb3bb
resolved-ref: cd1e5f42c34c93ec91f8da476ec19cc2d2435c36
url: "https://github.com/Zup-Protocol/zup-ui-kit.git"
source: git
version: "0.0.1"
Expand Down
14 changes: 7 additions & 7 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ dependencies:
firebase_analytics: ^11.4.5
envied: ^1.1.1

dependency_overrides:
# zup_core:
# path: ../zup-core
# web3kit:
# path: ../web3kit
# zup_ui_kit:
# path: ../zup-ui-kit
# dependency_overrides:
# zup_core:
# path: ../zup-core
# web3kit:
# path: ../web3kit
# zup_ui_kit:
# path: ../zup-ui-kit

dev_dependencies:
flutter_test:
Expand Down
Loading
Loading