Compare commits
10 Commits
f65b194e2d
...
28a66a3dd8
Author | SHA1 | Date |
---|---|---|
poka | 28a66a3dd8 | |
poka | 5ccacea46d | |
poka | a35d6b5cf2 | |
poka | a13d19177b | |
poka | e3dc579da7 | |
poka | 6be89a3622 | |
poka | b436341808 | |
poka | 7514eb7299 | |
poka | b916c44db4 | |
poka | 1b1c5ab7f0 |
|
@ -5,8 +5,7 @@ services:
|
|||
container_name: duniter-v2s-gecko-tests
|
||||
# image: duniter/duniter-v2s:debug-sha-4d5e08be
|
||||
image: duniter/duniter-v2s:debug-sha-44b09061
|
||||
command: --alice
|
||||
# --sealing=manual
|
||||
command: --alice --sealing=manual
|
||||
ports:
|
||||
- "127.0.0.1:9615:9615"
|
||||
- "127.0.0.1:9933:9933"
|
||||
|
|
|
@ -65,10 +65,11 @@ Future payTest2() async {
|
|||
|
||||
Future certifyTest5() async {
|
||||
// Create identity with Test1 account
|
||||
await pump(number: 8);
|
||||
await tapKey(keyCertify);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 1000);
|
||||
await tester.pump(const Duration(seconds: 2));
|
||||
await pump(number: 3);
|
||||
await waitFor('sending'.tr(),
|
||||
reverse: true, settle: false, timeout: const Duration(seconds: 20));
|
||||
await tapKey(keyCloseTransactionScreen);
|
||||
|
@ -83,7 +84,7 @@ Future certifyTest5() async {
|
|||
await enterText(keyEnterIdentityUsername, test5.name);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 1000);
|
||||
await tester.pump(const Duration(seconds: 2));
|
||||
await pump(number: 3);
|
||||
await waitFor('sending'.tr(),
|
||||
reverse: true, settle: false, timeout: const Duration(seconds: 20));
|
||||
await tapKey(keyCloseTransactionScreen);
|
||||
|
@ -111,7 +112,7 @@ Future certifyTest5() async {
|
|||
await tapKey(keyCertify);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 1000);
|
||||
await tester.pump(const Duration(seconds: 2));
|
||||
await pump(number: 3);
|
||||
await waitFor('sending'.tr(),
|
||||
reverse: true, settle: false, timeout: const Duration(seconds: 20));
|
||||
await tapKey(keyCloseTransactionScreen);
|
||||
|
@ -119,16 +120,16 @@ Future certifyTest5() async {
|
|||
|
||||
// Change default wallet to test3
|
||||
await tapKey(keyPay);
|
||||
await tapKey(keyChangeChest);
|
||||
await tapKey(keyDropdownWallets);
|
||||
await tapKey(keySelectThisWallet(test3.address));
|
||||
await tapKey(keyConfirm);
|
||||
await tapKey(keyPopButton);
|
||||
await sleep();
|
||||
|
||||
// Certify with test3 account
|
||||
await tapKey(keyCertify);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 1000);
|
||||
await tester.pump(const Duration(seconds: 2));
|
||||
await pump(number: 3);
|
||||
await waitFor('sending'.tr(),
|
||||
reverse: true, settle: false, timeout: const Duration(seconds: 20));
|
||||
await tapKey(keyCloseTransactionScreen);
|
||||
|
|
|
@ -44,6 +44,7 @@ void main() async {
|
|||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 1000);
|
||||
await tester.pump(const Duration(seconds: 2));
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
await waitFor('sending'.tr(),
|
||||
reverse: true, settle: false, timeout: const Duration(seconds: 20));
|
||||
await tapKey(keyCloseTransactionScreen, duration: 0);
|
||||
|
@ -52,7 +53,7 @@ void main() async {
|
|||
await waitFor('3', exactMatch: true);
|
||||
await waitFor('memberValidated'.tr());
|
||||
|
||||
await waitFor('99.98', exactMatch: true);
|
||||
await waitFor('110.01', exactMatch: true);
|
||||
}, timeout: testTimeout());
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ Future changeNode() async {
|
|||
}
|
||||
|
||||
Future deleteAllWallets() async {
|
||||
if (await isPresent('Rechercher')) {
|
||||
if (await isPresent('searchWallet'.tr())) {
|
||||
await tapKey(keyDrawerMenu);
|
||||
await tapKey(keyParameters);
|
||||
|
||||
|
@ -65,15 +65,17 @@ Future restoreChest() async {
|
|||
// Enter password
|
||||
await enterText(keyPinForm, 'AAAAA', 0);
|
||||
|
||||
// pump a few frame
|
||||
await pump(duration: const Duration(milliseconds: 500), number: 10);
|
||||
|
||||
// Check if string "Accéder à mon coffre" is present in screen
|
||||
await waitFor('accessMyChest'.tr(), pumpDuration: 30);
|
||||
await waitFor('accessMyChest'.tr(), settle: false);
|
||||
|
||||
// Go to wallets home
|
||||
await tapKey(keyGoWalletsHome, duration: 0);
|
||||
|
||||
// Skip tutorial
|
||||
await sleep(500);
|
||||
await tapKey(keyDragAndDrop).timeout(const Duration(seconds: 3));
|
||||
await skipWalletDragTutorial();
|
||||
|
||||
// Check if string "ĞD" is present in screen
|
||||
await waitFor('ĞD');
|
||||
|
@ -168,5 +170,15 @@ Future firstOpenChest() async {
|
|||
final isCached = await isIconPresent(Icons.check_box);
|
||||
if (!isCached) await tapKey(keyCachePassword, duration: 0);
|
||||
await enterText(keyPinForm, 'AAAAA', 0);
|
||||
await waitFor('100.0', exactMatch: true);
|
||||
await skipWalletDragTutorial();
|
||||
await waitFor(test1.name);
|
||||
}
|
||||
|
||||
Future skipWalletDragTutorial() async {
|
||||
await pump(duration: const Duration(milliseconds: 500), number: 4);
|
||||
await pump(duration: const Duration(seconds: 2));
|
||||
if (await isPresent('explainDraggableWallet'.tr().substring(0, 13),
|
||||
timeout: const Duration(seconds: 5), settle: false)) {
|
||||
await tapKey(keyDragAndDrop, duration: 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,15 @@ Future sleep([int time = 1000]) async {
|
|||
await Future.delayed(Duration(milliseconds: time));
|
||||
}
|
||||
|
||||
Future pump(
|
||||
{Duration duration = const Duration(milliseconds: 300),
|
||||
int number = 1}) async {
|
||||
for (int i = 0; i < number; i++) {
|
||||
log.d("pump $i");
|
||||
await tester.pump(duration = duration);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> clipPaste() async =>
|
||||
(await Clipboard.getData('text/plain'))?.text ?? '';
|
||||
|
||||
|
@ -146,7 +155,8 @@ Future<void> waitFor(String text,
|
|||
}
|
||||
|
||||
if (settle) {
|
||||
await tester.pumpAndSettle(Duration(milliseconds: pumpDuration));
|
||||
await tester.pumpAndSettle(Duration(milliseconds: pumpDuration),
|
||||
EnginePhase.sendSemanticsUpdate, timeout);
|
||||
}
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
} while (reverse ? finder.evaluate().isNotEmpty : finder.evaluate().isEmpty);
|
||||
|
@ -155,9 +165,9 @@ Future<void> waitFor(String text,
|
|||
|
||||
// Test if text is visible on screen, return a boolean
|
||||
Future<bool> isPresent(String text,
|
||||
{Duration timeout = const Duration(seconds: 1)}) async {
|
||||
{Duration timeout = const Duration(seconds: 1), bool settle = true}) async {
|
||||
try {
|
||||
await waitFor(text, timeout: timeout);
|
||||
await waitFor(text, timeout: timeout, settle: settle);
|
||||
humanRead();
|
||||
return true;
|
||||
} catch (exception) {
|
||||
|
@ -278,8 +288,8 @@ Future<WalletData> _addImportAccount(
|
|||
Future bkDeleteAllWallets() async {
|
||||
final myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(homeContext, listen: false);
|
||||
final isWalletsPresents =
|
||||
await isPresent('Scanner un', timeout: const Duration(milliseconds: 300));
|
||||
final isWalletsPresents = await isPresent('scanQRCode'.tr(),
|
||||
timeout: const Duration(milliseconds: 300));
|
||||
if (isWalletsPresents) {
|
||||
await walletBox.clear();
|
||||
await chestBox.clear();
|
||||
|
|
|
@ -61,6 +61,24 @@ class WalletData extends HiveObject {
|
|||
return "$chest:$number:$name:$derivation:$imageDefaultPath";
|
||||
}
|
||||
|
||||
bool hasIdentity() {
|
||||
return identityStatus == IdtyStatus.created ||
|
||||
identityStatus == IdtyStatus.confirmed ||
|
||||
identityStatus == IdtyStatus.validated;
|
||||
}
|
||||
|
||||
bool isMembre() {
|
||||
return identityStatus == IdtyStatus.validated;
|
||||
}
|
||||
|
||||
bool exist() {
|
||||
return balance != 0;
|
||||
}
|
||||
|
||||
bool hasCustomImage() {
|
||||
return imageCustomPath != null;
|
||||
}
|
||||
|
||||
// returns only the id part of the ':'-separated string
|
||||
List<int?> id() {
|
||||
return [chest, number];
|
||||
|
|
|
@ -98,6 +98,8 @@ const keyCesiumPassword = Key('keyCesiumPassword');
|
|||
const keySelectWallet = Key('keySelectWallet');
|
||||
const keyCesiumIdVisible = Key('keyCesiumIdVisible');
|
||||
|
||||
const keyDropdownWallets = Key('keyDropdownKey');
|
||||
|
||||
// Items keys
|
||||
Key keyTransaction(int keyId) => Key('keyTransaction$keyId');
|
||||
Key keyMnemonicWord(String word) => Key('keyMnemonicWord$word');
|
||||
|
|
|
@ -35,14 +35,32 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
List<WalletData> readAllWallets([int? chest]) {
|
||||
Future<List<WalletData>> readAllWallets([int? chest]) async {
|
||||
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
|
||||
chest = chest ?? configBox.get('currentChest') ?? 0;
|
||||
listWallets.clear();
|
||||
walletBox.toMap().forEach((key, value) {
|
||||
if (value.chest == chest) {
|
||||
listWallets.add(value);
|
||||
final wallets = walletBox.toMap().values.toList();
|
||||
Map<String, WalletData> walletsToScan = {};
|
||||
for (var walletFromBox in wallets) {
|
||||
if (walletFromBox.chest == chest) {
|
||||
if (walletFromBox.identityStatus == IdtyStatus.unknown) {
|
||||
walletsToScan.putIfAbsent(
|
||||
walletFromBox.address, (() => walletFromBox));
|
||||
} else {
|
||||
listWallets.add(walletFromBox);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// update all idty status in lists
|
||||
int n = 0;
|
||||
final idtyStatusList = await sub.idtyStatus(walletsToScan.keys.toList());
|
||||
for (final wallet in walletsToScan.values) {
|
||||
wallet.identityStatus = idtyStatusList[n];
|
||||
walletBox.put(wallet.address, wallet);
|
||||
listWallets.add(wallet);
|
||||
n++;
|
||||
}
|
||||
|
||||
return listWallets;
|
||||
}
|
||||
|
@ -118,7 +136,7 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
isNewDerivationLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
final List idList = getNextWalletNumberAndDerivation();
|
||||
final List idList = await getNextWalletNumberAndDerivation();
|
||||
int newWalletNbr = idList[0];
|
||||
int newDerivationNbr = number ?? idList[1];
|
||||
|
||||
|
@ -155,7 +173,7 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
int newWalletNbr;
|
||||
int? chest = getCurrentChest();
|
||||
|
||||
List<WalletData> walletConfig = readAllWallets(chest);
|
||||
List<WalletData> walletConfig = await readAllWallets(chest);
|
||||
walletConfig.sort((p1, p2) {
|
||||
return Comparable.compare(p1.number!, p2.number!);
|
||||
});
|
||||
|
@ -187,22 +205,21 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
List<int> getNextWalletNumberAndDerivation(
|
||||
{int? chestNumber, bool isOneshoot = false}) {
|
||||
Future<List<int>> getNextWalletNumberAndDerivation(
|
||||
{int? chestNumber, bool isOneshoot = false}) async {
|
||||
int newDerivationNbr = 0;
|
||||
int newWalletNbr = 0;
|
||||
|
||||
chestNumber ??= getCurrentChest();
|
||||
|
||||
List<WalletData> walletConfig = readAllWallets(chestNumber);
|
||||
walletConfig.sort((p1, p2) {
|
||||
listWallets.sort((p1, p2) {
|
||||
return Comparable.compare(p1.number!, p2.number!);
|
||||
});
|
||||
|
||||
if (walletConfig.isEmpty) {
|
||||
if (listWallets.isEmpty) {
|
||||
newDerivationNbr = 2;
|
||||
} else {
|
||||
WalletData lastWallet = walletConfig.reduce(
|
||||
WalletData lastWallet = listWallets.reduce(
|
||||
(curr, next) => curr.derivation! > next.derivation! ? curr : next);
|
||||
|
||||
if (lastWallet.derivation == -1) {
|
||||
|
@ -211,7 +228,7 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
newDerivationNbr = lastWallet.derivation! + (isOneshoot ? 1 : 2);
|
||||
}
|
||||
|
||||
newWalletNbr = walletConfig.last.number! + 1;
|
||||
newWalletNbr = listWallets.last.number! + 1;
|
||||
}
|
||||
|
||||
return [newWalletNbr, newDerivationNbr];
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// ignore_for_file: use_build_context_synchronously, body_might_complete_normally_catch_error
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:fast_base58/fast_base58.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -90,10 +92,11 @@ class SubstrateSdk with ChangeNotifier {
|
|||
|
||||
Future _getStorage(String call) async {
|
||||
try {
|
||||
log.d(call);
|
||||
return await sdk.webView!.evalJavascript('api.query.$call');
|
||||
} catch (e) {
|
||||
log.e("_getStorage error: $e");
|
||||
return Future(() {});
|
||||
throw Exception("_getStorage error: $e");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,6 +144,14 @@ class SubstrateSdk with ChangeNotifier {
|
|||
return await _getStorage('identity.identityIndexOf("$address")');
|
||||
}
|
||||
|
||||
Future<List<int?>> _getIdentityIndexOfMulti(List<String> addresses) async {
|
||||
String jsonString = jsonEncode(addresses);
|
||||
return List<int?>.from(
|
||||
await _getStorage('identity.identityIndexOf.multi($jsonString)'));
|
||||
// .map((e) => e as int?)
|
||||
// .toList() as List<int?>;
|
||||
}
|
||||
|
||||
Future<List<int>?> getCertsCounter(String address) async {
|
||||
final idtyIndex = await _getIdentityIndexOf(address);
|
||||
if (idtyIndex == null) {
|
||||
|
@ -169,7 +180,7 @@ class SubstrateSdk with ChangeNotifier {
|
|||
final idtyIndexFrom = await _getIdentityIndexOf(from);
|
||||
final idtyIndexTo = await _getIdentityIndexOf(to);
|
||||
|
||||
if (idtyIndexFrom == 0 || idtyIndexTo == 0) return 0;
|
||||
if (idtyIndexFrom == null || idtyIndexTo == null) return 0;
|
||||
|
||||
final List certData =
|
||||
await _getStorage('cert.certsByReceiver($idtyIndexTo)') ?? [];
|
||||
|
@ -214,18 +225,23 @@ class SubstrateSdk with ChangeNotifier {
|
|||
(await _getStorage('system.account.multi($stringifyAddresses)') as List)
|
||||
.map((dynamic e) => e as Map<String, dynamic>)
|
||||
.toList();
|
||||
log.d('debug multi: $balanceGlobalMulti');
|
||||
|
||||
final List<int?> idtyIndexList = (await _getStorage(
|
||||
'identity.identityIndexOf.multi($stringifyAddresses)') as List)
|
||||
.map((dynamic e) => e as int?)
|
||||
.toList();
|
||||
final List<Map?> idtyDataList = (idtyIndexList.isEmpty
|
||||
|
||||
//FIXME: With local dev duniter node only, need to switch null values by unused init as index to have good idtyDataList...
|
||||
final List<int> idtyIndexListNoNull =
|
||||
idtyIndexList.map((item) => item ?? 99999999).toList();
|
||||
|
||||
final List<Map?> idtyDataList = (idtyIndexListNoNull.isEmpty
|
||||
? []
|
||||
: (await _getStorage('identity.identities.multi($idtyIndexList)'))
|
||||
as List)
|
||||
: (await _getStorage(
|
||||
'identity.identities.multi($idtyIndexListNoNull)')) as List)
|
||||
.map((dynamic e) => e as Map<String, dynamic>?)
|
||||
.toList();
|
||||
|
||||
final List pastReevals =
|
||||
await _getStorage('universalDividend.pastReevals()');
|
||||
|
||||
|
@ -311,33 +327,13 @@ class SubstrateSdk with ChangeNotifier {
|
|||
return totalAmount;
|
||||
}
|
||||
|
||||
Future<bool> isMember(String address) async {
|
||||
final isMember = await idtyStatus(address) == IdtyStatus.validated;
|
||||
final walletData = walletBox.get(address) ?? WalletData(address: address);
|
||||
walletData.identityStatus = IdtyStatus.validated;
|
||||
walletBox.put(address, walletData);
|
||||
// notifyListeners();
|
||||
return isMember;
|
||||
}
|
||||
|
||||
Future<bool> isSmithGet(String address) async {
|
||||
var idtyIndex = await _getIdentityIndexOf(address);
|
||||
|
||||
final Map smithExpireOn =
|
||||
(await _getStorage('smithsMembership.membership($idtyIndex)')) ?? {};
|
||||
|
||||
if (smithExpireOn.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, int>> certState(String from, String to) async {
|
||||
Map<String, int> result = {};
|
||||
final toStatus = await idtyStatus(to);
|
||||
final toStatus = (await idtyStatus([to])).first;
|
||||
|
||||
if (from != to && await isMember(from)) {
|
||||
final myWallets = MyWalletsProvider();
|
||||
|
||||
if (from != to && myWallets.getWalletDataByAddress(from)!.isMembre()) {
|
||||
final removableOn = await getCertValidityPeriod(from, to);
|
||||
final certMeta = await getCertMeta(from);
|
||||
final int nextIssuableOn = certMeta['nextIssuableOn'] ?? 0;
|
||||
|
@ -360,8 +356,6 @@ class SubstrateSdk with ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
// if (toStatus == 'Created') result.putIfAbsent('toStatus', () => 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -379,7 +373,7 @@ class SubstrateSdk with ChangeNotifier {
|
|||
// Provider.of<WalletOptionsProvider>(homeContext, listen: false);
|
||||
|
||||
var idtyIndex = await _getIdentityIndexOf(address);
|
||||
if (idtyIndex == 0) return [];
|
||||
if (idtyIndex == null) return [];
|
||||
|
||||
final Map? idtyData = await _getStorage('identity.identities($idtyIndex)');
|
||||
if (idtyData == null || idtyData['oldOwnerKey'] == null) return [];
|
||||
|
@ -397,43 +391,59 @@ class SubstrateSdk with ChangeNotifier {
|
|||
return startBlockchainTime.add(Duration(seconds: blocNumber * 6));
|
||||
}
|
||||
|
||||
Future<IdtyStatus> idtyStatus(String address) async {
|
||||
Future<List<IdtyStatus>> idtyStatus(List<String> addresses) async {
|
||||
// final walletOptions =
|
||||
// Provider.of<WalletOptionsProvider>(homeContext, listen: false);
|
||||
|
||||
var idtyIndex = await _getIdentityIndexOf(address);
|
||||
log.d(addresses);
|
||||
final idtyIndexes = (await _getIdentityIndexOfMulti(addresses));
|
||||
// .map((dynamic e) => e as String)
|
||||
// .toList();
|
||||
log.d(idtyIndexes);
|
||||
final jsonString = jsonEncode(idtyIndexes);
|
||||
final List idtyStatusList =
|
||||
await _getStorage('identity.identities.multi($jsonString)');
|
||||
|
||||
if (idtyIndex == null) {
|
||||
return IdtyStatus.none;
|
||||
}
|
||||
log.d(idtyStatusList);
|
||||
|
||||
final idtyStatus = await _getStorage('identity.identities($idtyIndex)');
|
||||
List<IdtyStatus> resultStatus = [];
|
||||
|
||||
for (final idtyStatus in idtyStatusList) {
|
||||
if (idtyStatus == null) {
|
||||
resultStatus.add(IdtyStatus.none);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (idtyStatus != null) {
|
||||
switch (idtyStatus['status']) {
|
||||
case 'Created':
|
||||
return IdtyStatus.created;
|
||||
resultStatus.add(IdtyStatus.created);
|
||||
break;
|
||||
|
||||
case 'ConfirmedByOwner':
|
||||
return IdtyStatus.confirmed;
|
||||
resultStatus.add(IdtyStatus.confirmed);
|
||||
break;
|
||||
|
||||
case 'Validated':
|
||||
return IdtyStatus.validated;
|
||||
resultStatus.add(IdtyStatus.validated);
|
||||
break;
|
||||
|
||||
case 'Expired':
|
||||
resultStatus.add(IdtyStatus.expired);
|
||||
break;
|
||||
|
||||
default:
|
||||
return IdtyStatus.unknown;
|
||||
resultStatus.add(IdtyStatus.unknown);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return IdtyStatus.expired;
|
||||
}
|
||||
return resultStatus;
|
||||
}
|
||||
|
||||
Future<bool> isSmith(String address) async {
|
||||
var idtyIndex = await _getIdentityIndexOf(address);
|
||||
if (idtyIndex == 0) return false;
|
||||
if (idtyIndex == -1) return false;
|
||||
|
||||
final isSmith =
|
||||
await _getStorage('smithsMembership.membership($idtyIndex)');
|
||||
final isSmith = await _getStorage('smithMembership.membership($idtyIndex)');
|
||||
return isSmith == null ? false : true;
|
||||
}
|
||||
|
||||
|
@ -753,7 +763,6 @@ class SubstrateSdk with ChangeNotifier {
|
|||
seedText = seed.seed!.split('//')[0];
|
||||
}
|
||||
|
||||
log.d(seedText);
|
||||
return seedText;
|
||||
}
|
||||
|
||||
|
@ -891,11 +900,12 @@ class SubstrateSdk with ChangeNotifier {
|
|||
final fromBalance = fromAddress == ''
|
||||
? {'transferableBalance': 0}
|
||||
: await getBalance(fromAddress);
|
||||
final fromIdtyStatus =
|
||||
fromAddress == '' ? 'noid' : await idtyStatus(fromAddress);
|
||||
|
||||
final statusList = await idtyStatus([fromAddress, toAddress]);
|
||||
final fromIdtyStatus = statusList[0];
|
||||
final fromHasConsumer =
|
||||
fromAddress == '' ? false : await hasAccountConsumers(fromAddress);
|
||||
final toIdtyStatus = await idtyStatus(toAddress);
|
||||
final toIdtyStatus = statusList[1];
|
||||
final isSmithData = await isSmith(fromAddress);
|
||||
|
||||
return [
|
||||
|
@ -970,11 +980,14 @@ class SubstrateSdk with ChangeNotifier {
|
|||
String fromAddress, String destAddress, String password) async {
|
||||
transactionStatus = '';
|
||||
|
||||
final myIdtyStatus = await idtyStatus(fromAddress);
|
||||
final toIdtyStatus = await idtyStatus(destAddress);
|
||||
final statusList = await idtyStatus([fromAddress, destAddress]);
|
||||
final myIdtyStatus = statusList[0];
|
||||
final toIdtyStatus = statusList[1];
|
||||
|
||||
final fromIndex = await _getIdentityIndexOf(fromAddress);
|
||||
final toIndex = await _getIdentityIndexOf(destAddress);
|
||||
final idtyIndexList =
|
||||
await _getIdentityIndexOfMulti([fromAddress, destAddress]);
|
||||
final fromIndex = idtyIndexList[0];
|
||||
final toIndex = idtyIndexList[1];
|
||||
|
||||
if (myIdtyStatus != IdtyStatus.validated) {
|
||||
transactionStatus = 'notMember';
|
||||
|
@ -989,8 +1002,6 @@ class SubstrateSdk with ChangeNotifier {
|
|||
|
||||
final toCerts = await getCertsCounter(destAddress);
|
||||
|
||||
// log.d('debug: ${currencyParameters['minCertForMembership']}');
|
||||
|
||||
log.d(
|
||||
"debug toCert: ${toCerts?[0]} --- ${currencyParameters['minCertForMembership']!} --- $toIdtyStatus");
|
||||
|
||||
|
@ -1071,6 +1082,7 @@ class SubstrateSdk with ChangeNotifier {
|
|||
final messageToSignHex = HEX.encode(messageToSign);
|
||||
final newKeySig =
|
||||
await _signMessage(messageToSign, destAddress, destPassword);
|
||||
final newKeySigType = '{"Sr25519": "$newKeySig"}';
|
||||
|
||||
// messageToSign: [105, 99, 111, 107, 7, 193, 18, 255, 106, 185, 215, 208, 213, 49, 235, 229, 159, 152, 179, 83, 24, 178, 129, 59, 22, 85, 87, 115, 128, 129, 157, 56, 214, 24, 45, 153, 21, 0, 0, 0, 181, 82, 178, 99, 198, 4, 156, 190, 78, 35, 102, 137, 255, 7, 162, 31, 16, 79, 255, 132, 130, 237, 230, 222, 176, 88, 245, 217, 237, 78, 196, 239]
|
||||
|
||||
|
@ -1086,7 +1098,7 @@ oldPubkey: $oldPubkey
|
|||
|
||||
messageToSign: $messageToSign
|
||||
messageToSignHex: $messageToSignHex
|
||||
newKeySig: $newKeySig""");
|
||||
newKeySig: $newKeySigType""");
|
||||
|
||||
if (withBalance) {
|
||||
txInfo = TxInfoData(
|
||||
|
@ -1097,7 +1109,7 @@ newKeySig: $newKeySig""");
|
|||
|
||||
const tx1 = 'api.tx.universalDividend.claimUds()';
|
||||
final tx2 =
|
||||
'api.tx.identity.changeOwnerKey("$destAddress", "$newKeySig")';
|
||||
'api.tx.identity.changeOwnerKey("$destAddress", $newKeySigType)';
|
||||
final tx3 = 'api.tx.balances.transferAll("$destAddress", false)';
|
||||
|
||||
rawParams = fromBalance['unclaimedUds'] == 0
|
||||
|
@ -1110,7 +1122,7 @@ newKeySig: $newKeySig""");
|
|||
sender,
|
||||
);
|
||||
|
||||
txOptions = [destAddress, newKeySig];
|
||||
txOptions = [destAddress, newKeySigType];
|
||||
}
|
||||
|
||||
return await _executeCall(txInfo, txOptions, fromPassword, rawParams);
|
||||
|
@ -1143,7 +1155,7 @@ newKeySig: $newKeySig""");
|
|||
Future migrateCsToV2(String salt, String password, String destAddress,
|
||||
{required destPassword,
|
||||
required Map balance,
|
||||
String idtyStatus = 'noid'}) async {
|
||||
IdtyStatus idtyStatus = IdtyStatus.none}) async {
|
||||
final scrypt = pc.KeyDerivator('scrypt');
|
||||
|
||||
scrypt.init(
|
||||
|
@ -1174,7 +1186,7 @@ newKeySig: $newKeySig""");
|
|||
);
|
||||
|
||||
log.d('g1migration idtyStatus: $idtyStatus');
|
||||
if (idtyStatus != 'noid') {
|
||||
if (idtyStatus != IdtyStatus.none) {
|
||||
await migrateIdentity(
|
||||
fromAddress: keypair.address!,
|
||||
destAddress: destAddress,
|
||||
|
|
|
@ -35,9 +35,7 @@ class _CustomDerivationState extends State<CustomDerivation> {
|
|||
for (var i = 0; i < 51; i += 1) i.toString()
|
||||
];
|
||||
|
||||
final listWallets = myWalletProvider.readAllWallets();
|
||||
|
||||
for (WalletData wallet in listWallets) {
|
||||
for (WalletData wallet in myWalletProvider.listWallets) {
|
||||
derivationList.remove(wallet.derivation.toString());
|
||||
if (wallet.derivation == -1) {
|
||||
derivationList.remove('root');
|
||||
|
|
|
@ -27,11 +27,13 @@ class ImportG1v1 extends StatelessWidget {
|
|||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
Timer? debounce;
|
||||
const int debouneTime = 300;
|
||||
const int debouneTime = 600;
|
||||
WalletData selectedWallet = myWalletProvider.getDefaultWallet();
|
||||
bool canValidate = false;
|
||||
String validationStatus = '';
|
||||
|
||||
log.d(myWalletProvider.listWallets);
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
resetScreen(context);
|
||||
|
@ -58,8 +60,6 @@ class ImportG1v1 extends StatelessWidget {
|
|||
future: sub.getBalanceAndIdtyStatus(
|
||||
sub.g1V1NewAddress, selectedWallet.address),
|
||||
builder: (BuildContext context, AsyncSnapshot<List> status) {
|
||||
// log.d(_certs.data);
|
||||
|
||||
if (status.data == null) {
|
||||
return const Column(children: [
|
||||
SizedBox(height: 80),
|
||||
|
@ -79,13 +79,11 @@ class ImportG1v1 extends StatelessWidget {
|
|||
}
|
||||
|
||||
final Map balance = status.data?[0] ?? {};
|
||||
final String idtyStatus = status.data?[1];
|
||||
final String myIdtyStatus = status.data?[2];
|
||||
final IdtyStatus idtyStatus = status.data?[1];
|
||||
final IdtyStatus myIdtyStatus = status.data?[2];
|
||||
final bool hasConsumer = status.data?[3] ?? false;
|
||||
final bool isSmith = status.data?[4] ?? false;
|
||||
|
||||
// log.d('hasconsumer: $hasConsumer');
|
||||
|
||||
if (balance['transferableBalance'] != 0 && !hasConsumer) {
|
||||
canValidate = true;
|
||||
validationStatus = '';
|
||||
|
@ -96,7 +94,8 @@ class ImportG1v1 extends StatelessWidget {
|
|||
: 'thisAccountIsEmpty'.tr();
|
||||
}
|
||||
|
||||
if (idtyStatus != 'noid' && myIdtyStatus != 'noid') {
|
||||
if (idtyStatus != IdtyStatus.none &&
|
||||
myIdtyStatus != IdtyStatus.none) {
|
||||
canValidate = false;
|
||||
validationStatus =
|
||||
'youCannotMigrateIdentityToExistingIdentity'.tr();
|
||||
|
|
|
@ -43,7 +43,7 @@ class ManageMembership extends StatelessWidget {
|
|||
migrateIdentity(context),
|
||||
const SizedBox(height: 10),
|
||||
FutureBuilder(
|
||||
future: sub.isSmithGet(address),
|
||||
future: sub.isSmith(address),
|
||||
builder: (BuildContext context, AsyncSnapshot<bool> isSmith) {
|
||||
if (isSmith.data ?? false) {
|
||||
return SizedBox(
|
||||
|
|
|
@ -96,8 +96,8 @@ class MigrateIdentityScreen extends StatelessWidget {
|
|||
// log.d('statusData: ${status.data}');
|
||||
|
||||
final Map balance = status.data?[0] ?? {};
|
||||
final String idtyStatus = status.data?[1];
|
||||
final String myIdtyStatus = status.data?[2];
|
||||
final IdtyStatus idtyStatus = status.data?[1];
|
||||
final IdtyStatus myIdtyStatus = status.data?[2];
|
||||
final bool hasConsumer = status.data?[3] ?? false;
|
||||
final bool isSmith = status.data?[4] ?? false;
|
||||
|
||||
|
@ -110,7 +110,8 @@ class MigrateIdentityScreen extends StatelessWidget {
|
|||
!hasConsumer) {
|
||||
canValidate = true;
|
||||
validationStatus = '';
|
||||
} else if (idtyStatus != 'noid' && myIdtyStatus != 'noid') {
|
||||
} else if (idtyStatus != IdtyStatus.none &&
|
||||
myIdtyStatus != IdtyStatus.none) {
|
||||
canValidate = false;
|
||||
validationStatus =
|
||||
'youCannotMigrateIdentityToExistingIdentity'.tr();
|
||||
|
|
|
@ -43,14 +43,12 @@ class WalletOptions extends StatelessWidget {
|
|||
|
||||
final sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
log.d(walletOptions.address.text);
|
||||
walletOptions.address.text = wallet.address;
|
||||
|
||||
final currentChest = myWalletProvider.getCurrentChest();
|
||||
bool isWalletNameIndexed =
|
||||
final isWalletNameIndexed =
|
||||
duniterIndexer.walletNameIndexer[walletOptions.address.text] != null;
|
||||
|
||||
// final currentWallet = _myWalletProvider.getDefaultWallet();
|
||||
// log.d(_walletOptions.getAddress(_currentChest, 3));
|
||||
log.d("Wallet options: $currentChest:${wallet.derivation}");
|
||||
|
||||
return WillPopScope(
|
||||
|
@ -184,7 +182,9 @@ class WalletOptions extends StatelessWidget {
|
|||
address: walletProvider.address.text, size: 24),
|
||||
const SizedBox(width: 30),
|
||||
InkWell(
|
||||
onTap: () => isWalletNameIndexed
|
||||
onTap: () => sub.certsCounterCache[
|
||||
walletProvider.address.text] !=
|
||||
null
|
||||
? {
|
||||
Navigator.push(
|
||||
context,
|
||||
|
@ -193,9 +193,10 @@ class WalletOptions extends StatelessWidget {
|
|||
address:
|
||||
walletProvider.address.text,
|
||||
username: duniterIndexer
|
||||
.walletNameIndexer[
|
||||
walletProvider
|
||||
.address.text]!);
|
||||
.walletNameIndexer[
|
||||
walletProvider
|
||||
.address.text] ??
|
||||
'');
|
||||
}),
|
||||
),
|
||||
}
|
||||
|
@ -262,28 +263,16 @@ class WalletOptions extends StatelessWidget {
|
|||
walletOptions,
|
||||
currentChest),
|
||||
SizedBox(height: 17 * ratio),
|
||||
// walletProvider.isMember(context, _walletOptions.address.text)
|
||||
FutureBuilder(
|
||||
future:
|
||||
sub.isMember(walletOptions.address.text),
|
||||
builder: (BuildContext context,
|
||||
AsyncSnapshot<bool> isMember) {
|
||||
if (isMember.connectionState !=
|
||||
ConnectionState.done ||
|
||||
isMember.hasError) {
|
||||
return const Text('');
|
||||
}
|
||||
return Column(children: [
|
||||
if (!walletProvider.isDefaultWallet &&
|
||||
!isMember.data!)
|
||||
deleteWallet(context, walletProvider,
|
||||
currentChest)
|
||||
else
|
||||
const SizedBox(),
|
||||
if (isMember.data!)
|
||||
const ManageMembershipButton()
|
||||
]);
|
||||
}),
|
||||
Column(children: [
|
||||
if (!walletProvider.isDefaultWallet &&
|
||||
!wallet.isMembre())
|
||||
deleteWallet(
|
||||
context, walletProvider, currentChest)
|
||||
else
|
||||
const SizedBox(),
|
||||
if (wallet.isMembre())
|
||||
const ManageMembershipButton()
|
||||
])
|
||||
]);
|
||||
}),
|
||||
]),
|
||||
|
@ -351,10 +340,11 @@ class WalletOptions extends StatelessWidget {
|
|||
Widget confirmIdentityButton(WalletOptionsProvider walletProvider) {
|
||||
return Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
return FutureBuilder(
|
||||
future: sub.idtyStatus(walletProvider.address.text),
|
||||
initialData: '',
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.data == 'Created') {
|
||||
future: sub.idtyStatus([walletProvider.address.text]),
|
||||
initialData: const [IdtyStatus.unknown],
|
||||
builder:
|
||||
(BuildContext context, AsyncSnapshot<List<IdtyStatus>> snapshot) {
|
||||
if (snapshot.data!.first == IdtyStatus.created) {
|
||||
return Column(children: [
|
||||
SizedBox(
|
||||
width: 320,
|
||||
|
@ -553,7 +543,7 @@ class WalletOptions extends StatelessWidget {
|
|||
// WalletData defaultWallet = _myWalletProvider.getDefaultWallet()!;
|
||||
// defaultWallet = wallet;
|
||||
await sub.setCurrentWallet(wallet);
|
||||
myWalletProvider.readAllWallets(currentChest);
|
||||
await myWalletProvider.readAllWallets(currentChest);
|
||||
myWalletProvider.reload();
|
||||
walletOptions.reload();
|
||||
}
|
||||
|
@ -586,9 +576,9 @@ class WalletOptions extends StatelessWidget {
|
|||
onTap: canDelete
|
||||
? () async {
|
||||
await walletOptions.deleteWallet(context, wallet);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
myWalletProvider.listWallets =
|
||||
myWalletProvider.readAllWallets(currentChest);
|
||||
await myWalletProvider.readAllWallets(currentChest);
|
||||
myWalletProvider.reload();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,15 +10,14 @@ import 'package:gecko/providers/my_wallets.dart';
|
|||
import 'package:gecko/models/wallet_data.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gecko/providers/substrate_sdk.dart';
|
||||
import 'package:gecko/providers/wallet_options.dart';
|
||||
import 'package:gecko/screens/myWallets/chest_options.dart';
|
||||
import 'package:gecko/screens/myWallets/import_g1_v1.dart';
|
||||
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
|
||||
import 'package:gecko/widgets/balance.dart';
|
||||
import 'package:gecko/widgets/bottom_app_bar.dart';
|
||||
import 'package:gecko/widgets/commons/offline_info.dart';
|
||||
import 'package:gecko/widgets/payment_popup.dart';
|
||||
import 'package:gecko/widgets/wallet_tile.dart';
|
||||
import 'package:gecko/widgets/wallet_tile_membre.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
|
||||
|
@ -42,8 +41,6 @@ class _WalletsHomeState extends State<WalletsHome> {
|
|||
|
||||
final currentChestNumber = myWalletProvider.getCurrentChest();
|
||||
final ChestData currentChest = chestBox.get(currentChestNumber)!;
|
||||
myWalletProvider.listWallets =
|
||||
myWalletProvider.readAllWallets(currentChestNumber);
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
|
@ -84,12 +81,29 @@ class _WalletsHomeState extends State<WalletsHome> {
|
|||
actualRoute: 'safeHome',
|
||||
)
|
||||
: dragInfo(context),
|
||||
body: SafeArea(
|
||||
child: Stack(children: [
|
||||
myWalletsTiles(context, currentChestNumber),
|
||||
const OfflineInfo(),
|
||||
]),
|
||||
),
|
||||
body: FutureBuilder(
|
||||
future: myWalletProvider.readAllWallets(currentChestNumber),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState != ConnectionState.done ||
|
||||
snapshot.hasError) {
|
||||
return const Center(
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
width: 50,
|
||||
child: CircularProgressIndicator(
|
||||
color: orangeC,
|
||||
strokeWidth: 3,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return SafeArea(
|
||||
child: Stack(children: [
|
||||
myWalletsTiles(context, currentChestNumber),
|
||||
const OfflineInfo(),
|
||||
]),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -224,8 +238,6 @@ class _WalletsHomeState extends State<WalletsHome> {
|
|||
|
||||
Widget myWalletsTiles(BuildContext context, int currentChestNumber) {
|
||||
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
|
||||
final walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context, listen: false);
|
||||
final bool isWalletsExists = myWalletProvider.checkIfWalletExist();
|
||||
final sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
|
@ -250,6 +262,15 @@ class _WalletsHomeState extends State<WalletsHome> {
|
|||
return Comparable.compare(p1.number!, p2.number!);
|
||||
});
|
||||
|
||||
// Get first wallet with identity
|
||||
final idtyWallet = listWallets.firstWhere(
|
||||
(w) => w.hasIdentity(),
|
||||
orElse: () => WalletData(address: ''),
|
||||
);
|
||||
|
||||
List<WalletData> listWalletsWithoutIdty = listWallets.toList();
|
||||
listWalletsWithoutIdty.removeWhere((w) => w.address == idtyWallet.address);
|
||||
|
||||
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
int nTule;
|
||||
|
@ -303,6 +324,10 @@ class _WalletsHomeState extends State<WalletsHome> {
|
|||
|
||||
return CustomScrollView(slivers: <Widget>[
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 20)),
|
||||
if (idtyWallet.address != '')
|
||||
SliverToBoxAdapter(
|
||||
child: WalletTileMembre(
|
||||
repository: idtyWallet, defaultWallet: defaultWallet)),
|
||||
SliverGrid.count(
|
||||
key: keyListWallets,
|
||||
crossAxisCount: nTule,
|
||||
|
@ -310,7 +335,7 @@ class _WalletsHomeState extends State<WalletsHome> {
|
|||
crossAxisSpacing: 0,
|
||||
mainAxisSpacing: 0,
|
||||
children: <Widget>[
|
||||
for (WalletData repository in listWallets)
|
||||
for (WalletData repository in listWalletsWithoutIdty)
|
||||
LongPressDraggable<String>(
|
||||
delay: const Duration(milliseconds: 200),
|
||||
data: repository.address,
|
||||
|
@ -366,10 +391,7 @@ class _WalletsHomeState extends State<WalletsHome> {
|
|||
List<dynamic> rejected,
|
||||
) {
|
||||
return WalletTile(
|
||||
repository: repository,
|
||||
walletOptions: walletOptions,
|
||||
defaultWallet: defaultWallet,
|
||||
currentChestNumber: currentChestNumber);
|
||||
repository: repository, defaultWallet: defaultWallet);
|
||||
}),
|
||||
),
|
||||
Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
|
@ -443,95 +465,3 @@ class _WalletsHomeState extends State<WalletsHome> {
|
|||
])));
|
||||
}
|
||||
}
|
||||
|
||||
class BalanceBuilder extends StatelessWidget {
|
||||
const BalanceBuilder({
|
||||
Key? key,
|
||||
required this.address,
|
||||
required this.isDefault,
|
||||
}) : super(key: key);
|
||||
|
||||
final String address;
|
||||
final bool isDefault;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: isDefault ? orangeC : yellowC,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 5, right: 5, top: 38, bottom: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: 0.7,
|
||||
child: Balance(
|
||||
address: address,
|
||||
size: 16,
|
||||
color: isDefault ? Colors.white : Colors.black,
|
||||
loadingColor: isDefault ? yellowC : orangeC),
|
||||
)
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CustomClipperOval extends CustomClipper<Rect> {
|
||||
@override
|
||||
Rect getClip(Size size) {
|
||||
return Rect.fromCircle(
|
||||
center: Offset(size.width / 2, size.width / 2),
|
||||
radius: size.width / 2 + 3);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldReclip(CustomClipper<Rect> oldClipper) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class ClipOvalShadow extends StatelessWidget {
|
||||
final Shadow shadow;
|
||||
final CustomClipper<Rect> clipper;
|
||||
final Widget child;
|
||||
|
||||
const ClipOvalShadow({
|
||||
Key? key,
|
||||
required this.shadow,
|
||||
required this.clipper,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomPaint(
|
||||
painter: _ClipOvalShadowPainter(
|
||||
clipper: clipper,
|
||||
shadow: shadow,
|
||||
),
|
||||
child: ClipRect(clipper: clipper, child: child),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ClipOvalShadowPainter extends CustomPainter {
|
||||
final Shadow shadow;
|
||||
final CustomClipper<Rect> clipper;
|
||||
|
||||
_ClipOvalShadowPainter({required this.shadow, required this.clipper});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
var paint = shadow.toPaint();
|
||||
var clipRect = clipper.getClip(size).shift(const Offset(0, 0));
|
||||
canvas.drawOval(clipRect, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,7 +253,7 @@ class OnboardingStepTen extends StatelessWidget {
|
|||
isOwned: true);
|
||||
await walletBox.put(myWallet.address, myWallet);
|
||||
}
|
||||
myWalletProvider.readAllWallets(currentChest);
|
||||
await myWalletProvider.readAllWallets(currentChest);
|
||||
myWalletProvider.reload();
|
||||
|
||||
generateWalletProvider.generatedMnemonic = '';
|
||||
|
|
|
@ -194,7 +194,7 @@ class WalletViewScreen extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
final toStatus = snapshot.data!['toStatus'] ?? 0;
|
||||
final toStatus = snapshot.data!['toStatus'];
|
||||
|
||||
return Visibility(
|
||||
visible: (snapshot.data != {}),
|
||||
|
@ -272,7 +272,7 @@ class WalletViewScreen extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(height: 9),
|
||||
Text(
|
||||
toStatus == 0
|
||||
toStatus == null
|
||||
? "certify".tr()
|
||||
: "createIdentity".tr(),
|
||||
textAlign: TextAlign.center,
|
||||
|
|
|
@ -31,6 +31,7 @@ class HeaderProfile extends StatelessWidget {
|
|||
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
|
||||
final walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context, listen: false);
|
||||
final sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
return Stack(children: <Widget>[
|
||||
Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
|
@ -78,7 +79,7 @@ class HeaderProfile extends StatelessWidget {
|
|||
Balance(address: address, size: 25),
|
||||
const SizedBox(height: 9),
|
||||
InkWell(
|
||||
onTap: () => duniterIndexer.walletNameIndexer[address] != null
|
||||
onTap: () => sub.certsCounterCache[address] != null
|
||||
? {
|
||||
Navigator.push(
|
||||
context,
|
||||
|
@ -86,7 +87,8 @@ class HeaderProfile extends StatelessWidget {
|
|||
return CertificationsScreen(
|
||||
address: address,
|
||||
username: duniterIndexer
|
||||
.walletNameIndexer[address]!);
|
||||
.walletNameIndexer[address] ??
|
||||
'');
|
||||
}),
|
||||
),
|
||||
}
|
||||
|
|
|
@ -24,10 +24,10 @@ class IdentityStatus extends StatelessWidget {
|
|||
|
||||
return Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
return FutureBuilder(
|
||||
future: sub.idtyStatus(address),
|
||||
initialData: walletData.identityStatus,
|
||||
builder: (context, AsyncSnapshot<IdtyStatus> snapshot) {
|
||||
final resStatus = snapshot.data!;
|
||||
future: sub.idtyStatus([address]),
|
||||
initialData: [walletData.identityStatus],
|
||||
builder: (context, AsyncSnapshot<List<IdtyStatus>> snapshot) {
|
||||
final resStatus = snapshot.data!.first;
|
||||
walletData.identityStatus = resStatus;
|
||||
walletBox.put(address, walletData);
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ void paymentPopup(BuildContext context, String toAddress, String username) {
|
|||
var defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
bool canValidate = false;
|
||||
final amountFocus = FocusNode();
|
||||
final dropdownKey = GlobalKey();
|
||||
|
||||
walletViewProvider.payAmount.text = '';
|
||||
|
||||
|
@ -66,10 +65,8 @@ void paymentPopup(BuildContext context, String toAddress, String username) {
|
|||
}
|
||||
}
|
||||
|
||||
myWalletProvider.readAllWallets();
|
||||
myWalletProvider.listWallets
|
||||
.sort((a, b) => a.derivation!.compareTo(b.derivation!));
|
||||
log.d(myWalletProvider.listWallets);
|
||||
myWalletProvider.readAllWallets().then((value) => myWalletProvider.listWallets
|
||||
.sort((a, b) => a.derivation!.compareTo(b.derivation!)));
|
||||
|
||||
showModalBottomSheet<void>(
|
||||
shape: const RoundedRectangleBorder(
|
||||
|
@ -134,6 +131,7 @@ void paymentPopup(BuildContext context, String toAddress, String username) {
|
|||
fontSize: 26, fontWeight: FontWeight.w700),
|
||||
),
|
||||
IconButton(
|
||||
key: keyPopButton,
|
||||
iconSize: 40,
|
||||
icon: const Icon(Icons.cancel_outlined),
|
||||
onPressed: () {
|
||||
|
@ -154,7 +152,7 @@ void paymentPopup(BuildContext context, String toAddress, String username) {
|
|||
return DropdownButton(
|
||||
dropdownColor: const Color(0xffffeed1),
|
||||
elevation: 12,
|
||||
key: dropdownKey,
|
||||
key: keyDropdownWallets,
|
||||
value: defaultWallet,
|
||||
menuMaxHeight: 300,
|
||||
onTap: () {
|
||||
|
@ -199,6 +197,7 @@ void paymentPopup(BuildContext context, String toAddress, String username) {
|
|||
.map((WalletData wallet) {
|
||||
return DropdownMenuItem(
|
||||
value: wallet,
|
||||
key: keySelectThisWallet(wallet.address),
|
||||
child: Container(
|
||||
color: const Color(0xffffeed1),
|
||||
width: 408,
|
||||
|
|
|
@ -100,8 +100,8 @@ class SearchResult extends StatelessWidget {
|
|||
walletsProfilesClass.address = g1Wallet.address;
|
||||
return WalletViewScreen(
|
||||
address: g1Wallet.address,
|
||||
username: g1WalletsBox.get(g1Wallet)!.username ?? '',
|
||||
avatar: g1WalletsBox.get(g1Wallet.address)?.avatar,
|
||||
username: g1Wallet.username ?? '',
|
||||
avatar: g1Wallet.avatar,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -1,28 +1,22 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:gecko/models/wallet_data.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:gecko/providers/wallet_options.dart';
|
||||
import 'package:gecko/screens/myWallets/wallet_options.dart';
|
||||
import 'package:gecko/screens/myWallets/wallets_home.dart';
|
||||
import 'package:gecko/widgets/balance.dart';
|
||||
import 'package:gecko/widgets/commons/smooth_transition.dart';
|
||||
import 'package:gecko/widgets/name_by_address.dart';
|
||||
|
||||
class WalletTile extends StatelessWidget {
|
||||
const WalletTile(
|
||||
{Key? key,
|
||||
required this.repository,
|
||||
required this.walletOptions,
|
||||
required this.defaultWallet,
|
||||
required this.currentChestNumber})
|
||||
: super(key: key);
|
||||
const WalletTile({
|
||||
Key? key,
|
||||
required this.repository,
|
||||
required this.defaultWallet,
|
||||
}) : super(key: key);
|
||||
|
||||
final WalletData repository;
|
||||
final WalletOptionsProvider walletOptions;
|
||||
final WalletData defaultWallet;
|
||||
final int currentChestNumber;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -31,7 +25,6 @@ class WalletTile extends StatelessWidget {
|
|||
child: GestureDetector(
|
||||
key: keyOpenWallet(repository.address),
|
||||
onTap: () {
|
||||
walletOptions.getAddress(currentChestNumber, repository.derivation!);
|
||||
Navigator.push(
|
||||
context,
|
||||
SmoothTransition(
|
||||
|
@ -121,3 +114,95 @@ class WalletTile extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BalanceBuilder extends StatelessWidget {
|
||||
const BalanceBuilder({
|
||||
Key? key,
|
||||
required this.address,
|
||||
required this.isDefault,
|
||||
}) : super(key: key);
|
||||
|
||||
final String address;
|
||||
final bool isDefault;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: isDefault ? orangeC : yellowC,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 5, right: 5, top: 38, bottom: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: 0.7,
|
||||
child: Balance(
|
||||
address: address,
|
||||
size: 16,
|
||||
color: isDefault ? Colors.white : Colors.black,
|
||||
loadingColor: isDefault ? yellowC : orangeC),
|
||||
)
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ClipOvalShadow extends StatelessWidget {
|
||||
final Shadow shadow;
|
||||
final CustomClipper<Rect> clipper;
|
||||
final Widget child;
|
||||
|
||||
const ClipOvalShadow({
|
||||
Key? key,
|
||||
required this.shadow,
|
||||
required this.clipper,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomPaint(
|
||||
painter: _ClipOvalShadowPainter(
|
||||
clipper: clipper,
|
||||
shadow: shadow,
|
||||
),
|
||||
child: ClipRect(clipper: clipper, child: child),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ClipOvalShadowPainter extends CustomPainter {
|
||||
final Shadow shadow;
|
||||
final CustomClipper<Rect> clipper;
|
||||
|
||||
_ClipOvalShadowPainter({required this.shadow, required this.clipper});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
var paint = shadow.toPaint();
|
||||
var clipRect = clipper.getClip(size).shift(const Offset(0, 0));
|
||||
canvas.drawOval(clipRect, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class CustomClipperOval extends CustomClipper<Rect> {
|
||||
@override
|
||||
Rect getClip(Size size) {
|
||||
return Rect.fromCircle(
|
||||
center: Offset(size.width / 2, size.width / 2),
|
||||
radius: size.width / 2 + 3);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldReclip(CustomClipper<Rect> oldClipper) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:gecko/models/wallet_data.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:gecko/screens/myWallets/wallet_options.dart';
|
||||
import 'package:gecko/widgets/balance.dart';
|
||||
import 'package:gecko/widgets/commons/smooth_transition.dart';
|
||||
import 'package:gecko/widgets/name_by_address.dart';
|
||||
|
||||
class WalletTileMembre extends StatelessWidget {
|
||||
const WalletTileMembre({
|
||||
Key? key,
|
||||
required this.repository,
|
||||
required this.defaultWallet,
|
||||
}) : super(key: key);
|
||||
|
||||
final WalletData repository;
|
||||
final WalletData defaultWallet;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 70, vertical: 20),
|
||||
child: GestureDetector(
|
||||
key: keyOpenWallet(repository.address),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
SmoothTransition(
|
||||
page: WalletOptions(
|
||||
wallet: repository,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: SizedBox(
|
||||
key: repository.number == 1 ? keyDragAndDrop : const Key('nothing'),
|
||||
height: 240,
|
||||
child: ClipOvalShadow(
|
||||
shadow: const Shadow(
|
||||
color: Colors.transparent,
|
||||
offset: Offset(0, 0),
|
||||
blurRadius: 5,
|
||||
),
|
||||
clipper: CustomClipperOval(),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
decoration: const BoxDecoration(
|
||||
gradient: RadialGradient(
|
||||
radius: 0.8,
|
||||
colors: [
|
||||
Color.fromARGB(255, 255, 255, 211),
|
||||
yellowC,
|
||||
],
|
||||
),
|
||||
),
|
||||
child: repository.imageCustomPath == null ||
|
||||
repository.imageCustomPath == ''
|
||||
? Image.asset(
|
||||
'assets/avatars/${repository.imageDefaultPath}',
|
||||
alignment: Alignment.bottomCenter,
|
||||
scale: 0.5,
|
||||
)
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.transparent,
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fitHeight,
|
||||
image: FileImage(
|
||||
File(repository.imageCustomPath!),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
Stack(children: <Widget>[
|
||||
BalanceBuilder(
|
||||
address: repository.address,
|
||||
isDefault: repository.address == defaultWallet.address),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(height: 7),
|
||||
Opacity(
|
||||
opacity: 0.7,
|
||||
child: NameByAddress(
|
||||
wallet: repository,
|
||||
size: 20,
|
||||
color:
|
||||
defaultWallet.address == repository.address
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontStyle: FontStyle.normal,
|
||||
))
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BalanceBuilder extends StatelessWidget {
|
||||
const BalanceBuilder({
|
||||
Key? key,
|
||||
required this.address,
|
||||
required this.isDefault,
|
||||
}) : super(key: key);
|
||||
|
||||
final String address;
|
||||
final bool isDefault;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: isDefault ? orangeC : yellowC,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 5, right: 5, top: 45, bottom: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: 0.7,
|
||||
child: Balance(
|
||||
address: address,
|
||||
size: 16,
|
||||
color: isDefault ? Colors.white : Colors.black,
|
||||
loadingColor: isDefault ? yellowC : orangeC),
|
||||
)
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ClipOvalShadow extends StatelessWidget {
|
||||
final Shadow shadow;
|
||||
final CustomClipper<Rect> clipper;
|
||||
final Widget child;
|
||||
|
||||
const ClipOvalShadow({
|
||||
Key? key,
|
||||
required this.shadow,
|
||||
required this.clipper,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomPaint(
|
||||
painter: _ClipOvalShadowPainter(
|
||||
clipper: clipper,
|
||||
shadow: shadow,
|
||||
),
|
||||
child: ClipRect(clipper: clipper, child: child),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ClipOvalShadowPainter extends CustomPainter {
|
||||
final Shadow shadow;
|
||||
final CustomClipper<Rect> clipper;
|
||||
|
||||
_ClipOvalShadowPainter({required this.shadow, required this.clipper});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
var paint = shadow.toPaint();
|
||||
var clipRect = clipper.getClip(size).shift(const Offset(0, 0));
|
||||
canvas.drawOval(clipRect, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class CustomClipperOval extends CustomClipper<Rect> {
|
||||
@override
|
||||
Rect getClip(Size size) {
|
||||
return Rect.fromCircle(
|
||||
center: Offset(size.width / 2, size.width / 2),
|
||||
radius: size.width / 2 + 3);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldReclip(CustomClipper<Rect> oldClipper) {
|
||||
return false;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue