From ef7e51403e6ad5fd2689923e594cba4e1526ae5b Mon Sep 17 00:00:00 2001 From: Dan Lopez Date: Fri, 13 Oct 2023 21:32:22 -0500 Subject: [PATCH] feat: connect getRanking function to Ranking view and render real data from blockchain --- lib/pages/my-dinogrow/my_dinogrow.dart | 44 +------ lib/pages/ranking/ranking.dart | 170 +++++++++++++++++++------ 2 files changed, 136 insertions(+), 78 deletions(-) diff --git a/lib/pages/my-dinogrow/my_dinogrow.dart b/lib/pages/my-dinogrow/my_dinogrow.dart index d7bf461..432106e 100644 --- a/lib/pages/my-dinogrow/my_dinogrow.dart +++ b/lib/pages/my-dinogrow/my_dinogrow.dart @@ -1,23 +1,19 @@ import 'dart:convert'; -import 'dart:typed_data'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; -import 'package:solana/dto.dart'; import 'package:solana/solana.dart'; import '../../anchor_types/score_parameters.dart' as anchor_types_parameters; -import '../../anchor_types/dino_score_info.dart' as anchor_types_dino; -import '../../anchor_types/dino_game_info.dart' as anchor_types_dino_game; + import '../../ui/widgets/widgets.dart'; import 'dart:math'; import 'package:solana/solana.dart' as solana; import 'package:solana/anchor.dart' as solana_anchor; import 'package:solana/encoder.dart' as solana_encoder; -import 'package:solana_common/borsh/borsh.dart' as solana_borsh; import 'package:solana_common/utils/buffer.dart' as solana_buffer; import '../../anchor_types/nft_parameters.dart' as anchor_types; @@ -137,7 +133,7 @@ class _MydinogrowScreenState extends State { child: const Padding( padding: EdgeInsets.all(3), child: Text( - "Hi ^.^ Please select one Dino to use as character when you play minigames", + "Hi ^.^ Please choose one Dino to use it as your avatar", textAlign: TextAlign.center, style: TextStyle( color: Colors.white, @@ -528,40 +524,4 @@ class _MydinogrowScreenState extends State { ); print('Tx successful with hash: $signature'); } - - getRanking() async { - //Get rank from blockchain - await dotenv.load(fileName: ".env"); - - SolanaClient? client; - client = SolanaClient( - rpcUrl: Uri.parse(dotenv.env['QUICKNODE_RPC_URL'].toString()), - websocketUrl: Uri.parse(dotenv.env['QUICKNODE_RPC_WSS'].toString()), - ); - - const programId = '9V9ttZw7WTYW78Dx3hi2hV7V76PxAs5ZwbCkGi7qq8FW'; - - // Obtener todas las cuentas del programa - final accounts = await client.rpcClient.getProgramAccounts( - programId, - encoding: Encoding.jsonParsed, - ); - - // Recorre las cuentas y muestra los datos - for (var account in accounts) { - final bytes = account.account.data as BinaryAccountData; - - //Get Score - final decoderDataScore = anchor_types_dino.DinoScoreArguments.fromBorsh( - bytes.data as Uint8List); - print("score: ${decoderDataScore.gamescore}"); - - //Get Game Data - final decoderDataGame = - anchor_types_dino_game.DinoGameArguments.fromBorsh( - bytes.data as Uint8List); - print("score: ${decoderDataGame.playerPubkey}"); - print("score: ${decoderDataGame.dinoPubkey}"); - } - } } diff --git a/lib/pages/ranking/ranking.dart b/lib/pages/ranking/ranking.dart index 18def6c..073cf91 100644 --- a/lib/pages/ranking/ranking.dart +++ b/lib/pages/ranking/ranking.dart @@ -1,15 +1,31 @@ import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:solana/solana.dart'; +import 'package:solana/dto.dart'; +import 'dart:typed_data'; +// import 'package:solana_common/borsh/borsh.dart' as solana_borsh; +import '../../anchor_types/dino_score_info.dart' as anchor_types_dino; +import '../../anchor_types/dino_game_info.dart' as anchor_types_dino_game; import '../../ui/widgets/widgets.dart'; -class RankingScreen extends StatelessWidget { - RankingScreen({super.key}); +class RankingScreen extends StatefulWidget { + const RankingScreen({super.key}); - final List items = List.generate( - 20, - (i) => ItemsProps(wallet: 'User $i', score: (i * 100).toString()), - ); + @override + State createState() => _RankingScreenState(); +} + +class _RankingScreenState extends State { + List items = []; + bool loading = true; + + @override + void initState() { + super.initState(); + getRanking(); + } @override Widget build(BuildContext context) { @@ -45,33 +61,43 @@ class RankingScreen extends StatelessWidget { color: const Color.fromRGBO(241, 189, 57, 1), width: 6), ), - child: ListView.builder( - shrinkWrap: true, - itemCount: items.length, - itemBuilder: (context, index) { - items.sort((a, b) => double.parse(b.score) - .compareTo(double.parse(a.score))); - - final item = items[index]; - - return ListTile( - leading: index < 3 - ? Icon( - Icons.emoji_events, - color: prizeColors[index], - ) - : null, - title: Text(item.wallet, - style: const TextStyle( - fontWeight: FontWeight.bold, - color: Colors.black)), - trailing: Text(item.score, - style: const TextStyle( - fontWeight: FontWeight.bold, - color: Colors.black)), - ); - }, - ), + child: loading + ? const Center( + child: CircularProgressIndicator( + color: Colors.black, + ), + ) + : RefreshIndicator( + onRefresh: getRanking, + child: ListView.builder( + shrinkWrap: true, + itemCount: items.length, + itemBuilder: (context, index) { + items.sort((a, b) => double.parse(b.gamescore) + .compareTo(double.parse(a.gamescore))); + + final item = items[index]; + + return ListTile( + leading: index < 3 + ? Icon( + Icons.emoji_events, + color: prizeColors[index], + ) + : null, + title: Text( + '${item.playerPubkey.substring(0, 5)}...${item.playerPubkey.substring(item.playerPubkey.length - 5, item.playerPubkey.length)}', + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black)), + trailing: Text(item.gamescore, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black)), + ); + }, + ), + ), ), ), ]), @@ -80,6 +106,74 @@ class RankingScreen extends StatelessWidget { ), ); } + + Future getRanking() async { + try { + List items2save = []; + + setState(() { + loading = true; + }); + + //Get rank from blockchain + await dotenv.load(fileName: ".env"); + + SolanaClient? client; + client = SolanaClient( + rpcUrl: Uri.parse(dotenv.env['QUICKNODE_RPC_URL'].toString()), + websocketUrl: Uri.parse(dotenv.env['QUICKNODE_RPC_WSS'].toString()), + ); + + const programId = '9V9ttZw7WTYW78Dx3hi2hV7V76PxAs5ZwbCkGi7qq8FW'; + + // Obtener todas las cuentas del programa + final accounts = await client.rpcClient.getProgramAccounts( + programId, + encoding: Encoding.jsonParsed, + ); + + // Recorre las cuentas y muestra los datos + for (var account in accounts) { + final bytes = account.account.data as BinaryAccountData; + + //Get Score + final decoderDataScore = anchor_types_dino.DinoScoreArguments.fromBorsh( + bytes.data as Uint8List); + + //Get Game Data + final decoderDataGame = + anchor_types_dino_game.DinoGameArguments.fromBorsh( + bytes.data as Uint8List); + + items2save.add(ItemsProps( + dinoPubkey: '${decoderDataGame.dinoPubkey}', + gamescore: '${decoderDataScore.gamescore}', + playerPubkey: '${decoderDataGame.playerPubkey}')); + + // print("score: ${decoderDataScore.gamescore}"); + // print("score: ${decoderDataGame.playerPubkey}"); + // print("score: ${decoderDataGame.dinoPubkey}"); + } + + setState(() { + items = items2save; + }); + } catch (e) { + final snackBar = SnackBar( + content: Text( + 'Error: $e', + style: const TextStyle(color: Colors.white), + ), + backgroundColor: Colors.red, + ); + + ScaffoldMessenger.of(context).showSnackBar(snackBar); + } finally { + setState(() { + loading = false; + }); + } + } } List prizeColors = List.generate( @@ -88,10 +182,14 @@ List prizeColors = List.generate( index == 0 ? Colors.orange : (index == 1 ? Colors.grey : Colors.brown)); class ItemsProps { - String wallet; - String score; + String playerPubkey; + String gamescore; + String dinoPubkey; - ItemsProps({required this.wallet, required this.score}); + ItemsProps( + {required this.playerPubkey, + required this.gamescore, + required this.dinoPubkey}); } Future _launchUrl() async {