diff --git a/lib/anchor_types/get_dino_score.dart b/lib/anchor_types/get_dino_score.dart new file mode 100644 index 0000000..45dafa4 --- /dev/null +++ b/lib/anchor_types/get_dino_score.dart @@ -0,0 +1,21 @@ +import 'package:borsh_annotation/borsh_annotation.dart'; +import 'package:solana/solana.dart'; + +part 'get_dino_score.g.dart'; + +@BorshSerializable() +class GetScoreArguments with _$GetScoreArguments { + factory GetScoreArguments( + { + @BU64() required BigInt deterministicId, + @BU32() required int score, + @BU32() required int game, + @BPublicKey() required Ed25519HDPublicKey playerkey, + @BPublicKey() required Ed25519HDPublicKey dinokey, + }) = _GetScoreArguments; + + const GetScoreArguments._(); + + factory GetScoreArguments.fromBorsh(Uint8List data) => + _$GetScoreArgumentsFromBorsh(data); +} \ No newline at end of file diff --git a/lib/anchor_types/get_dino_score.g.dart b/lib/anchor_types/get_dino_score.g.dart new file mode 100644 index 0000000..53158c4 --- /dev/null +++ b/lib/anchor_types/get_dino_score.g.dart @@ -0,0 +1,69 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_dino_score.dart'; + +// ************************************************************************** +// BorshSerializableGenerator +// ************************************************************************** + +mixin _$GetScoreArguments { + BigInt get deterministicId => throw UnimplementedError(); + int get score => throw UnimplementedError(); + int get game => throw UnimplementedError(); + Ed25519HDPublicKey get playerkey => throw UnimplementedError(); + Ed25519HDPublicKey get dinokey => throw UnimplementedError(); + + Uint8List toBorsh() { + final writer = BinaryWriter(); + + const BU64().write(writer, deterministicId); + const BU32().write(writer, score); + const BU32().write(writer, game); + const BPublicKey().write(writer, playerkey); + const BPublicKey().write(writer, dinokey); + + return writer.toArray(); + } +} + +class _GetScoreArguments extends GetScoreArguments { + _GetScoreArguments({ + required this.deterministicId, + required this.score, + required this.game, + required this.playerkey, + required this.dinokey, + }) : super._(); + + final BigInt deterministicId; + final int score; + final int game; + final Ed25519HDPublicKey playerkey; + final Ed25519HDPublicKey dinokey; +} + +class BGetScoreArguments implements BType { + const BGetScoreArguments(); + + @override + void write(BinaryWriter writer, GetScoreArguments value) { + writer.writeStruct(value.toBorsh()); + } + + @override + GetScoreArguments read(BinaryReader reader) { + return GetScoreArguments( + deterministicId: const BU64().read(reader), + score: const BU32().read(reader), + game: const BU32().read(reader), + playerkey: const BPublicKey().read(reader), + dinokey: const BPublicKey().read(reader), + ); + } +} + +GetScoreArguments _$GetScoreArgumentsFromBorsh(Uint8List data) { + final reader = BinaryReader(data.buffer.asByteData()); + + return const BGetScoreArguments().read(reader); +} diff --git a/lib/anchor_types/get_profile_info.dart b/lib/anchor_types/get_profile_info.dart new file mode 100644 index 0000000..352372a --- /dev/null +++ b/lib/anchor_types/get_profile_info.dart @@ -0,0 +1,22 @@ +import 'package:borsh_annotation/borsh_annotation.dart'; +import 'package:solana/solana.dart'; + +part 'get_profile_info.g.dart'; + +@BorshSerializable() +class GetProfileArguments with _$GetProfileArguments { + factory GetProfileArguments( + { + @BU64() required BigInt deterministicId, + @BString() required String nickname, + @BString() required String bio, + @BString() required String status, + @BString() required String uri, + @BPublicKey() required Ed25519HDPublicKey playerkey, + }) = _GetProfileArguments; + + const GetProfileArguments._(); + + factory GetProfileArguments.fromBorsh(Uint8List data) => + _$GetProfileArgumentsFromBorsh(data); +} \ No newline at end of file diff --git a/lib/anchor_types/get_profile_info.g.dart b/lib/anchor_types/get_profile_info.g.dart new file mode 100644 index 0000000..092438f --- /dev/null +++ b/lib/anchor_types/get_profile_info.g.dart @@ -0,0 +1,74 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_profile_info.dart'; + +// ************************************************************************** +// BorshSerializableGenerator +// ************************************************************************** + +mixin _$GetProfileArguments { + BigInt get deterministicId => throw UnimplementedError(); + String get nickname => throw UnimplementedError(); + String get bio => throw UnimplementedError(); + String get status => throw UnimplementedError(); + String get uri => throw UnimplementedError(); + Ed25519HDPublicKey get playerkey => throw UnimplementedError(); + + Uint8List toBorsh() { + final writer = BinaryWriter(); + + const BU64().write(writer, deterministicId); + const BString().write(writer, nickname); + const BString().write(writer, bio); + const BString().write(writer, status); + const BString().write(writer, uri); + const BPublicKey().write(writer, playerkey); + + return writer.toArray(); + } +} + +class _GetProfileArguments extends GetProfileArguments { + _GetProfileArguments({ + required this.deterministicId, + required this.nickname, + required this.bio, + required this.status, + required this.uri, + required this.playerkey, + }) : super._(); + + final BigInt deterministicId; + final String nickname; + final String bio; + final String status; + final String uri; + final Ed25519HDPublicKey playerkey; +} + +class BGetProfileArguments implements BType { + const BGetProfileArguments(); + + @override + void write(BinaryWriter writer, GetProfileArguments value) { + writer.writeStruct(value.toBorsh()); + } + + @override + GetProfileArguments read(BinaryReader reader) { + return GetProfileArguments( + deterministicId: const BU64().read(reader), + nickname: const BString().read(reader), + bio: const BString().read(reader), + status: const BString().read(reader), + uri: const BString().read(reader), + playerkey: const BPublicKey().read(reader), + ); + } +} + +GetProfileArguments _$GetProfileArgumentsFromBorsh(Uint8List data) { + final reader = BinaryReader(data.buffer.asByteData()); + + return const BGetProfileArguments().read(reader); +} diff --git a/lib/anchor_types/put_dino_score.dart b/lib/anchor_types/put_dino_score.dart new file mode 100644 index 0000000..2afd17d --- /dev/null +++ b/lib/anchor_types/put_dino_score.dart @@ -0,0 +1,17 @@ +import 'package:borsh_annotation/borsh_annotation.dart'; + +part 'put_dino_score.g.dart'; + +@BorshSerializable() +class PutScoreArguments with _$PutScoreArguments { + factory PutScoreArguments( + { + @BU32() required int game, + @BU32() required int score, + }) = _PutScoreArguments; + + const PutScoreArguments._(); + + factory PutScoreArguments.fromBorsh(Uint8List data) => + _$PutScoreArgumentsFromBorsh(data); +} \ No newline at end of file diff --git a/lib/anchor_types/put_dino_score.g.dart b/lib/anchor_types/put_dino_score.g.dart new file mode 100644 index 0000000..c689115 --- /dev/null +++ b/lib/anchor_types/put_dino_score.g.dart @@ -0,0 +1,54 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'put_dino_score.dart'; + +// ************************************************************************** +// BorshSerializableGenerator +// ************************************************************************** + +mixin _$PutScoreArguments { + int get game => throw UnimplementedError(); + int get score => throw UnimplementedError(); + + Uint8List toBorsh() { + final writer = BinaryWriter(); + + const BU32().write(writer, game); + const BU32().write(writer, score); + + return writer.toArray(); + } +} + +class _PutScoreArguments extends PutScoreArguments { + _PutScoreArguments({ + required this.game, + required this.score, + }) : super._(); + + final int game; + final int score; +} + +class BPutScoreArguments implements BType { + const BPutScoreArguments(); + + @override + void write(BinaryWriter writer, PutScoreArguments value) { + writer.writeStruct(value.toBorsh()); + } + + @override + PutScoreArguments read(BinaryReader reader) { + return PutScoreArguments( + game: const BU32().read(reader), + score: const BU32().read(reader), + ); + } +} + +PutScoreArguments _$PutScoreArgumentsFromBorsh(Uint8List data) { + final reader = BinaryReader(data.buffer.asByteData()); + + return const BPutScoreArguments().read(reader); +} diff --git a/lib/anchor_types/put_profile_info.dart b/lib/anchor_types/put_profile_info.dart new file mode 100644 index 0000000..a54b87b --- /dev/null +++ b/lib/anchor_types/put_profile_info.dart @@ -0,0 +1,20 @@ +import 'package:borsh_annotation/borsh_annotation.dart'; +import 'package:solana/solana.dart'; + +part 'put_profile_info.g.dart'; + +@BorshSerializable() +class PutProfileArguments with _$PutProfileArguments { + factory PutProfileArguments( + { + @BString() required String nickname, + @BString() required String bio, + @BString() required String status, + @BString() required String uri, + }) = _PutProfileArguments; + + const PutProfileArguments._(); + + factory PutProfileArguments.fromBorsh(Uint8List data) => + _$PutProfileArgumentsFromBorsh(data); +} \ No newline at end of file diff --git a/lib/anchor_types/put_profile_info.g.dart b/lib/anchor_types/put_profile_info.g.dart new file mode 100644 index 0000000..99e5e5f --- /dev/null +++ b/lib/anchor_types/put_profile_info.g.dart @@ -0,0 +1,64 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'put_profile_info.dart'; + +// ************************************************************************** +// BorshSerializableGenerator +// ************************************************************************** + +mixin _$PutProfileArguments { + String get nickname => throw UnimplementedError(); + String get bio => throw UnimplementedError(); + String get status => throw UnimplementedError(); + String get uri => throw UnimplementedError(); + + Uint8List toBorsh() { + final writer = BinaryWriter(); + + const BString().write(writer, nickname); + const BString().write(writer, bio); + const BString().write(writer, status); + const BString().write(writer, uri); + + return writer.toArray(); + } +} + +class _PutProfileArguments extends PutProfileArguments { + _PutProfileArguments({ + required this.nickname, + required this.bio, + required this.status, + required this.uri, + }) : super._(); + + final String nickname; + final String bio; + final String status; + final String uri; +} + +class BPutProfileArguments implements BType { + const BPutProfileArguments(); + + @override + void write(BinaryWriter writer, PutProfileArguments value) { + writer.writeStruct(value.toBorsh()); + } + + @override + PutProfileArguments read(BinaryReader reader) { + return PutProfileArguments( + nickname: const BString().read(reader), + bio: const BString().read(reader), + status: const BString().read(reader), + uri: const BString().read(reader), + ); + } +} + +PutProfileArguments _$PutProfileArgumentsFromBorsh(Uint8List data) { + final reader = BinaryReader(data.buffer.asByteData()); + + return const BPutProfileArguments().read(reader); +} diff --git a/lib/pages/mini-games/up/down.dart b/lib/pages/mini-games/up/down.dart index e050e65..ff0a5df 100644 --- a/lib/pages/mini-games/up/down.dart +++ b/lib/pages/mini-games/up/down.dart @@ -1,3 +1,5 @@ +import 'dart:typed_data'; + import 'package:dinogrow/pages/mini-games/up/buttons.dart'; import 'package:dinogrow/pages/mini-games/up/objects/dino.dart'; import 'package:flame/palette.dart'; @@ -11,8 +13,9 @@ import 'objects/floor.dart'; import 'objects/box.dart'; import 'package:flame/timer.dart' as timer_flame; import 'package:url_launcher/url_launcher.dart'; +import 'package:solana_web3/solana_web3.dart' as web3; -import '../../../anchor_types/score_parameters.dart' as anchor_types_parameters; +import '../../../anchor_types/put_dino_score.dart' as anchor_types_parameters; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; @@ -469,6 +472,19 @@ class _GameWidgetDownState extends State { mainWalletKey!, ); + //Generate internal wallet + String dinoString = dotenv.env['DINO_KEY'].toString(); + dinoString = dinoString.replaceAll(RegExp(r'\[|\]'), ''); + List valueStrings = dinoString.split(','); + List integerList = + (valueStrings).map((value) => int.parse(value)).toList(); + Uint8List secretKey = Uint8List.fromList(integerList); + final keypair = await web3.Keypair.fromSecretKey(secretKey); + //path: "m/44'/501'/0'/0'/0'", + String hdPath = dotenv.env['HD_PATH'].toString(); + final walletdino = await solana.Ed25519HDKeyPair.fromSeedWithHdPath( + seed: keypair.secretKey, hdPath: hdPath); + final programId = dotenv.env['PROGRAM_ID'].toString(); final systemProgramId = solana.Ed25519HDPublicKey.fromBase58(solana.SystemProgram.programId); @@ -488,7 +504,7 @@ class _GameWidgetDownState extends State { final gscorePda = await solana.Ed25519HDPublicKey.findProgramAddress( programId: programIdPublicKey, seeds: [ - solana_buffer.Buffer.fromString("score"), + solana_buffer.Buffer.fromString(dotenv.env['SCORE_SEED'].toString()), mainWalletSolana.publicKey.bytes, dinoTest.bytes, solana_buffer.Buffer.fromInt32(1), @@ -500,7 +516,7 @@ class _GameWidgetDownState extends State { programId: programIdPublicKey, method: 'savescore', arguments: - solana_encoder.ByteArray(anchor_types_parameters.ScoreArguments( + solana_encoder.ByteArray(anchor_types_parameters.PutScoreArguments( game: 1, score: score, ).toBorsh().toList()), @@ -513,6 +529,8 @@ class _GameWidgetDownState extends State { pubKey: dinoTest, isSigner: false), solana_encoder.AccountMeta.readonly( pubKey: systemProgramId, isSigner: false), + solana_encoder.AccountMeta.writeable( + pubKey: walletdino.publicKey, isSigner: true), ], namespace: 'global', ), @@ -520,7 +538,7 @@ class _GameWidgetDownState extends State { final message = solana.Message(instructions: instructions); final signature = await client.sendAndConfirmTransaction( message: message, - signers: [mainWalletSolana], + signers: [mainWalletSolana, walletdino], commitment: solana.Commitment.confirmed, ); diff --git a/lib/pages/my-dinogrow/my_dinogrow.dart b/lib/pages/my-dinogrow/my_dinogrow.dart index 7ddc9dd..14fba5b 100644 --- a/lib/pages/my-dinogrow/my_dinogrow.dart +++ b/lib/pages/my-dinogrow/my_dinogrow.dart @@ -1,10 +1,13 @@ 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/solana.dart'; +import 'package:solana_common/utils/convert.dart'; +import 'package:solana_web3/solana_web3.dart' as web3; import 'package:url_launcher/url_launcher.dart'; import '../../ui/widgets/widgets.dart'; @@ -363,6 +366,20 @@ class _MydinogrowScreenState extends State { final mainWalletKey = await storage.read(key: 'mnemonic'); + //Generate internal wallet + String dinoString = dotenv.env['DINO_KEY'].toString(); + dinoString = dinoString.replaceAll(RegExp(r'\[|\]'), ''); + List valueStrings = dinoString.split(','); + List integerList = + (valueStrings).map((value) => int.parse(value)).toList(); + Uint8List secretKey = Uint8List.fromList(integerList); + final keypair = await web3.Keypair.fromSecretKey(secretKey); + //path: "m/44'/501'/0'/0'/0'", + String hdPath = dotenv.env['HD_PATH'].toString(); + final walletdino = await solana.Ed25519HDKeyPair.fromSeedWithHdPath( + seed: keypair.secretKey, hdPath: hdPath); + + final mainWalletSolana = await solana.Ed25519HDKeyPair.fromMnemonic( mainWalletKey!, ); @@ -472,6 +489,8 @@ class _MydinogrowScreenState extends State { pubKey: masterEditionAccountPda, isSigner: false), solana_encoder.AccountMeta.writeable( pubKey: nftMetadataPda, isSigner: false), + solana_encoder.AccountMeta.writeable( + pubKey: walletdino.publicKey, isSigner: true), ], namespace: 'global', ), @@ -479,7 +498,7 @@ class _MydinogrowScreenState extends State { final message = solana.Message(instructions: instructions); final signature = await client.sendAndConfirmTransaction( message: message, - signers: [mainWalletSolana], + signers: [mainWalletSolana, walletdino], commitment: solana.Commitment.confirmed, ); print('Tx successful with hash: $signature'); @@ -489,8 +508,7 @@ class _MydinogrowScreenState extends State { final snackBar = SnackBar( content: Text('Error: $e', style: const TextStyle(color: Colors.white)), backgroundColor: Colors.red, - ); - + ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } finally { if (mounted) { diff --git a/lib/pages/ranking/ranking.dart b/lib/pages/ranking/ranking.dart index 1f4660e..7ccee43 100644 --- a/lib/pages/ranking/ranking.dart +++ b/lib/pages/ranking/ranking.dart @@ -11,6 +11,7 @@ import 'dart:convert'; // 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 '../../anchor_types/get_dino_score.dart' as anchor_types_dino_score; import '../../ui/widgets/widgets.dart'; class RankingScreen extends StatefulWidget { @@ -146,7 +147,7 @@ class _RankingScreenState extends State { // Obtener todas las cuentas del programa final accounts = await client.rpcClient.getProgramAccounts( programId, - encoding: Encoding.jsonParsed, + encoding: Encoding.base64, ); // Recorre las cuentas y muestra los datos @@ -154,6 +155,11 @@ class _RankingScreenState extends State { in (accounts.length <= 15 ? accounts : accounts.sublist(0, 15))) { final bytes = account.account.data as BinaryAccountData; + //Get all data + final decodeAllData = + anchor_types_dino_score.GetScoreArguments.fromBorsh( + bytes.data as Uint8List); + //Get Score final decoderDataScore = anchor_types_dino.DinoScoreArguments.fromBorsh( bytes.data as Uint8List); @@ -164,7 +170,7 @@ class _RankingScreenState extends State { bytes.data as Uint8List); String? localImgUrl = - await storage.read(key: '${decoderDataGame.dinoPubkey}'); + await storage.read(key: '${decodeAllData.dinokey}'); if (localImgUrl == null) { final response = await http.post( @@ -176,7 +182,7 @@ class _RankingScreenState extends State { body: jsonEncode({ "method": "qn_fetchNFTs", "params": { - "wallet": '${decoderDataGame.playerPubkey}', + "wallet": '${decodeAllData.playerkey}', "page": 1, "perPage": 10 } @@ -187,32 +193,32 @@ class _RankingScreenState extends State { if (dataResponse.isNotEmpty) { final arrayAssets = dataResponse['result']['assets']; final indexNft = arrayAssets.indexWhere((item) => - item["tokenAddress"] == '${decoderDataGame.dinoPubkey}'); + item["tokenAddress"] == '${decodeAllData.dinokey}'); String imgurl = indexNft > -1 ? arrayAssets[int.parse('$indexNft')]['imageUrl'] : ''; await storage.write( - key: '${decoderDataGame.dinoPubkey}', value: imgurl); + key: '${decodeAllData.dinokey}', value: imgurl); items2save.add(ItemsProps( imageUrl: imgurl, - dinoPubkey: '${decoderDataGame.dinoPubkey}', - gamescore: '${decoderDataScore.gamescore}', - playerPubkey: '${decoderDataGame.playerPubkey}')); + dinoPubkey: '${decodeAllData.dinokey}', + gamescore: '${decodeAllData.score}', + playerPubkey: '${decodeAllData.playerkey}')); } else { items2save.add(ItemsProps( imageUrl: '', - dinoPubkey: '${decoderDataGame.dinoPubkey}', - gamescore: '${decoderDataScore.gamescore}', - playerPubkey: '${decoderDataGame.playerPubkey}')); + dinoPubkey: '${decodeAllData.dinokey}', + gamescore: '${decodeAllData.score}', + playerPubkey: '${decodeAllData.playerkey}')); } } else { items2save.add(ItemsProps( imageUrl: localImgUrl, - dinoPubkey: '${decoderDataGame.dinoPubkey}', - gamescore: '${decoderDataScore.gamescore}', - playerPubkey: '${decoderDataGame.playerPubkey}')); + dinoPubkey: '${decodeAllData.dinokey}', + gamescore: '${decodeAllData.score}', + playerPubkey: '${decodeAllData.playerkey}')); } }