From 3d0b83d77db131ab7265f5acf67e1b0fbc78b705 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Tue, 3 Feb 2026 12:25:32 +0800 Subject: [PATCH 1/7] add referral rank --- .../quests/referrals_quest_screen.dart | 19 ++++++++++++--- quantus_sdk/lib/quantus_sdk.dart | 1 + quantus_sdk/lib/src/models/referral_rank.dart | 24 +++++++++++++++++++ .../lib/src/services/taskmaster_service.dart | 19 +++++++++++++++ 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 quantus_sdk/lib/src/models/referral_rank.dart diff --git a/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart b/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart index 849421a0..8fd945a8 100644 --- a/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart +++ b/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart @@ -23,7 +23,9 @@ class ReferralsQuestScreen extends ConsumerStatefulWidget { class _ReferralsQuestScreenState extends ConsumerState { final ReferralService _referralService = ReferralService(); + final TaskmasterService _taskmasterService = TaskmasterService(); String? _referralCode; + int? _rank; Future _loadReferralCode() async { try { @@ -31,11 +33,22 @@ class _ReferralsQuestScreenState extends ConsumerState { setState(() { _referralCode = myReferralCode; }); + _loadRank(myReferralCode); } catch (e) { - debugPrint('Error loading account data: $e'); + debugPrint('Error loading referral code: $e'); + } + } + + Future _loadRank(String referralCode) async { + try { + final rankData = await _taskmasterService.getReferralRank(referralCode); if (mounted) { - setState(() {}); + setState(() { + _rank = rankData.rank; + }); } + } catch (e) { + debugPrint('Error loading rank: $e'); } } @@ -250,7 +263,7 @@ class _ReferralsQuestScreenState extends ConsumerState { children: [ _buildStatRow('Referrals', '$referralsCount', Colors.white), const SizedBox(height: 16), - _buildStatRow('Rank', '#-', context.themeColors.pink), + _buildStatRow('Rank', _rank != null && _rank! > 0 ? '#$_rank' : '#-', context.themeColors.pink), ], ), ), diff --git a/quantus_sdk/lib/quantus_sdk.dart b/quantus_sdk/lib/quantus_sdk.dart index b417ce73..ba023c93 100644 --- a/quantus_sdk/lib/quantus_sdk.dart +++ b/quantus_sdk/lib/quantus_sdk.dart @@ -33,6 +33,7 @@ export 'src/models/transaction_event.dart'; export 'src/models/transaction_state.dart'; export 'src/models/raider_submissions.dart'; export 'src/models/raid_quest.dart'; +export 'src/models/referral_rank.dart'; // note we have to hide some things here because they're exported by substrate service // should probably expise all of crypto.dart through substrateservice instead export 'src/rust/api/crypto.dart' hide crystalAlice, crystalCharlie, crystalBob; diff --git a/quantus_sdk/lib/src/models/referral_rank.dart b/quantus_sdk/lib/src/models/referral_rank.dart new file mode 100644 index 00000000..d908ea3e --- /dev/null +++ b/quantus_sdk/lib/src/models/referral_rank.dart @@ -0,0 +1,24 @@ +import 'package:flutter/foundation.dart'; + +@immutable +class ReferralRank { + final int rank; + final int referralsCount; + + const ReferralRank({ + required this.rank, + required this.referralsCount, + }); + + factory ReferralRank.fromJson(Map json) { + final data = json['data'] as List; + if (data.isEmpty) { + return const ReferralRank(rank: 0, referralsCount: 0); + } + final first = data[0] as Map; + return ReferralRank( + rank: first['rank'] as int, + referralsCount: first['address']['referrals_count'] as int, + ); + } +} diff --git a/quantus_sdk/lib/src/services/taskmaster_service.dart b/quantus_sdk/lib/src/services/taskmaster_service.dart index 6e2d200b..488eb1d9 100644 --- a/quantus_sdk/lib/src/services/taskmaster_service.dart +++ b/quantus_sdk/lib/src/services/taskmaster_service.dart @@ -581,4 +581,23 @@ class TaskmasterService { Future logout() async { _clearToken(); } + + Future getReferralRank(String referralCode) async { + final Uri uri = Uri.parse('${AppConstants.taskMasterEndpoint}/addresses/leaderboard?referral_code=$referralCode'); + + try { + final http.Response response = await _authenticatedHttpClient.get(uri); + + if (response.statusCode != 200) { + throw Exception('HTTP request failed with status: ${response.statusCode}. Body: ${response.body}'); + } + + final json = jsonDecode(response.body) as Map; + return ReferralRank.fromJson(json); + } catch (e, stackTrace) { + print('Error fetching referral rank: $e'); + print(stackTrace); + rethrow; + } + } } From 949f132022b2a7bbe96a216d42c665dac1fbc502 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Tue, 3 Feb 2026 13:55:15 +0800 Subject: [PATCH 2/7] fix up king of the shill - quest stats --- .../quests/king_of_the_shill_screen.dart | 42 ++++++++++++++++--- mobile-app/pubspec.yaml | 2 +- quantus_sdk/lib/quantus_sdk.dart | 1 + quantus_sdk/lib/src/models/raid_stats.dart | 35 ++++++++++++++++ .../lib/src/services/taskmaster_service.dart | 21 ++++++++++ 5 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 quantus_sdk/lib/src/models/raid_stats.dart diff --git a/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart b/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart index f57ec327..c780e0ea 100644 --- a/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart +++ b/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart @@ -21,6 +21,24 @@ class KingOfTheShillScreen extends ConsumerStatefulWidget { } class _KingOfTheShillScreenState extends ConsumerState { + final TaskmasterService _taskmasterService = TaskmasterService(); + int? _rank; + int? _totalImpressions; + + Future _loadRaidStats(int raidId) async { + try { + final stats = await _taskmasterService.getRaidStats(raidId); + if (mounted) { + setState(() { + _rank = stats.rank; + _totalImpressions = stats.totalImpressions; + }); + } + } catch (e) { + debugPrint('Error loading raid stats: $e'); + } + } + void _showHowItWorksDialog() { showDialog( context: context, @@ -114,6 +132,18 @@ class _KingOfTheShillScreenState extends ConsumerState { Widget build(BuildContext context) { final raiderSubmissionsAsync = ref.watch(raiderSubmissionsProvider); + ref.listen(raiderSubmissionsProvider, (prev, next) { + final state = next.value; + if (state is RaiderSubmissionsOk && _rank == null) { + _loadRaidStats(state.activeRaid.id); + } + }); + + if (raiderSubmissionsAsync.value is RaiderSubmissionsOk && _rank == null) { + final state = raiderSubmissionsAsync.value as RaiderSubmissionsOk; + _loadRaidStats(state.activeRaid.id); + } + return ScaffoldBase( appBar: WalletAppBar( title: 'King of The Shill', @@ -189,12 +219,12 @@ class _KingOfTheShillScreenState extends ConsumerState { child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2), ), ), - error: (_, _) => _buildStatsBox(0, 0), + error: (_, _) => _buildStatsBox(0, _totalImpressions ?? 0, _rank), data: (state) { if (state is RaiderSubmissionsOk) { - return _buildStatsBox(state.submissions.length, 0); + return _buildStatsBox(state.submissions.length, _totalImpressions ?? 0, _rank); } - return _buildStatsBox(0, 0); + return _buildStatsBox(0, _totalImpressions ?? 0, _rank); }, ), const SizedBox(height: 24), @@ -237,7 +267,7 @@ class _KingOfTheShillScreenState extends ConsumerState { ); } - Widget _buildStatsBox(int submissions, int verifiedPosts) { + Widget _buildStatsBox(int submissions, int totalImpressions, int? rank) { return Container( width: double.infinity, padding: const EdgeInsets.all(16), @@ -253,9 +283,9 @@ class _KingOfTheShillScreenState extends ConsumerState { children: [ _buildStatRow('Submissions', '$submissions', Colors.white), const SizedBox(height: 16), - _buildStatRow('Verified posts', verifiedPosts.toString().padLeft(2, '0'), Colors.white), + _buildStatRow('Total impressions', '$totalImpressions', Colors.white), const SizedBox(height: 16), - _buildStatRow('Rank', '#-', context.themeColors.pink), + _buildStatRow('Rank', rank != null && rank > 0 ? '#$rank' : '#-', context.themeColors.pink), ], ), ); diff --git a/mobile-app/pubspec.yaml b/mobile-app/pubspec.yaml index 09fb807d..d4aa8b23 100644 --- a/mobile-app/pubspec.yaml +++ b/mobile-app/pubspec.yaml @@ -2,7 +2,7 @@ name: resonance_network_wallet description: A Flutter wallet for the Quantus blockchain. publish_to: "none" -version: 1.1.5+66 +version: 1.1.5+66x environment: sdk: ">=3.8.0 <4.0.0" diff --git a/quantus_sdk/lib/quantus_sdk.dart b/quantus_sdk/lib/quantus_sdk.dart index ba023c93..8de791c5 100644 --- a/quantus_sdk/lib/quantus_sdk.dart +++ b/quantus_sdk/lib/quantus_sdk.dart @@ -34,6 +34,7 @@ export 'src/models/transaction_state.dart'; export 'src/models/raider_submissions.dart'; export 'src/models/raid_quest.dart'; export 'src/models/referral_rank.dart'; +export 'src/models/raid_stats.dart'; // note we have to hide some things here because they're exported by substrate service // should probably expise all of crypto.dart through substrateservice instead export 'src/rust/api/crypto.dart' hide crystalAlice, crystalCharlie, crystalBob; diff --git a/quantus_sdk/lib/src/models/raid_stats.dart b/quantus_sdk/lib/src/models/raid_stats.dart new file mode 100644 index 00000000..b3054542 --- /dev/null +++ b/quantus_sdk/lib/src/models/raid_stats.dart @@ -0,0 +1,35 @@ +import 'package:flutter/foundation.dart'; + +@immutable +class RaidStats { + final int raidId; + final int rank; + final int totalSubmissions; + final int totalImpressions; + final int totalReplies; + final int totalRetweets; + final int totalLikes; + + const RaidStats({ + required this.raidId, + required this.rank, + required this.totalSubmissions, + required this.totalImpressions, + required this.totalReplies, + required this.totalRetweets, + required this.totalLikes, + }); + + factory RaidStats.fromJson(Map json) { + final data = json['data'] as Map; + return RaidStats( + raidId: data['raid_id'] as int, + rank: data['rank'] as int, + totalSubmissions: data['total_submissions'] as int, + totalImpressions: data['total_impressions'] as int, + totalReplies: data['total_replies'] as int, + totalRetweets: data['total_retweets'] as int, + totalLikes: data['total_likes'] as int, + ); + } +} diff --git a/quantus_sdk/lib/src/services/taskmaster_service.dart b/quantus_sdk/lib/src/services/taskmaster_service.dart index 488eb1d9..95b5de80 100644 --- a/quantus_sdk/lib/src/services/taskmaster_service.dart +++ b/quantus_sdk/lib/src/services/taskmaster_service.dart @@ -600,4 +600,25 @@ class TaskmasterService { rethrow; } } + + Future getRaidStats(int raidId) async { + final activeAccount = await getMainAccount(); + final Uri uri = Uri.parse('${AppConstants.taskMasterEndpoint}/raid-quests/raiders/${activeAccount.accountId}/leaderboards/$raidId'); + +print('getRaidStats $uri'); + try { + final http.Response response = await _authenticatedHttpClient.get(uri); + + if (response.statusCode != 200) { + throw Exception('HTTP request failed with status: ${response.statusCode}. Body: ${response.body}'); + } + + final json = jsonDecode(response.body) as Map; + return RaidStats.fromJson(json); + } catch (e, stackTrace) { + print('Error fetching raid stats: $e'); + print(stackTrace); + rethrow; + } + } } From 6646dca2e7465f323409449d2490a0d9fe5b1e5a Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Tue, 3 Feb 2026 14:00:38 +0800 Subject: [PATCH 3/7] format --- .../main/screens/quests/referrals_quest_screen.dart | 6 +++++- quantus_sdk/lib/src/models/referral_rank.dart | 10 ++-------- quantus_sdk/lib/src/services/taskmaster_service.dart | 6 ++++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart b/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart index 8fd945a8..68c0aaa5 100644 --- a/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart +++ b/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart @@ -263,7 +263,11 @@ class _ReferralsQuestScreenState extends ConsumerState { children: [ _buildStatRow('Referrals', '$referralsCount', Colors.white), const SizedBox(height: 16), - _buildStatRow('Rank', _rank != null && _rank! > 0 ? '#$_rank' : '#-', context.themeColors.pink), + _buildStatRow( + 'Rank', + _rank != null && _rank! > 0 ? '#$_rank' : '#-', + context.themeColors.pink, + ), ], ), ), diff --git a/quantus_sdk/lib/src/models/referral_rank.dart b/quantus_sdk/lib/src/models/referral_rank.dart index d908ea3e..121a4e94 100644 --- a/quantus_sdk/lib/src/models/referral_rank.dart +++ b/quantus_sdk/lib/src/models/referral_rank.dart @@ -5,10 +5,7 @@ class ReferralRank { final int rank; final int referralsCount; - const ReferralRank({ - required this.rank, - required this.referralsCount, - }); + const ReferralRank({required this.rank, required this.referralsCount}); factory ReferralRank.fromJson(Map json) { final data = json['data'] as List; @@ -16,9 +13,6 @@ class ReferralRank { return const ReferralRank(rank: 0, referralsCount: 0); } final first = data[0] as Map; - return ReferralRank( - rank: first['rank'] as int, - referralsCount: first['address']['referrals_count'] as int, - ); + return ReferralRank(rank: first['rank'] as int, referralsCount: first['address']['referrals_count'] as int); } } diff --git a/quantus_sdk/lib/src/services/taskmaster_service.dart b/quantus_sdk/lib/src/services/taskmaster_service.dart index 95b5de80..93b21e4d 100644 --- a/quantus_sdk/lib/src/services/taskmaster_service.dart +++ b/quantus_sdk/lib/src/services/taskmaster_service.dart @@ -603,9 +603,11 @@ class TaskmasterService { Future getRaidStats(int raidId) async { final activeAccount = await getMainAccount(); - final Uri uri = Uri.parse('${AppConstants.taskMasterEndpoint}/raid-quests/raiders/${activeAccount.accountId}/leaderboards/$raidId'); + final Uri uri = Uri.parse( + '${AppConstants.taskMasterEndpoint}/raid-quests/raiders/${activeAccount.accountId}/leaderboards/$raidId', + ); -print('getRaidStats $uri'); + print('getRaidStats $uri'); try { final http.Response response = await _authenticatedHttpClient.get(uri); From aee4e3f7916cbcecfa061cc6417fa10b271af61d Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Tue, 3 Feb 2026 14:20:06 +0800 Subject: [PATCH 4/7] refactor for DRY, add loading indicators --- .../quests/king_of_the_shill_screen.dart | 91 +++++++++++++------ .../quests/referrals_quest_screen.dart | 34 +++++-- mobile-app/pubspec.yaml | 2 +- .../lib/src/services/taskmaster_service.dart | 72 +++------------ 4 files changed, 102 insertions(+), 97 deletions(-) diff --git a/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart b/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart index c780e0ea..1607f9dd 100644 --- a/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart +++ b/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart @@ -25,6 +25,15 @@ class _KingOfTheShillScreenState extends ConsumerState { int? _rank; int? _totalImpressions; + @override + void initState() { + super.initState(); + final asyncValue = ref.read(raiderSubmissionsProvider); + if (asyncValue.value is RaiderSubmissionsOk) { + _loadRaidStats((asyncValue.value as RaiderSubmissionsOk).activeRaid.id); + } + } + Future _loadRaidStats(int raidId) async { try { final stats = await _taskmasterService.getRaidStats(raidId); @@ -139,11 +148,6 @@ class _KingOfTheShillScreenState extends ConsumerState { } }); - if (raiderSubmissionsAsync.value is RaiderSubmissionsOk && _rank == null) { - final state = raiderSubmissionsAsync.value as RaiderSubmissionsOk; - _loadRaidStats(state.activeRaid.id); - } - return ScaffoldBase( appBar: WalletAppBar( title: 'King of The Shill', @@ -211,23 +215,23 @@ class _KingOfTheShillScreenState extends ConsumerState { ), ), const SizedBox(height: 40), - raiderSubmissionsAsync.when( - loading: () => const Center( - child: SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2), - ), + raiderSubmissionsAsync.when( + loading: () => const Center( + child: SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2), ), - error: (_, _) => _buildStatsBox(0, _totalImpressions ?? 0, _rank), - data: (state) { - if (state is RaiderSubmissionsOk) { - return _buildStatsBox(state.submissions.length, _totalImpressions ?? 0, _rank); - } - return _buildStatsBox(0, _totalImpressions ?? 0, _rank); - }, ), - const SizedBox(height: 24), + error: (_, _) => _buildStatsBox(0, _totalImpressions, _rank), + data: (state) { + if (state is RaiderSubmissionsOk) { + return _buildStatsBox(state.submissions.length, _totalImpressions, _rank); + } + return _buildStatsBox(0, _totalImpressions, _rank); + }, + ), + const SizedBox(height: 24), _buildPastSubmissionsSection(raiderSubmissionsAsync), const Spacer(), _buildSubmitSection(), @@ -267,7 +271,7 @@ class _KingOfTheShillScreenState extends ConsumerState { ); } - Widget _buildStatsBox(int submissions, int totalImpressions, int? rank) { + Widget _buildStatsBox(int submissions, int? totalImpressions, int? rank) { return Container( width: double.infinity, padding: const EdgeInsets.all(16), @@ -281,17 +285,49 @@ class _KingOfTheShillScreenState extends ConsumerState { ), child: Column( children: [ - _buildStatRow('Submissions', '$submissions', Colors.white), + _buildStatRow( + 'Submissions', + Text( + '$submissions', + style: const TextStyle( + color: Colors.white, + fontSize: 14, + fontFamily: 'Fira Code', + fontWeight: FontWeight.w400, + ), + ), + ), const SizedBox(height: 16), - _buildStatRow('Total impressions', '$totalImpressions', Colors.white), + _buildStatRow( + 'Total impressions', + _buildLoadingOrValue(totalImpressions, Colors.white), + ), const SizedBox(height: 16), - _buildStatRow('Rank', rank != null && rank > 0 ? '#$rank' : '#-', context.themeColors.pink), + _buildStatRow( + 'Rank', + _buildLoadingOrValue(rank, context.themeColors.pink, isRank: true), + ), ], ), ); } - Widget _buildStatRow(String label, String value, Color valueColor) { + Widget _buildLoadingOrValue(int? value, Color color, {bool isRank = false}) { + if (value == null) { + return SizedBox( + width: 12, + height: 12, + child: CircularProgressIndicator(strokeWidth: 2, color: color), + ); + } + final text = isRank ? (value > 0 ? '#$value' : '#-') : '$value'; + return Text( + text, + style: TextStyle(color: color, fontSize: 14, fontFamily: 'Fira Code', fontWeight: FontWeight.w400), + ); + } + + Widget _buildStatRow(String label, Widget valueWidget) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -304,10 +340,7 @@ class _KingOfTheShillScreenState extends ConsumerState { fontWeight: FontWeight.w400, ), ), - Text( - value, - style: TextStyle(color: valueColor, fontSize: 14, fontFamily: 'Fira Code', fontWeight: FontWeight.w400), - ), + valueWidget, ], ); } diff --git a/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart b/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart index 68c0aaa5..c4c64fc3 100644 --- a/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart +++ b/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart @@ -158,7 +158,7 @@ class _ReferralsQuestScreenState extends ConsumerState { @override Widget build(BuildContext context) { final statsAsync = ref.watch(accountsStatsProvider); - final referralsCount = statsAsync.value?.referralCount ?? 0; + final referralsCount = statsAsync.value?.referralCount; return ScaffoldBase( appBar: WalletAppBar( @@ -261,12 +261,14 @@ class _ReferralsQuestScreenState extends ConsumerState { ), child: Column( children: [ - _buildStatRow('Referrals', '$referralsCount', Colors.white), + _buildStatRow( + 'Referrals', + _buildLoadingOrValue(referralsCount, Colors.white), + ), const SizedBox(height: 16), _buildStatRow( 'Rank', - _rank != null && _rank! > 0 ? '#$_rank' : '#-', - context.themeColors.pink, + _buildLoadingOrValue(_rank, context.themeColors.pink, isRank: true), ), ], ), @@ -366,7 +368,7 @@ class _ReferralsQuestScreenState extends ConsumerState { ); } - Widget _buildStatRow(String label, String value, Color valueColor) { + Widget _buildStatRow(String label, Widget valueWidget) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -379,12 +381,24 @@ class _ReferralsQuestScreenState extends ConsumerState { fontWeight: FontWeight.w400, ), ), - Text( - value, - textAlign: TextAlign.center, - style: TextStyle(color: valueColor, fontSize: 14, fontFamily: 'Fira Code', fontWeight: FontWeight.w400), - ), + valueWidget, ], ); } + + Widget _buildLoadingOrValue(int? value, Color color, {bool isRank = false}) { + if (value == null) { + return SizedBox( + width: 12, + height: 12, + child: CircularProgressIndicator(strokeWidth: 2, color: color), + ); + } + final text = isRank ? (value > 0 ? '#$value' : '#-') : '$value'; + return Text( + text, + textAlign: TextAlign.center, + style: TextStyle(color: color, fontSize: 14, fontFamily: 'Fira Code', fontWeight: FontWeight.w400), + ); + } } diff --git a/mobile-app/pubspec.yaml b/mobile-app/pubspec.yaml index d4aa8b23..09fb807d 100644 --- a/mobile-app/pubspec.yaml +++ b/mobile-app/pubspec.yaml @@ -2,7 +2,7 @@ name: resonance_network_wallet description: A Flutter wallet for the Quantus blockchain. publish_to: "none" -version: 1.1.5+66x +version: 1.1.5+66 environment: sdk: ">=3.8.0 <4.0.0" diff --git a/quantus_sdk/lib/src/services/taskmaster_service.dart b/quantus_sdk/lib/src/services/taskmaster_service.dart index 93b21e4d..9fac8836 100644 --- a/quantus_sdk/lib/src/services/taskmaster_service.dart +++ b/quantus_sdk/lib/src/services/taskmaster_service.dart @@ -464,29 +464,30 @@ class TaskmasterService { } } - Future getAccountAssociations() async { - final activeAccount = await getMainAccount(); - print('getAccountAssociations ${activeAccount.accountId}'); - final accountAssociationsEndpoint = Uri.parse('${AppConstants.taskMasterEndpoint}/addresses/associations'); - + Future _authenticatedGet(Uri uri, T Function(Map) fromJson) async { try { - final http.Response response = await _authenticatedHttpClient.get(accountAssociationsEndpoint); + final response = await _authenticatedHttpClient.get(uri); if (response.statusCode != 200) { - throw Exception( - 'Account Associations http request failed with status: ${response.statusCode}. Body: ${response.body}', - ); + throw Exception('HTTP request failed with status: ${response.statusCode}. Body: ${response.body}'); } final json = jsonDecode(response.body) as Map; - return AccountAssociations.fromJson(json); + return fromJson(json); } catch (e, stackTrace) { - print('Error fetching miner stats: $e'); + print('Error fetching data from $uri: $e'); print(stackTrace); rethrow; } } + Future getAccountAssociations() async { + final activeAccount = await getMainAccount(); + print('getAccountAssociations ${activeAccount.accountId}'); + final accountAssociationsEndpoint = Uri.parse('${AppConstants.taskMasterEndpoint}/addresses/associations'); + return _authenticatedGet(accountAssociationsEndpoint, AccountAssociations.fromJson); + } + Future submitAddress() async { await ensureIsLoggedIn(); } @@ -561,21 +562,7 @@ class TaskmasterService { Future getOptInPosition() async { final Uri uri = Uri.parse('${AppConstants.taskMasterEndpoint}/addresses/my-position'); - - try { - final http.Response response = await _authenticatedHttpClient.get(uri); - - if (response.statusCode != 200) { - throw Exception('HTTP request failed with status: ${response.statusCode}. Body: ${response.body}'); - } - - final json = jsonDecode(response.body) as Map; - return OptedInPosition.fromJson(json); - } catch (e, stackTrace) { - print('Error fetching address stats: $e'); - print(stackTrace); - rethrow; - } + return _authenticatedGet(uri, OptedInPosition.fromJson); } Future logout() async { @@ -584,21 +571,7 @@ class TaskmasterService { Future getReferralRank(String referralCode) async { final Uri uri = Uri.parse('${AppConstants.taskMasterEndpoint}/addresses/leaderboard?referral_code=$referralCode'); - - try { - final http.Response response = await _authenticatedHttpClient.get(uri); - - if (response.statusCode != 200) { - throw Exception('HTTP request failed with status: ${response.statusCode}. Body: ${response.body}'); - } - - final json = jsonDecode(response.body) as Map; - return ReferralRank.fromJson(json); - } catch (e, stackTrace) { - print('Error fetching referral rank: $e'); - print(stackTrace); - rethrow; - } + return _authenticatedGet(uri, ReferralRank.fromJson); } Future getRaidStats(int raidId) async { @@ -606,21 +579,6 @@ class TaskmasterService { final Uri uri = Uri.parse( '${AppConstants.taskMasterEndpoint}/raid-quests/raiders/${activeAccount.accountId}/leaderboards/$raidId', ); - - print('getRaidStats $uri'); - try { - final http.Response response = await _authenticatedHttpClient.get(uri); - - if (response.statusCode != 200) { - throw Exception('HTTP request failed with status: ${response.statusCode}. Body: ${response.body}'); - } - - final json = jsonDecode(response.body) as Map; - return RaidStats.fromJson(json); - } catch (e, stackTrace) { - print('Error fetching raid stats: $e'); - print(stackTrace); - rethrow; - } + return _authenticatedGet(uri, RaidStats.fromJson); } } From cc5318fa34ba35146333284f2b61eeb1852bb65d Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Tue, 3 Feb 2026 14:20:15 +0800 Subject: [PATCH 5/7] format --- .../quests/king_of_the_shill_screen.dart | 46 ++++++++----------- .../quests/referrals_quest_screen.dart | 11 +---- 2 files changed, 20 insertions(+), 37 deletions(-) diff --git a/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart b/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart index 1607f9dd..49eeb246 100644 --- a/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart +++ b/mobile-app/lib/features/main/screens/quests/king_of_the_shill_screen.dart @@ -215,23 +215,23 @@ class _KingOfTheShillScreenState extends ConsumerState { ), ), const SizedBox(height: 40), - raiderSubmissionsAsync.when( - loading: () => const Center( - child: SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2), + raiderSubmissionsAsync.when( + loading: () => const Center( + child: SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2), + ), ), + error: (_, _) => _buildStatsBox(0, _totalImpressions, _rank), + data: (state) { + if (state is RaiderSubmissionsOk) { + return _buildStatsBox(state.submissions.length, _totalImpressions, _rank); + } + return _buildStatsBox(0, _totalImpressions, _rank); + }, ), - error: (_, _) => _buildStatsBox(0, _totalImpressions, _rank), - data: (state) { - if (state is RaiderSubmissionsOk) { - return _buildStatsBox(state.submissions.length, _totalImpressions, _rank); - } - return _buildStatsBox(0, _totalImpressions, _rank); - }, - ), - const SizedBox(height: 24), + const SizedBox(height: 24), _buildPastSubmissionsSection(raiderSubmissionsAsync), const Spacer(), _buildSubmitSection(), @@ -298,15 +298,9 @@ class _KingOfTheShillScreenState extends ConsumerState { ), ), const SizedBox(height: 16), - _buildStatRow( - 'Total impressions', - _buildLoadingOrValue(totalImpressions, Colors.white), - ), + _buildStatRow('Total impressions', _buildLoadingOrValue(totalImpressions, Colors.white)), const SizedBox(height: 16), - _buildStatRow( - 'Rank', - _buildLoadingOrValue(rank, context.themeColors.pink, isRank: true), - ), + _buildStatRow('Rank', _buildLoadingOrValue(rank, context.themeColors.pink, isRank: true)), ], ), ); @@ -314,11 +308,7 @@ class _KingOfTheShillScreenState extends ConsumerState { Widget _buildLoadingOrValue(int? value, Color color, {bool isRank = false}) { if (value == null) { - return SizedBox( - width: 12, - height: 12, - child: CircularProgressIndicator(strokeWidth: 2, color: color), - ); + return SizedBox(width: 12, height: 12, child: CircularProgressIndicator(strokeWidth: 2, color: color)); } final text = isRank ? (value > 0 ? '#$value' : '#-') : '$value'; return Text( diff --git a/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart b/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart index c4c64fc3..3b49944a 100644 --- a/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart +++ b/mobile-app/lib/features/main/screens/quests/referrals_quest_screen.dart @@ -261,10 +261,7 @@ class _ReferralsQuestScreenState extends ConsumerState { ), child: Column( children: [ - _buildStatRow( - 'Referrals', - _buildLoadingOrValue(referralsCount, Colors.white), - ), + _buildStatRow('Referrals', _buildLoadingOrValue(referralsCount, Colors.white)), const SizedBox(height: 16), _buildStatRow( 'Rank', @@ -388,11 +385,7 @@ class _ReferralsQuestScreenState extends ConsumerState { Widget _buildLoadingOrValue(int? value, Color color, {bool isRank = false}) { if (value == null) { - return SizedBox( - width: 12, - height: 12, - child: CircularProgressIndicator(strokeWidth: 2, color: color), - ); + return SizedBox(width: 12, height: 12, child: CircularProgressIndicator(strokeWidth: 2, color: color)); } final text = isRank ? (value > 0 ? '#$value' : '#-') : '$value'; return Text( From 4d826dcef9676df4a7e5a35e88faaceb1742f305 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Tue, 3 Feb 2026 14:24:24 +0800 Subject: [PATCH 6/7] build 67 --- mobile-app/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile-app/pubspec.yaml b/mobile-app/pubspec.yaml index 09fb807d..e42d4218 100644 --- a/mobile-app/pubspec.yaml +++ b/mobile-app/pubspec.yaml @@ -2,7 +2,7 @@ name: resonance_network_wallet description: A Flutter wallet for the Quantus blockchain. publish_to: "none" -version: 1.1.5+66 +version: 1.1.5+67 environment: sdk: ">=3.8.0 <4.0.0" From 0cbf43fa12a7936e7bf8ae734fbdce788195606f Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Tue, 3 Feb 2026 14:30:59 +0800 Subject: [PATCH 7/7] new flutter syntax --- mobile-app/lib/features/components/card_info.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile-app/lib/features/components/card_info.dart b/mobile-app/lib/features/components/card_info.dart index 498f3586..50e8b323 100644 --- a/mobile-app/lib/features/components/card_info.dart +++ b/mobile-app/lib/features/components/card_info.dart @@ -36,7 +36,7 @@ class CardInfo extends StatelessWidget { width: context.isTablet ? 660 : 251, child: Text(text, style: context.themeText.tag?.copyWith(color: textColor)), ), - if (icon != null) icon!, + ?icon, ], ), ),