Skip to content

Commit

Permalink
adding ipfs upload, profile CRUD and others functions
Browse files Browse the repository at this point in the history
  • Loading branch information
sistemaseltigre committed Oct 25, 2023
1 parent 0489ec6 commit eb0d9f8
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 1 deletion.
152 changes: 151 additions & 1 deletion lib/pages/profile.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import 'dart:typed_data';
import 'package:solana/dto.dart';
import 'package:dinogrow/pages/upload_to_ipfs.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:go_router/go_router.dart';
import 'dart:async';
import 'dart:io';

import 'package:solana_common/utils/buffer.dart' as solana_buffer;
import 'package:solana_web3/solana_web3.dart' as web3;
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:solana/solana.dart';
import 'package:solana/solana.dart' as solana;
import '../ui/widgets/widgets.dart';
import 'package:solana/anchor.dart' as solana_anchor;
import 'package:solana/encoder.dart' as solana_encoder;
import '../anchor_types/put_profile_info.dart' as anchor_types_parameters;
import '../anchor_types/get_profile_info.dart' as anchor_types_parameters_get;

class ProfileScreen extends StatefulWidget {
const ProfileScreen({super.key});
Expand Down Expand Up @@ -231,6 +242,99 @@ class _ProfileScreenState extends State<ProfileScreen> {
setState(() {
_loading = true;
});
var methodprogram = "saveprofile";
final findprofileb = await findprofile();
if (findprofileb != null) {
methodprogram = "updateprofile";
print('Profile found');
print(findprofileb.bio);
print(findprofileb.nickname);
print(findprofileb.status);
print(findprofileb.uri);
print(findprofileb.uri);
//https://quicknode.myfilebase.com/ipfs/+uri
}
final String? cid = await uploadToIPFS(imageProfile);

//save profile
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 storage = FlutterSecureStorage();

final mainWalletKey = await storage.read(key: 'mnemonic');

final mainWalletSolana = await solana.Ed25519HDKeyPair.fromMnemonic(
mainWalletKey!,
);

//Generate internal wallet
String dinoString = dotenv.env['DINO_KEY'].toString();
dinoString = dinoString.replaceAll(RegExp(r'\[|\]'), '');
List<String> valueStrings = dinoString.split(',');
List<int> 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);

final programIdPublicKey =
solana.Ed25519HDPublicKey.fromBase58(programId);

final dprofilePda = await solana.Ed25519HDPublicKey
.findProgramAddress(programId: programIdPublicKey, seeds: [
solana_buffer.Buffer.fromString(dotenv.env['PROFILE_SEED'].toString()),
mainWalletSolana.publicKey.bytes,
]);

final instructions = [
await solana_anchor.AnchorInstruction.forMethod(
programId: programIdPublicKey,
method: methodprogram,
arguments: solana_encoder.ByteArray(
anchor_types_parameters.PutProfileArguments(
nickname: nicknameController.text,
bio: bioController.text,
status: statusController.text,
uri: cid as String,
).toBorsh().toList()),
accounts: <solana_encoder.AccountMeta>[
solana_encoder.AccountMeta.writeable(
pubKey: dprofilePda, isSigner: false),
solana_encoder.AccountMeta.writeable(
pubKey: mainWalletSolana.publicKey, isSigner: true),
solana_encoder.AccountMeta.readonly(
pubKey: systemProgramId, isSigner: false),
solana_encoder.AccountMeta.writeable(
pubKey: walletdino.publicKey, isSigner: true),
],
namespace: 'global',
),
];
final message = solana.Message(instructions: instructions);
final signature = await client.sendAndConfirmTransaction(
message: message,
signers: [mainWalletSolana, walletdino],
commitment: solana.Commitment.confirmed,
);

print('Tx successful with hash: $signature');

print(imageProfile.path);
print(nicknameController.text);
print(bioController.text);
print(statusController.text);

// TODO update profile
GoRouter.of(context).pop();
Expand All @@ -250,4 +354,50 @@ class _ProfileScreenState extends State<ProfileScreen> {
});
}
}

findprofile() async {
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 storage = FlutterSecureStorage();

final mainWalletKey = await storage.read(key: 'mnemonic');

final mainWalletSolana = await solana.Ed25519HDKeyPair.fromMnemonic(
mainWalletKey!,
);

final programId = dotenv.env['PROGRAM_ID'].toString();

final programIdPublicKey = solana.Ed25519HDPublicKey.fromBase58(programId);

final dprofilePda = await solana.Ed25519HDPublicKey
.findProgramAddress(programId: programIdPublicKey, seeds: [
solana_buffer.Buffer.fromString(dotenv.env['PROFILE_SEED'].toString()),
mainWalletSolana.publicKey.bytes,
]);

// Obtener todas las cuentas del programa
final accountprofile = await client.rpcClient
.getAccountInfo(
dprofilePda.toBase58(),
encoding: Encoding.base64,
)
.value;

if (accountprofile != null) {
final bytes = accountprofile.data as BinaryAccountData;
final decodeAllData =
anchor_types_parameters_get.GetProfileArguments.fromBorsh(
bytes.data as Uint8List);
return decodeAllData;
} else {
print('No profile found');
return null;
}
}
}
33 changes: 33 additions & 0 deletions lib/pages/upload_to_ipfs.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:http/http.dart' as http;
import 'package:flutter_dotenv/flutter_dotenv.dart';

Future<String?> uploadToIPFS(File file) async {
await dotenv.load(fileName: ".env");
final apiKeyQuicknodeIPFS = dotenv.env['QUICKNODE_API_URL_IPFS'].toString();
const apiUrl = 'https://api.quicknode.com/ipfs/rest/v1/s3/put-object';
String fileName = file.path.split('/').last;
final random = Random();
final hash = List.generate(8, (index) => random.nextInt(10)).join();
final hashedFileName = '${hash}_${fileName}';
try {
print("inside the try catch");
final headers = {
'x-api-key': apiKeyQuicknodeIPFS,
};
final request = http.MultipartRequest('POST', Uri.parse(apiUrl))
..headers.addAll(headers)
..files.add(await http.MultipartFile.fromPath('Body', file.path))
..fields['Key'] = hashedFileName
..fields['ContentType'] = 'text';
final response = await http.Response.fromStream(await request.send());
final jsonResponse = jsonDecode(response.body);
final cid = jsonResponse['pin']['cid'];

return cid;
} catch (e) {
return null;
}
}

0 comments on commit eb0d9f8

Please sign in to comment.