feat: add methode to store cs+ avatar (disabled due to sr25519 cryptotype)
This commit is contained in:
parent
3e18df973b
commit
3458702631
|
@ -2,10 +2,13 @@ import 'dart:convert';
|
|||
import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:gecko/providers/substrate_sdk.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
|
||||
// import 'package:http/http.dart' as http;
|
||||
|
||||
class CesiumPlusProvider with ChangeNotifier {
|
||||
|
@ -13,107 +16,186 @@ class CesiumPlusProvider with ChangeNotifier {
|
|||
|
||||
CancelToken avatarCancelToken = CancelToken();
|
||||
|
||||
Future<List> _buildQuery(String address) async {
|
||||
var queryGetAvatar = json.encode({
|
||||
"query": {
|
||||
"bool": {
|
||||
"should": [
|
||||
{
|
||||
"match": {
|
||||
'_id': {"query": address, "boost": 2}
|
||||
}
|
||||
},
|
||||
{
|
||||
"prefix": {'_id': address}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"highlight": {
|
||||
"fields": {"title": {}, "tags": {}}
|
||||
},
|
||||
"from": 0,
|
||||
"size": 100,
|
||||
"_source": [
|
||||
"title",
|
||||
"avatar",
|
||||
"avatar._content_type",
|
||||
"description",
|
||||
"city",
|
||||
"address",
|
||||
"socials.url",
|
||||
"creationTime",
|
||||
"membersCount",
|
||||
"type"
|
||||
],
|
||||
"indices_boost": {"user": 100, "page": 1, "group": 0.01}
|
||||
final Map<String, String> _headers = {
|
||||
'Content-type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
};
|
||||
|
||||
// List _buildQueryGetAvatar(String pubkeyV1) {
|
||||
// final queryGetAvatar = json.encode({
|
||||
// "query": {
|
||||
// "bool": {
|
||||
// "should": [
|
||||
// {
|
||||
// "match": {
|
||||
// '_id': {"query": pubkeyV1, "boost": 1}
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "prefix": {'_id': pubkeyV1}
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
// "_source": [
|
||||
// "avatar",
|
||||
// "avatar._content_type",
|
||||
// ],
|
||||
// "indices_boost": {"user": 1, "page": 1, "group": 0.01}
|
||||
// });
|
||||
|
||||
// const requestUrl = "/user,page,group/profile,record/_search";
|
||||
// final podRequest = cesiumPod + requestUrl;
|
||||
|
||||
// return [podRequest, queryGetAvatar];
|
||||
// }
|
||||
|
||||
Future<List> _buildQuerySetAvatar(
|
||||
String pubkeyV1, String address, String avatar) async {
|
||||
int timeSent = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
final queryGetAvatar = json.encode({
|
||||
"avatar": {"_content": avatar, "_content_type": "image/png"},
|
||||
"time": timeSent,
|
||||
"issuer": pubkeyV1,
|
||||
"version": 2,
|
||||
"tags": []
|
||||
});
|
||||
|
||||
String requestUrl = "/user,page,group/profile,record/_search";
|
||||
String podRequest = cesiumPod + requestUrl;
|
||||
final requestUrl =
|
||||
"/user/profile?pubkey=$pubkeyV1/_update?pubkey=$pubkeyV1";
|
||||
final podRequest = cesiumPod + requestUrl;
|
||||
|
||||
Map<String, String> headers = {
|
||||
'Content-type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
final signedDocument = await signDoc(queryGetAvatar, address);
|
||||
|
||||
return [podRequest, signedDocument];
|
||||
}
|
||||
|
||||
Future<String> signDoc(String document, String address) async {
|
||||
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
|
||||
final hashDocBytes = utf8.encode(document);
|
||||
final hashDoc = sha256.convert(hashDocBytes);
|
||||
final hashDocHex = hashDoc.toString().toUpperCase();
|
||||
|
||||
// Generate signature of document
|
||||
final signature = await sub.signCsPlusDocument(hashDocHex, address);
|
||||
|
||||
// Build final document
|
||||
final Map<String, dynamic> data = {
|
||||
'hash': hashDocHex,
|
||||
'signature': signature
|
||||
};
|
||||
final signJSON = jsonEncode(data);
|
||||
final Map<String, dynamic> finalJSON = {
|
||||
...jsonDecode(signJSON),
|
||||
...jsonDecode(document)
|
||||
};
|
||||
|
||||
return [podRequest, queryGetAvatar, headers];
|
||||
return jsonEncode(finalJSON);
|
||||
}
|
||||
// Future<String> getName(String address) async {
|
||||
// String? name;
|
||||
|
||||
Future<String> getName(String address) async {
|
||||
String? name;
|
||||
// if (g1WalletsBox.get(address)?.csName != null) {
|
||||
// return g1WalletsBox.get(address)!.csName!;
|
||||
// }
|
||||
|
||||
if (g1WalletsBox.get(address)?.csName != null) {
|
||||
return g1WalletsBox.get(address)!.csName!;
|
||||
}
|
||||
// List queryOptions = await _buildQueryName(address);
|
||||
|
||||
List queryOptions = await _buildQuery(address);
|
||||
// var dio = Dio();
|
||||
// late Response response;
|
||||
// try {
|
||||
// response = await dio.post(
|
||||
// queryOptions[0],
|
||||
// data: queryOptions[1],
|
||||
// options: Options(
|
||||
// headers: queryOptions[2],
|
||||
// sendTimeout: const Duration(seconds: 3),
|
||||
// receiveTimeout: const Duration(seconds: 5),
|
||||
// ),
|
||||
// );
|
||||
// // response = await http.post((Uri.parse(queryOptions[0])),
|
||||
// // body: queryOptions[1], headers: queryOptions[2]);
|
||||
// } catch (e) {
|
||||
// log.e(e);
|
||||
// }
|
||||
|
||||
var dio = Dio();
|
||||
late Response response;
|
||||
try {
|
||||
response = await dio.post(
|
||||
queryOptions[0],
|
||||
data: queryOptions[1],
|
||||
options: Options(
|
||||
headers: queryOptions[2],
|
||||
sendTimeout: const Duration(seconds: 3),
|
||||
receiveTimeout: const Duration(seconds: 5),
|
||||
),
|
||||
);
|
||||
// response = await http.post((Uri.parse(queryOptions[0])),
|
||||
// body: queryOptions[1], headers: queryOptions[2]);
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
}
|
||||
// if (response.data['hits']['hits'].toString() == '[]') {
|
||||
// return '';
|
||||
// }
|
||||
// final bool nameExist =
|
||||
// response.data['hits']['hits'][0]['_source'].containsKey("title");
|
||||
// if (!nameExist) {
|
||||
// return '';
|
||||
// }
|
||||
// name = response.data['hits']['hits'][0]['_source']['title'];
|
||||
|
||||
if (response.data['hits']['hits'].toString() == '[]') {
|
||||
return '';
|
||||
}
|
||||
final bool nameExist =
|
||||
response.data['hits']['hits'][0]['_source'].containsKey("title");
|
||||
if (!nameExist) {
|
||||
return '';
|
||||
}
|
||||
name = response.data['hits']['hits'][0]['_source']['title'];
|
||||
// name ??= '';
|
||||
// g1WalletsBox.get(address)!.csName = name;
|
||||
|
||||
name ??= '';
|
||||
g1WalletsBox.get(address)!.csName = name;
|
||||
|
||||
return name;
|
||||
}
|
||||
// return name;
|
||||
// }
|
||||
|
||||
Future<Image> getAvatar(String address, double size) async {
|
||||
return defaultAvatar(size);
|
||||
// final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
|
||||
// if (await isAvatarExist(address)) {
|
||||
// return await getAvatarLocal(address, size);
|
||||
// }
|
||||
|
||||
// final pubkeyV1 = await sub.addressToPubkeyB58(address);
|
||||
// var dio = Dio();
|
||||
|
||||
// List queryOptions = _buildQueryGetAvatar(pubkeyV1);
|
||||
|
||||
// late Response response;
|
||||
// try {
|
||||
// response = await dio
|
||||
// .post(queryOptions[0],
|
||||
// data: queryOptions[1],
|
||||
// options: Options(
|
||||
// headers: _headers,
|
||||
// sendTimeout: const Duration(seconds: 4),
|
||||
// receiveTimeout: const Duration(seconds: 15),
|
||||
// ),
|
||||
// cancelToken: avatarCancelToken)
|
||||
// .timeout(
|
||||
// const Duration(seconds: 15),
|
||||
// );
|
||||
// } catch (e) {
|
||||
// log.e(e);
|
||||
// }
|
||||
|
||||
// if (response.data['hits']['hits'].toString() == '[]' ||
|
||||
// !response.data['hits']['hits'][0]['_source'].containsKey("avatar")) {
|
||||
// return defaultAvatar(size);
|
||||
// }
|
||||
|
||||
// final avatar =
|
||||
// response.data['hits']['hits'][0]['_source']['avatar']['_content'];
|
||||
|
||||
// final avatarFile = await saveAvatar(address, avatar);
|
||||
|
||||
// final finalAvatar = Image.file(
|
||||
// avatarFile,
|
||||
// height: size,
|
||||
// fit: BoxFit.fitWidth,
|
||||
// );
|
||||
|
||||
// return finalAvatar;
|
||||
}
|
||||
|
||||
Future<bool> setAvatar(String address, String avatarPath) async {
|
||||
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
|
||||
if (await isAvatarExist(address)) {
|
||||
return await getAvatarLocal(address, size);
|
||||
}
|
||||
|
||||
final pubkeyV1 = await sub.addressToPubkeyB58(address);
|
||||
|
||||
var dio = Dio();
|
||||
final Uint8List avatarBytes = await File(avatarPath).readAsBytes();
|
||||
final avatarString = base64Encode(avatarBytes);
|
||||
|
||||
List queryOptions = await _buildQuery(pubkeyV1);
|
||||
List queryOptions =
|
||||
await _buildQuerySetAvatar(pubkeyV1, address, avatarString);
|
||||
log.d(queryOptions[0]);
|
||||
log.d(jsonDecode(queryOptions[1]));
|
||||
|
||||
late Response response;
|
||||
try {
|
||||
|
@ -121,7 +203,7 @@ class CesiumPlusProvider with ChangeNotifier {
|
|||
.post(queryOptions[0],
|
||||
data: queryOptions[1],
|
||||
options: Options(
|
||||
headers: queryOptions[2],
|
||||
headers: _headers,
|
||||
sendTimeout: const Duration(seconds: 4),
|
||||
receiveTimeout: const Duration(seconds: 15),
|
||||
),
|
||||
|
@ -129,29 +211,12 @@ class CesiumPlusProvider with ChangeNotifier {
|
|||
.timeout(
|
||||
const Duration(seconds: 15),
|
||||
);
|
||||
// response = await http.post((Uri.parse(queryOptions[0])),
|
||||
// body: queryOptions[1], headers: queryOptions[2]);
|
||||
log.d(response.data);
|
||||
return response.statusCode == 200;
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.data['hits']['hits'].toString() == '[]' ||
|
||||
!response.data['hits']['hits'][0]['_source'].containsKey("avatar")) {
|
||||
return defaultAvatar(size);
|
||||
}
|
||||
|
||||
final avatar =
|
||||
response.data['hits']['hits'][0]['_source']['avatar']['_content'];
|
||||
|
||||
final avatarFile = await saveAvatar(address, avatar);
|
||||
|
||||
final finalAvatar = Image.file(
|
||||
avatarFile,
|
||||
height: size,
|
||||
fit: BoxFit.fitWidth,
|
||||
);
|
||||
|
||||
return finalAvatar;
|
||||
}
|
||||
|
||||
Future<String> getLocalPath() async {
|
||||
|
@ -188,7 +253,9 @@ class CesiumPlusProvider with ChangeNotifier {
|
|||
Future deleteAvatarFolder() async {
|
||||
final path = await getLocalPath();
|
||||
final avatarFolder = Directory('$path/avatars/');
|
||||
await avatarFolder.delete(recursive: true);
|
||||
if (await avatarFolder.exists()) {
|
||||
await avatarFolder.delete(recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -136,6 +136,42 @@ class SubstrateSdk with ChangeNotifier {
|
|||
return res?.signature ?? '';
|
||||
}
|
||||
|
||||
Future<String> signCsPlusDocument(String document, String address) async {
|
||||
final myWallets =
|
||||
Provider.of<MyWalletsProvider>(homeContext, listen: false);
|
||||
final messageToSign = Uint8List.fromList(document.codeUnits);
|
||||
// final pubkeyV1 = json.decode(document)['issuer'];
|
||||
// final address = await pubkeyV1ToAddress(pubkeyV1);
|
||||
// final walletData = myWallets.getWalletDataByAddress(address);
|
||||
// final derivationPath =
|
||||
// walletData!.derivation == null ? '' : "//${walletData.derivation}";
|
||||
|
||||
// final seed = await getSeed(address, myWallets.pinCode);
|
||||
// final addressEd25519 = await importAccount(
|
||||
// mnemonic: seed,
|
||||
// password: 'AAAAA',
|
||||
// cryptoType: CryptoType.ed25519,
|
||||
// derivePath: derivationPath);
|
||||
|
||||
// final pubkeyEd25519 = await addressToPubkeyB58(addressEd25519);
|
||||
|
||||
final signatureString =
|
||||
await _signMessage(messageToSign, address, myWallets.pinCode);
|
||||
final signatureInt = HEX.decode(signatureString.substring(2));
|
||||
final signature64 = base64Encode(signatureInt);
|
||||
|
||||
// await deleteAccounts([addressEd25519]);
|
||||
|
||||
// log.d("""
|
||||
// $addressEd25519
|
||||
// $pubkeyEd25519
|
||||
// $derivationPath
|
||||
// $signature64
|
||||
// """);
|
||||
|
||||
return signature64;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
////////// 2: GET ONCHAIN STORAGE //////////
|
||||
////////////////////////////////////////////
|
||||
|
@ -453,9 +489,12 @@ class SubstrateSdk with ChangeNotifier {
|
|||
return Base58Encode(await addressToPubkey(address));
|
||||
}
|
||||
|
||||
// Future pubkeyToAddress(String pubkey) async {
|
||||
// await sdk.api.account.encodeAddress([pubkey]);
|
||||
// }
|
||||
Future<String> pubkeyV1ToAddress(String pubkey) async {
|
||||
final pubkeyByte = Base58Decode(pubkey);
|
||||
final String pubkeyHex = '0x${HEX.encode(pubkeyByte)}';
|
||||
final address = await sdk.api.account.encodeAddress([pubkeyHex]);
|
||||
return address!.keys.first;
|
||||
}
|
||||
|
||||
Future initCurrencyParameters() async {
|
||||
try {
|
||||
|
@ -681,7 +720,8 @@ class SubstrateSdk with ChangeNotifier {
|
|||
Future<String> importAccount(
|
||||
{String mnemonic = '',
|
||||
String derivePath = '',
|
||||
required String password}) async {
|
||||
required String password,
|
||||
CryptoType cryptoType = CryptoType.sr25519}) async {
|
||||
const keytype = KeyType.mnemonic;
|
||||
if (mnemonic != '') generatedMnemonic = mnemonic;
|
||||
|
||||
|
@ -695,7 +735,7 @@ class SubstrateSdk with ChangeNotifier {
|
|||
name: derivePath,
|
||||
password: password,
|
||||
derivePath: derivePath,
|
||||
cryptoType: CryptoType.sr25519)
|
||||
cryptoType: cryptoType)
|
||||
.catchError((e) {
|
||||
importIsLoading = false;
|
||||
notifyListeners();
|
||||
|
@ -752,12 +792,6 @@ class SubstrateSdk with ChangeNotifier {
|
|||
return seedText;
|
||||
}
|
||||
|
||||
int getDerivationNumber(String address) {
|
||||
final account = getKeypair(address);
|
||||
final deriveNbr = account.name!.split('//')[1];
|
||||
return int.parse(deriveNbr);
|
||||
}
|
||||
|
||||
Future<KeyPairData?> changePassword(BuildContext context, String address,
|
||||
String passOld, String passNew) async {
|
||||
final account = getKeypair(address);
|
||||
|
|
|
@ -286,6 +286,8 @@ class WalletOptions extends StatelessWidget {
|
|||
if (newPath != '') {
|
||||
wallet.imageCustomPath = newPath;
|
||||
walletBox.put(wallet.key, wallet);
|
||||
// Uncomment to enable Cs+ avatar storage
|
||||
// CesiumPlusProvider().setAvatar(wallet.address, newPath);
|
||||
}
|
||||
walletProvider.reload();
|
||||
},
|
||||
|
|
|
@ -298,7 +298,7 @@ packages:
|
|||
source: hosted
|
||||
version: "0.3.3+7"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
|
|
|
@ -59,6 +59,7 @@ dependencies:
|
|||
tutorial_coach_mark: ^1.2.8
|
||||
confetti: ^0.7.0
|
||||
url_launcher: ^6.1.11
|
||||
crypto: ^3.0.3
|
||||
|
||||
dev_dependencies:
|
||||
# flutter_launcher_icons: ^0.9.2
|
||||
|
|
Loading…
Reference in New Issue