Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
fb80fa0
WIP: implementing market screen
AlaaElattar Feb 19, 2025
e4f16ac
WIP: handling fetching price
AlaaElattar Feb 24, 2025
d13b1a9
WIP: Implement pages && connect with BE
AlaaElattar Feb 26, 2025
19af5e4
WIP: update new style of selecting wallet
AlaaElattar Mar 4, 2025
db9616e
Merge branch 'development' of github.com:threefoldtech/threefold_conn…
AlaaElattar Mar 4, 2025
53cde3f
WIP: handle market stats
AlaaElattar Mar 4, 2025
c483fe9
WIP: fix bug in overview screen
AlaaElattar Mar 5, 2025
1ba63a5
WIP: implement order screens
AlaaElattar Mar 9, 2025
6be9bcd
WIP: handld orders screen
AlaaElattar Mar 10, 2025
e5c1c9b
WIP: working on order cards
AlaaElattar Mar 11, 2025
e5b00c1
WIP: fix cards
AlaaElattar Mar 12, 2025
de28923
WIP: fix bug
AlaaElattar Mar 23, 2025
8fda8f6
remove wallets provides && add notifier
AlaaElattar Mar 24, 2025
4a754dd
add market in layout_drawer
AlaaElattar Mar 24, 2025
458d3fa
fix bug of updating order
AlaaElattar Mar 24, 2025
6904ad2
Merge branch 'development' of github.com:threefoldtech/threefold_conn…
AlaaElattar Mar 26, 2025
2ab5ace
WIP: updating with changes in dart client
AlaaElattar May 6, 2025
f95b48a
WIP: update changes from the dart client
AlaaElattar May 6, 2025
179e5e2
Merge branch 'development' into development_market
AlaaElattar May 6, 2025
0e0c2cc
fix navigation
AlaaElattar May 6, 2025
a1bb60a
WIP: fixing bugs && testing the whole flow
AlaaElattar May 7, 2025
837b637
add more validations
AlaaElattar May 7, 2025
8823c42
fix orders history
AlaaElattar May 12, 2025
d14153a
Merge branch 'development' into development_market
AlaaElattar May 12, 2025
68830af
fix workflow
AlaaElattar May 12, 2025
195a040
remove duplicated import
AlaaElattar May 12, 2025
cb5cb4d
improve code && remove unnecessary logic
AlaaElattar May 12, 2025
b86ce01
apply pr comments
AlaaElattar May 14, 2025
e4017a7
Update app/lib/apps/market/market.dart
AlaaElattar May 15, 2025
96da34b
Update app/lib/widgets/market/buy_tft.dart
AlaaElattar May 15, 2025
9abf47c
Update app/lib/widgets/market/overview.dart
AlaaElattar May 15, 2025
5d4ec8d
Update app/lib/widgets/market/overview.dart
AlaaElattar May 15, 2025
25ac5e5
Update app/lib/widgets/market/order_card.dart
AlaaElattar May 15, 2025
0aff01f
Update app/lib/widgets/market/order_details.dart
AlaaElattar May 15, 2025
c894965
Update app/lib/widgets/market/order_details.dart
AlaaElattar May 15, 2025
e286fd6
WIP: apply pr comments
AlaaElattar May 15, 2025
637dcdf
WIP: apply pr comments
AlaaElattar May 18, 2025
f5f1871
move order notifier to providers directory
AlaaElattar May 18, 2025
c78d878
Merge branch 'development' into development_market
AlaaElattar May 18, 2025
5fc0b33
fix conflict
AlaaElattar May 18, 2025
553c2aa
Update app/lib/widgets/market/buy_tft.dart
AlaaElattar May 19, 2025
f74c302
Update app/lib/widgets/market/buy_tft.dart
AlaaElattar May 19, 2025
5dbeeb8
WIP: apply pr comments
AlaaElattar May 19, 2025
4a7f0f1
WIP: apply pr comments
AlaaElattar May 19, 2025
7fcb711
handle available balance with usdc
AlaaElattar May 19, 2025
2c88b27
add check on low xlm balance when catching error
AlaaElattar May 20, 2025
b5dfdfe
fix error message
AlaaElattar May 20, 2025
f224796
update pushReplacement in creating order && add cancel button
AlaaElattar May 20, 2025
2ae229a
WIP: apply pr comments
AlaaElattar May 21, 2025
ee55968
Merge branch 'development' into development_market
AlaaElattar May 21, 2025
9573bf5
fix failed workflow
AlaaElattar May 21, 2025
0359c29
apply pr comments
AlaaElattar May 21, 2025
370c5ff
run format && analyze
AlaaElattar May 21, 2025
4d1e6a8
add intl as direct dependency to fix workflow
AlaaElattar May 21, 2025
e0607cf
add reflectable in pubspec yaml
AlaaElattar May 21, 2025
96b9ace
fix pr comments
AlaaElattar May 21, 2025
0de520d
remove unused var
AlaaElattar May 21, 2025
ed3a5ee
update version && remove unused var
AlaaElattar May 21, 2025
663bf8b
remove missed e
AlaaElattar May 21, 2025
e0ea2b4
update text styling of buttons from titleLarge to medium (#1022)
AlaaElattar May 21, 2025
76124c0
update font tp be consistent with app
AlaaElattar May 22, 2025
81f8a47
undo changes from pubspec.yaml
AlaaElattar May 22, 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
1 change: 1 addition & 0 deletions .github/workflows/format_analyze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.27.2"
channel: 'stable'

- name: Get dependencies
Expand Down
Binary file added app/assets/usdc-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions app/lib/apps/market/market.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'package:flutter/widgets.dart';
import 'package:threebotlogin/app.dart';
import 'package:threebotlogin/apps/farmers/farmers_user_data.dart';
import 'package:threebotlogin/events/events.dart';
import 'package:threebotlogin/events/go_home_event.dart';
import 'package:threebotlogin/screens/market/market_screen.dart';

class Market implements App {
static final Market _singleton = Market._internal();
static const Widget _daoWidget = MarketPage();

factory Market() {
return _singleton;
}

Market._internal();

@override
Future<Widget> widget() async {
return _daoWidget;
}

@override
void clearData() {
clearAllData();
}

@override
bool emailVerificationRequired() {
return false;
}

@override
bool pinRequired() {
return true;
}

@override
void back() {
Events().emit(GoHomeEvent());
}
}
10 changes: 10 additions & 0 deletions app/lib/jrouter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:threebotlogin/app.dart';
import 'package:threebotlogin/apps/council/council.dart';
import 'package:threebotlogin/apps/dao/dao.dart';
import 'package:threebotlogin/apps/market/market.dart';
import 'package:threebotlogin/apps/wallet/wallet.dart';
import 'package:threebotlogin/screens/identity_verification_screen.dart';
import 'package:threebotlogin/screens/preference_screen.dart';
Expand Down Expand Up @@ -71,6 +72,15 @@ class JRouter {
view: const IdentityVerificationScreen(),
),
app: null),
AppInfo(
route: Route(
path: '/market',
name: 'Market',
icon: Icons.show_chart_sharp,
view: await Market().widget(),
),
app: Market(),
),
AppInfo(
route: Route(
path: '/settings',
Expand Down
65 changes: 65 additions & 0 deletions app/lib/models/market_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
class TftMarketData {
final double lastPrice;
final double lastUsdPrice;
final double change24h;
final double high24h;
final double low24h;
final double volume24h;

TftMarketData({
required this.lastPrice,
required this.lastUsdPrice,
required this.change24h,
required this.high24h,
required this.low24h,
required this.volume24h,
});

factory TftMarketData.fromTrades(List<dynamic> trades) {
if (trades.isEmpty) return TftMarketData.empty();

final latestTrade = trades.first;
final double lastUsdcPrice = double.parse(latestTrade['base_amount']) /
double.parse(latestTrade['counter_amount']);
final double lastPrice = 1 / lastUsdcPrice;

double high24h = lastUsdcPrice;
double low24h = lastUsdcPrice;
double volume24h = 0;

final oldestTrade = trades.last;
final double oldestUsdcPrice = double.parse(oldestTrade['base_amount']) /
double.parse(oldestTrade['counter_amount']);

for (var trade in trades) {
double usdcPrice = double.parse(trade['base_amount']) /
double.parse(trade['counter_amount']);
high24h = usdcPrice > high24h ? usdcPrice : high24h;
low24h = usdcPrice < low24h ? usdcPrice : low24h;
volume24h += double.parse(trade['counter_amount']);
}

final double change24h =
((lastUsdcPrice - oldestUsdcPrice) / oldestUsdcPrice) * 100;

return TftMarketData(
lastPrice: 1 / lastPrice,
lastUsdPrice: lastUsdcPrice,
change24h: change24h,
high24h: high24h,
low24h: low24h,
volume24h: volume24h / 1000,
);
}

factory TftMarketData.empty() {
return TftMarketData(
lastPrice: 0,
lastUsdPrice: 0,
change24h: 0,
high24h: 0,
low24h: 0,
volume24h: 0,
);
}
}
80 changes: 80 additions & 0 deletions app/lib/models/offer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart';
import 'package:threebotlogin/services/stellar_service.dart';

class Offer {
final String id;
final String seller;
final String sellingAsset;
final String buyingAsset;
final String amount;
final String price;
final String lastModifiedTime;

Offer({
required this.id,
required this.seller,
required this.sellingAsset,
required this.buyingAsset,
required this.amount,
required this.price,
required this.lastModifiedTime,
});

factory Offer.fromOfferResponse(OfferResponse response) {
return Offer(
id: response.id,
seller: response.seller,
sellingAsset: getAssetName(response.selling),
buyingAsset: getAssetName(response.buying),
amount: response.amount,
price: response.price,
lastModifiedTime: response.lastModifiedTime,
);
}

factory Offer.fromTradeResponse(TradeResponse response) {
final bool userIsSeller =
response.baseAccount == response.links.base.href.split('/').last;
final String sellingAsset = userIsSeller
? _getAssetNameFromTrade(response.baseAssetType, response.baseAssetCode,
response.baseAssetIssuer)
: _getAssetNameFromTrade(response.counterAssetType,
response.counterAssetCode, response.counterAssetIssuer);

final String buyingAsset = userIsSeller
? _getAssetNameFromTrade(response.counterAssetType,
response.counterAssetCode, response.counterAssetIssuer)
: _getAssetNameFromTrade(response.baseAssetType, response.baseAssetCode,
response.baseAssetIssuer);
final String amount =
userIsSeller ? response.baseAmount : response.counterAmount;

String priceStr;
try {
Price priceObj = response.price;
priceStr = (priceObj.numerator! / priceObj.denominator!).toString();
} catch (e) {
priceStr = '0';
}

return Offer(
id: response.id,
seller: userIsSeller ? response.baseAccount! : response.counterAccount!,
sellingAsset: sellingAsset,
buyingAsset: buyingAsset,
amount: amount,
price: priceStr,
lastModifiedTime: response.ledgerCloseTime,
);
}

static String _getAssetNameFromTrade(
String type, String? code, String? issuer) {
if (type == 'native') {
return 'XLM';
} else if (code != null && issuer != null) {
return code;
}
return 'Unknown Asset';
}
}
87 changes: 87 additions & 0 deletions app/lib/models/order_book.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
class OrderBook {
final String base;
final String counter;
final List<OrderOffer> bids;
final List<OrderOffer> asks;

OrderBook({
required this.base,
required this.counter,
required this.bids,
required this.asks,
});

factory OrderBook.fromJson(Map<String, dynamic> json) {
return OrderBook(
base: json['base'],
counter: json['counter'],
bids: (json['bids'] as List<dynamic>)
.map((e) => OrderOffer.fromJson(e))
.toList(),
asks: (json['asks'] as List<dynamic>)
.map((e) => OrderOffer.fromJson(e))
.toList(),
);
}

Map<String, dynamic> toJson() {
return {
'base': base,
'counter': counter,
'bids': bids.map((e) => e.toJson()).toList(),
'asks': asks.map((e) => e.toJson()).toList(),
};
}
}

class OrderOffer {
final String amount;
final String price;
final PriceR priceR;

OrderOffer({
required this.amount,
required this.price,
required this.priceR,
});

factory OrderOffer.fromJson(Map<String, dynamic> json) {
return OrderOffer(
amount: json['amount'],
price: json['price'],
priceR: PriceR.fromJson(json['price_r']),
);
}

Map<String, dynamic> toJson() {
return {
'amount': amount,
'price': price,
'price_r': priceR.toJson(),
};
}
}

class PriceR {
final int numerator;
final int denominator;

PriceR({
required this.numerator,
required this.denominator,
});

factory PriceR.fromJson(Map<String, dynamic> json) {
return PriceR(
numerator: json['n'],
denominator: json['d'],
);
}

Map<String, dynamic> toJson() {
return {
'n': numerator,
'd': denominator,
};
}
}
4 changes: 2 additions & 2 deletions app/lib/models/wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Wallet {
required this.name,
required this.stellarSecret,
required this.stellarAddress,
required this.stellarBalance,
required this.stellarBalances,
required this.tfchainSecret,
required this.tfchainAddress,
required this.tfchainBalance,
Expand All @@ -23,7 +23,7 @@ class Wallet {
final String stellarAddress;
final String tfchainSecret;
final String tfchainAddress;
String stellarBalance;
final Map<String, String> stellarBalances;
String tfchainBalance;
final WalletType type;
VerificationState verificationStatus;
Expand Down
9 changes: 9 additions & 0 deletions app/lib/providers/orders_notifier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'package:flutter/material.dart';

class OrderNotifier {
static final ValueNotifier<bool> orderUpdated = ValueNotifier(false);

static void emitUpdate() {
orderUpdated.value = !orderUpdated.value;
}
}
6 changes: 3 additions & 3 deletions app/lib/providers/wallets_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ class WalletsNotifier extends StateNotifier<List<Wallet>> {
final tfchainBalance =
balance.toString() == '0.0' ? '0' : balance.toString();
final stellarBalance =
await StellarService.getBalance(wallet.stellarSecret);
await StellarService.getTFTBalance(wallet.stellarSecret);

if (tfchainBalance != wallet.tfchainBalance ||
stellarBalance != wallet.stellarBalance) {
wallet.stellarBalance = stellarBalance;
stellarBalance != wallet.stellarBalances['TFT']) {
wallet.stellarBalances['TFT'] = stellarBalance;
wallet.tfchainBalance = tfchainBalance;
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/lib/screens/council_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class _CouncilScreenState extends State<CouncilScreen> {
child: Text(
style: Theme.of(context)
.textTheme
.titleLarge!
.titleMedium!
.copyWith(
color: errorMessage == null
? Theme.of(context).colorScheme.primary
Expand Down
4 changes: 2 additions & 2 deletions app/lib/screens/farm_details.dart
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,10 @@ class _FarmDetailsState extends State<FarmDetails> {
wallets: widget.wallets
.where((w) =>
double.tryParse(w
.stellarBalance) !=
.stellarBalances['TFT']!) !=
null &&
double.parse(w
.stellarBalance) >=
.stellarBalances['TFT']!) >=
0)
.toList(),
onSelectToAddress:
Expand Down
2 changes: 1 addition & 1 deletion app/lib/screens/farm_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class _FarmScreenState extends ConsumerState<FarmScreen>
onPressed: _openAddFarmOverlay,
child: Text(
'Create New Farm',
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimaryContainer,
fontWeight: FontWeight.bold,
),
Expand Down
Loading