enh: refactor Transacation in progress screen with uuid per transaction

This commit is contained in:
poka 2024-01-03 20:26:11 +01:00
parent 8ca0b00a60
commit 007d62054b
22 changed files with 430 additions and 368 deletions

View File

@ -1,7 +1,6 @@
// 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';
@ -26,6 +25,7 @@ import 'package:provider/provider.dart';
import 'package:truncate/truncate.dart';
import 'package:pointycastle/pointycastle.dart' as pc;
import "package:hex/hex.dart";
import 'package:uuid/uuid.dart' show Uuid;
class SubstrateSdk with ChangeNotifier {
final WalletSDK sdk = WalletSDK();
@ -37,8 +37,8 @@ class SubstrateSdk with ChangeNotifier {
bool importIsLoading = false;
int blocNumber = 0;
bool isLoadingEndpoint = false;
String? transactionStatus;
final int initSs58 = 42;
Map transactionStatus = {};
static const int initSs58 = 42;
Map<String, int> currencyParameters = {};
final csSalt = TextEditingController();
final csPassword = TextEditingController();
@ -52,18 +52,23 @@ class SubstrateSdk with ChangeNotifier {
/////////////////////////////////////
////////// 1: API METHODS ///////////
/////////////////////////////////////3
/////////////////////////////////////
Future<String> _executeCall(TxInfoData txInfo, txOptions, String password,
Future<String> _executeCall(String currentTransactionId, TxInfoData txInfo,
txOptions, String password,
[String? rawParams]) async {
final walletOptions =
Provider.of<WalletOptionsProvider>(homeContext, listen: false);
final walletProfiles =
Provider.of<WalletsProfilesProvider>(homeContext, listen: false);
transactionStatus.putIfAbsent(currentTransactionId, () => 'sending');
notifyListeners();
try {
final hash = await sdk.api.tx.signAndSend(txInfo, txOptions, password,
rawParam: rawParams, onStatusChange: (p0) {
transactionStatus = p0;
transactionStatus.update(currentTransactionId, (_) => p0,
ifAbsent: () => p0);
notifyListeners();
}).timeout(
const Duration(seconds: 18),
@ -71,20 +76,23 @@ class SubstrateSdk with ChangeNotifier {
);
log.d(hash);
if (hash.isEmpty) {
transactionStatus = 'Exception: timeout';
transactionStatus.update(
currentTransactionId, (_) => 'Exception: timeout');
notifyListeners();
return 'Exception: timeout';
} else {
// Success !
transactionStatus = hash.toString();
transactionStatus.update(currentTransactionId, (_) => hash.toString(),
ifAbsent: () => hash.toString());
notifyListeners();
walletOptions.reload();
walletProfiles.reload();
return hash.toString();
}
} catch (e) {
transactionStatus = e.toString();
transactionStatus.update(currentTransactionId, (_) => e.toString(),
ifAbsent: () => e.toString());
notifyListeners();
return e.toString();
}
@ -909,8 +917,6 @@ class SubstrateSdk with ChangeNotifier {
required String destAddress,
required double amount,
required String password}) async {
transactionStatus = 'sending';
final sender = await _setSender(fromAddress);
final globalBalance = await getBalance(fromAddress);
@ -956,13 +962,13 @@ class SubstrateSdk with ChangeNotifier {
rawParams = '[[$tx1, $tx2]]';
}
return await _executeCall(txInfo, txOptions, password, rawParams);
final transactionId = const Uuid().v4();
_executeCall(transactionId, txInfo, txOptions, password, rawParams);
return transactionId;
}
Future<String> certify(
String fromAddress, String destAddress, String password) async {
transactionStatus = 'sending';
final statusList = await idtyStatus([fromAddress, destAddress]);
final myIdtyStatus = statusList[0];
final toIdtyStatus = statusList[1];
@ -973,8 +979,6 @@ class SubstrateSdk with ChangeNotifier {
final toIndex = idtyIndexList[1];
if (myIdtyStatus != IdtyStatus.validated) {
transactionStatus = 'notMember';
notifyListeners();
return 'notMember';
}
@ -1022,18 +1026,17 @@ class SubstrateSdk with ChangeNotifier {
txOptions = [fromIndex, toIndex];
}
} else {
transactionStatus = 'cantBeCert';
notifyListeners();
return 'cantBeCert';
}
log.d('Cert action: ${txInfo.call!}');
return await _executeCall(txInfo, txOptions, password, rawParams);
final transactionId = const Uuid().v4();
_executeCall(transactionId, txInfo, txOptions, password, rawParams);
return transactionId;
}
Future<String> confirmIdentity(
String fromAddress, String name, String password) async {
transactionStatus = 'sending';
final sender = await _setSender(fromAddress);
final txInfo = TxInfoData(
@ -1043,7 +1046,11 @@ class SubstrateSdk with ChangeNotifier {
);
final txOptions = [name];
return await _executeCall(txInfo, txOptions, password);
final transactionId = const Uuid().v4();
_executeCall(transactionId, txInfo, txOptions, password);
return transactionId;
}
Future<String> migrateIdentity(
@ -1053,7 +1060,6 @@ class SubstrateSdk with ChangeNotifier {
required String destPassword,
required Map fromBalance,
bool withBalance = false}) async {
transactionStatus = 'sending';
final sender = await _setSender(fromAddress);
TxInfoData txInfo;
@ -1111,7 +1117,9 @@ newKeySig: $newKeySigType""");
txOptions = [destAddress, newKeySigType];
}
return await _executeCall(txInfo, txOptions, fromPassword, rawParams);
final transactionId = const Uuid().v4();
_executeCall(transactionId, txInfo, txOptions, fromPassword, rawParams);
return transactionId;
}
Future revokeIdentity(String address, String password) async {
@ -1135,10 +1143,12 @@ newKeySig: $newKeySigType""");
);
final txOptions = [idtyIndex, address, revocationSigTyped];
return await _executeCall(txInfo, txOptions, password);
final transactionId = const Uuid().v4();
_executeCall(transactionId, txInfo, txOptions, password);
return transactionId;
}
Future migrateCsToV2(String salt, String password, String destAddress,
Future<String> migrateCsToV2(String salt, String password, String destAddress,
{required destPassword,
required Map balance,
IdtyStatus idtyStatus = IdtyStatus.none}) async {
@ -1171,8 +1181,10 @@ newKeySig: $newKeySigType""");
password: password,
);
late String transactionId;
if (idtyStatus != IdtyStatus.none) {
await migrateIdentity(
transactionId = await migrateIdentity(
fromAddress: keypair.address!,
destAddress: destAddress,
fromPassword: 'password',
@ -1180,14 +1192,17 @@ newKeySig: $newKeySigType""");
withBalance: true,
fromBalance: balance);
} else if (balance['transferableBalance'] != 0) {
await pay(
transactionId = await pay(
fromAddress: keypair.address!,
destAddress: destAddress,
amount: -1,
password: 'password');
} else {
transactionId = '';
}
await sdk.api.keyring.deleteAccount(keyring, keypair);
return transactionId;
}
Future spawnBlock([int number = 1, int until = 0]) async {
@ -1204,6 +1219,10 @@ newKeySig: $newKeySigType""");
void reload() {
notifyListeners();
}
void resetTransactionStatus() {
transactionStatus.clear();
}
}
////////////////////////////////////////////

View File

@ -217,14 +217,17 @@ class WalletOptionsProvider with ChangeNotifier {
final wallet = myWalletProvider
.getWalletDataByAddress(address.text);
await sub.setCurrentWallet(wallet!);
sub.confirmIdentity(walletOptions.address.text,
idtyName.text, myWalletProvider.pinCode);
final transactionId = await sub.confirmIdentity(
walletOptions.address.text,
idtyName.text,
myWalletProvider.pinCode);
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transactionId: transactionId,
transType: 'comfirmIdty',
fromAddress:
getShortPubkey(wallet.address),

View File

@ -39,8 +39,9 @@ class DebugScreen extends StatelessWidget {
width: 250,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
foregroundColor: Colors.white,
elevation: 4,
backgroundColor: orangeC,
),
onPressed: () async => await sub.spawnBlock(),
child: const Text(

View File

@ -322,8 +322,9 @@ Widget welcomeHome(context) {
child: ElevatedButton(
key: keyOnboardingNewChest,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
foregroundColor: Colors.white,
elevation: 4,
backgroundColor: orangeC,
),
onPressed: () {
Navigator.push(

View File

@ -93,8 +93,9 @@ class _ChangePinScreenState extends State<ChangePinScreen> {
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.black, elevation: 12,
backgroundColor: Colors.green[400], // foreground
foregroundColor: Colors.black,
elevation: 12,
backgroundColor: Colors.green[400],
),
onPressed: () async {
WalletData defaultWallet =

View File

@ -106,7 +106,7 @@ class _ChooseChestState extends State<ChooseChest> {
child: ElevatedButton(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.black,
backgroundColor: orangeC, // foreground
backgroundColor: orangeC,
),
onPressed: () async {
await configBox.put('currentChest', currentChest);

View File

@ -22,6 +22,7 @@ import 'package:provider/provider.dart';
class ImportG1v1 extends StatelessWidget {
const ImportG1v1({Key? key}) : super(key: key);
static const int debouneTime = 600;
@override
Widget build(BuildContext context) {
@ -29,7 +30,6 @@ class ImportG1v1 extends StatelessWidget {
Provider.of<MyWalletsProvider>(context, listen: false);
Timer? debounce;
const int debouneTime = 600;
WalletData selectedWallet = myWalletProvider.getDefaultWallet();
bool canValidate = false;
String validationStatus = '';
@ -297,8 +297,10 @@ class ImportG1v1 extends StatelessWidget {
);
}
sub.migrateCsToV2(sub.csSalt.text,
sub.csPassword.text, selectedWallet.address,
final transactionId = await sub.migrateCsToV2(
sub.csSalt.text,
sub.csPassword.text,
selectedWallet.address,
destPassword:
pin ?? myWalletProvider.pinCode,
balance: balance,
@ -308,6 +310,7 @@ class ImportG1v1 extends StatelessWidget {
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transactionId: transactionId,
transType: 'identityMigration',
fromAddress:
getShortPubkey(sub.g1V1NewAddress),

View File

@ -109,38 +109,41 @@ class ManageMembership extends StatelessWidget {
'Êtes-vous certains de vouloir révoquer définitivement cette identité ?') ??
false;
if (answer) {
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
if (!answer) return;
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(wallet: defaultWallet);
},
),
);
}
if (pin != null || myWalletProvider.pinCode != '') {
sub.revokeIdentity(address, myWalletProvider.pinCode);
}
Navigator.pop(context);
Navigator.push(
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transType: 'revokeIdty',
fromAddress: getShortPubkey(address),
toAddress: getShortPubkey(address));
}),
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(wallet: defaultWallet);
},
),
);
}
if (pin == null || myWalletProvider.pinCode == '') return;
final transactionId =
await sub.revokeIdentity(address, myWalletProvider.pinCode);
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transactionId: transactionId,
transType: 'revokeIdty',
fromAddress: getShortPubkey(address),
toAddress: getShortPubkey(address));
}),
);
},
child: ScaledSizedBox(
height: 55,

View File

@ -190,28 +190,25 @@ class MigrateIdentityScreen extends StatelessWidget {
);
}
if (myWalletProvider.pinCode != '') {
sub.migrateIdentity(
fromAddress: fromAddress,
destAddress: selectedWallet.address,
fromPassword:
pin ?? myWalletProvider.pinCode,
destPassword:
pin ?? myWalletProvider.pinCode,
withBalance: true,
fromBalance: balance);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transType: 'identityMigration',
fromAddress:
getShortPubkey(fromAddress),
toAddress: getShortPubkey(
selectedWallet.address));
}),
);
}
if (myWalletProvider.pinCode == '') return;
final transactionId = await sub.migrateIdentity(
fromAddress: fromAddress,
destAddress: selectedWallet.address,
fromPassword: pin ?? myWalletProvider.pinCode,
destPassword: pin ?? myWalletProvider.pinCode,
withBalance: true,
fromBalance: balance);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transactionId: transactionId,
transType: 'identityMigration',
fromAddress: getShortPubkey(fromAddress),
toAddress: getShortPubkey(
selectedWallet.address));
}),
);
}
: null,
child: Text(

View File

@ -84,8 +84,9 @@ class RestoreChest extends StatelessWidget {
child: ElevatedButton(
key: keyGoNext,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
foregroundColor: Colors.white,
elevation: 4,
backgroundColor: orangeC,
),
onPressed: () async {
if (await sub
@ -125,8 +126,9 @@ class RestoreChest extends StatelessWidget {
child: ElevatedButton(
key: keyPastMnemonic,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.black, elevation: 4,
backgroundColor: yellowC, // foreground
foregroundColor: Colors.black,
elevation: 4,
backgroundColor: yellowC,
),
onPressed: () {
genW.pasteMnemonic(context);

View File

@ -239,9 +239,7 @@ class WalletOptions extends StatelessWidget {
if (!walletProvider.isDefaultWallet &&
!wallet.isMembre())
deleteWallet(
context, walletProvider, currentChest)
else
ScaledSizedBox(),
context, walletProvider, currentChest),
if (wallet.isMembre())
const ManageMembershipButton()
])
@ -327,16 +325,10 @@ class WalletOptions extends StatelessWidget {
key: keyConfirmIdentity,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
backgroundColor: orangeC,
),
onPressed: () async {
onPressed: () {
walletProvider.confirmIdentityPopup(context);
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) {
// return const SearchResultScreen();
// }),
// );
},
child: Text(
'confirmMyIdentity'.tr(),

View File

@ -221,8 +221,9 @@ Widget nextButton(
child: ElevatedButton(
key: keyGoNext,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
foregroundColor: Colors.white,
elevation: 4,
backgroundColor: orangeC,
),
onPressed: () {
generateWalletProvider.nbrWord = generateWalletProvider.getRandomInt();

View File

@ -148,8 +148,9 @@ Widget nextButton(BuildContext context, String text, nextScreen, bool isFast) {
child: ElevatedButton(
key: keyGoNext,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
foregroundColor: Colors.white,
elevation: 4,
backgroundColor: orangeC,
),
onPressed: () {
Navigator.push(

View File

@ -81,8 +81,7 @@ class OnboardingStepNine extends StatelessWidget {
style: ElevatedButton.styleFrom(
foregroundColor: Colors.black,
elevation: 4,
backgroundColor:
const Color(0xffFFD58D), // foreground
backgroundColor: const Color(0xffFFD58D),
),
onPressed: () {
generateWalletProvider.changePinCode(

View File

@ -141,8 +141,9 @@ class _SearchScreenState extends State<SearchScreen> {
child: ElevatedButton(
key: keyConfirmSearch,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
foregroundColor: Colors.white,
elevation: 4,
backgroundColor: orangeC,
),
onPressed: canValidate
? () {

View File

@ -18,11 +18,11 @@ class SearchResultScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final searchProvider = Provider.of<SearchProvider>(context, listen: false);
WalletsProfilesProvider walletsProfilesClass =
final walletsProfilesClass =
Provider.of<WalletsProfilesProvider>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
double avatarSize = scaleSize(37);
final avatarSize = scaleSize(37);
return Scaffold(
backgroundColor: backgroundColor,

View File

@ -1,95 +1,87 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/scale_functions.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class TransactionInProgress extends StatelessWidget {
const TransactionInProgress(
{Key? key,
this.transType = 'pay',
this.fromAddress,
this.toAddress,
this.toUsername})
: super(key: key);
final String transactionId;
final String transType;
final String? fromAddress;
final String? toAddress;
final String? toUsername;
final String? fromAddress, toAddress, toUsername;
const TransactionInProgress({
Key? key,
required this.transactionId,
this.transType = 'pay',
this.fromAddress,
this.toAddress,
this.toUsername,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final sub = Provider.of<SubstrateSdk>(context, listen: true);
final walletProfiles =
Provider.of<WalletsProfilesProvider>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
var txStatus = TransactionStatus.none;
final result = sub.transactionStatus;
final from = fromAddress ??
g1WalletsBox
.get(myWalletProvider.getDefaultWallet().address)
?.username ??
myWalletProvider.getDefaultWallet().name!;
final transactionDetails = TransactionDetails(
transactionId: transactionId,
fromAddress: fromAddress,
toAddress: toAddress,
toUsername: toUsername,
sub: sub,
transType: transType,
);
String to = toAddress ?? walletProfiles.address;
to =
myWalletProvider.getWalletDataByAddress(to)?.name ?? getShortPubkey(to);
final amount = walletProfiles.payAmount.text;
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
final Map<String, String> actionMap = {
'pay': 'transaction'.tr(),
'cert': 'certification'.tr(),
'comfirmIdty': 'identityConfirm'.tr(),
'revokeIdty': 'revokeAdhesion'.tr(),
'identityMigration': 'identityMigration'.tr(),
};
String resultText = '';
final Map<String, String> resultMap = {
'sending': 'sending'.tr(),
'Ready': 'propagating'.tr(),
'Broadcast': 'validating'.tr(),
'cert.NotRespectCertPeriod': '24hbetweenCerts'.tr(),
'identity.CreatorNotAllowedToCreateIdty': '24hbetweenCerts'.tr(),
'cert.CannotCertifySelf': 'canNotCertifySelf'.tr(),
'identity.IdtyNameAlreadyExist': 'nameAlreadyExist'.tr(),
'balances.KeepAlive': '2GDtoKeepAlive'.tr(),
'1010: Invalid Transaction: Inability to pay some fees , e.g. account balance too low':
'youHaveToFeedThisAccountBeforeUsing'.tr(),
'Token.FundsUnavailable': 'fundsUnavailable'.tr(),
'Exception: timeout': 'execTimeoutOver'.tr(),
};
if (result == null) {
txStatus = TransactionStatus.none;
} else if (result.contains('blockHash: ')) {
txStatus = TransactionStatus.success;
resultText = 'extrinsicValidated'
.tr(args: [actionMap[transType] ?? 'strangeTransaction'.tr()]);
} else if (result.contains('Exception: ')) {
txStatus = TransactionStatus.failed;
resultText = "${"anErrorOccurred".tr()}:\n";
final String exception = result.split('Exception: ')[1];
resultText = resultMap[exception] ?? "$resultText\n$exception";
log.e('Error: $exception');
} else {
txStatus = TransactionStatus.loading;
resultText = resultMap[result] ?? 'unknown status...';
Widget getTransactionStatusIcon(TransactionDetails details) {
switch (details.txStatus) {
case TransactionStatus.loading:
return ScaledSizedBox(
height: 17,
width: 17,
child: const CircularProgressIndicator(
color: orangeC,
strokeWidth: 2,
),
);
case TransactionStatus.success:
return Icon(
Icons.done_all,
size: scaleSize(32),
color: Colors.greenAccent,
);
case TransactionStatus.failed:
return Icon(
Icons.close,
size: scaleSize(32),
color: Colors.redAccent,
);
case TransactionStatus.none:
default:
return const SizedBox.shrink();
}
}
log.d("$transType :: ${actionMap[transType]} :: $result");
Widget buildTransactionStatus(TransactionDetails details) {
return Column(
children: [
getTransactionStatusIcon(details),
ScaledSizedBox(height: 7),
if (details.txStatus != TransactionStatus.none)
Text(
transactionDetails.resultText,
textAlign: TextAlign.center,
style: scaledTextStyle(fontSize: 17),
)
],
);
}
return PopScope(
onPopInvoked: (_) {
sub.transactionStatus = null;
sub.resetTransactionStatus();
},
child: Scaffold(
backgroundColor: backgroundColor,
@ -102,138 +94,105 @@ class TransactionInProgress extends StatelessWidget {
children: <Widget>[
Text(
'extrinsicInProgress'.tr(args: [
actionMap[transType] ?? 'strangeTransaction'.tr()
transactionDetails.actionMap[transType] ??
'strangeTransaction'.tr()
]),
style: scaledTextStyle(fontSize: 20),
)
])),
body: SafeArea(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Column(children: <Widget>[
Container(
width: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
yellowC,
backgroundColor,
],
)),
child: Column(children: <Widget>[
ScaledSizedBox(height: 10),
if (transType == 'pay')
Text(
isUdUnit
? 'ud'.tr(args: ['$amount '])
: '$amount $currencyName',
textAlign: TextAlign.center,
style: scaledTextStyle(
fontSize: 17, fontWeight: FontWeight.w500),
),
if (transType == 'pay') ScaledSizedBox(height: 10),
alignment: FractionalOffset.bottomCenter,
child: Column(children: <Widget>[
Container(
width: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
yellowC,
backgroundColor,
],
)),
child: Column(children: <Widget>[
ScaledSizedBox(height: 10),
if (transType == 'pay')
Text(
'fromMinus'.tr(),
textAlign: TextAlign.center,
style: scaledTextStyle(fontSize: 16),
),
Text(
from,
transactionDetails.isUdUnit
? 'ud'.tr(args: ['${transactionDetails.amount} '])
: '${transactionDetails.amount} $currencyName',
textAlign: TextAlign.center,
style: scaledTextStyle(
fontSize: 17, fontWeight: FontWeight.w500),
),
Visibility(
visible: from != to,
child: Column(
children: [
ScaledSizedBox(height: 10),
Text(
'toMinus'.tr(),
textAlign: TextAlign.center,
style: scaledTextStyle(fontSize: 16),
),
Text(
toUsername ?? to,
textAlign: TextAlign.center,
style: scaledTextStyle(
fontSize: 17, fontWeight: FontWeight.w500),
),
],
),
),
ScaledSizedBox(height: 20),
]),
),
const Spacer(),
Column(children: [
Visibility(
visible: txStatus == TransactionStatus.loading,
child: ScaledSizedBox(
height: 17,
width: 17,
child: const CircularProgressIndicator(
color: orangeC,
strokeWidth: 2,
),
),
if (transType == 'pay') ScaledSizedBox(height: 10),
Text(
'fromMinus'.tr(),
textAlign: TextAlign.center,
style: scaledTextStyle(fontSize: 16),
),
Text(
transactionDetails.fromAddress!,
textAlign: TextAlign.center,
style: scaledTextStyle(
fontSize: 17, fontWeight: FontWeight.w500),
),
Visibility(
visible: txStatus == TransactionStatus.success,
child: Icon(
Icons.done_all,
size: scaleSize(32),
color: Colors.greenAccent,
),
),
Visibility(
visible: txStatus == TransactionStatus.failed,
child: Icon(
Icons.close,
size: scaleSize(32),
color: Colors.redAccent,
),
),
ScaledSizedBox(height: 10),
Visibility(
visible: txStatus != TransactionStatus.none,
child: Text(
resultText,
textAlign: TextAlign.center,
style: scaledTextStyle(fontSize: 17),
),
),
]),
const Spacer(),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: ScaledSizedBox(
width: 300,
height: 55,
child: ElevatedButton(
key: keyCloseTransactionScreen,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
visible: transactionDetails.fromAddress !=
transactionDetails.toAddress,
child: Column(
children: [
ScaledSizedBox(height: 10),
Text(
'toMinus'.tr(),
textAlign: TextAlign.center,
style: scaledTextStyle(fontSize: 16),
),
onPressed: () {
sub.transactionStatus = null;
Navigator.pop(context);
},
child: Text(
'close'.tr(),
Text(
transactionDetails.toUsername!,
textAlign: TextAlign.center,
style: scaledTextStyle(
fontSize: 20, fontWeight: FontWeight.w600),
fontSize: 17, fontWeight: FontWeight.w500),
),
],
),
),
ScaledSizedBox(height: 20),
]),
),
const Spacer(),
buildTransactionStatus(transactionDetails),
const Spacer(),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: ScaledSizedBox(
width: 300,
height: 55,
child: ElevatedButton(
key: keyCloseTransactionScreen,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
elevation: 4,
backgroundColor: orangeC,
),
onPressed: () {
sub.resetTransactionStatus();
Navigator.pop(context);
},
child: Text(
'close'.tr(),
style: scaledTextStyle(
fontSize: 20, fontWeight: FontWeight.w600),
),
),
),
),
ScaledSizedBox(height: 80)
])),
),
ScaledSizedBox(height: 80)
]),
),
),
),
);
@ -241,3 +200,82 @@ class TransactionInProgress extends StatelessWidget {
}
enum TransactionStatus { loading, failed, success, none }
class TransactionDetails {
String? fromAddress, toAddress, toUsername, amount;
bool isUdUnit = false;
String resultText = '';
TransactionStatus txStatus = TransactionStatus.none;
Map<String, String> actionMap = {
'pay': 'transaction'.tr(),
'cert': 'certification'.tr(),
'comfirmIdty': 'identityConfirm'.tr(),
'revokeIdty': 'revokeAdhesion'.tr(),
'identityMigration': 'identityMigration'.tr(),
};
Map<String, String> resultMap = {
'sending': 'sending'.tr(),
'Ready': 'propagating'.tr(),
'Broadcast': 'validating'.tr(),
'cert.NotRespectCertPeriod': '24hbetweenCerts'.tr(),
'identity.CreatorNotAllowedToCreateIdty': '24hbetweenCerts'.tr(),
'cert.CannotCertifySelf': 'canNotCertifySelf'.tr(),
'identity.IdtyNameAlreadyExist': 'nameAlreadyExist'.tr(),
'balances.KeepAlive': '2GDtoKeepAlive'.tr(),
'1010: Invalid Transaction: Inability to pay some fees , e.g. account balance too low':
'youHaveToFeedThisAccountBeforeUsing'.tr(),
'Token.FundsUnavailable': 'fundsUnavailable'.tr(),
'Exception: timeout': 'execTimeoutOver'.tr(),
};
TransactionDetails({
required transactionId,
required this.fromAddress,
required this.toAddress,
required this.toUsername,
required SubstrateSdk sub,
required String transType,
}) {
final walletProfiles =
Provider.of<WalletsProfilesProvider>(homeContext, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(homeContext, listen: false);
String defaultWalletAddress = myWalletProvider.getDefaultWallet().address;
String defaultWalletName = myWalletProvider.getDefaultWallet().name!;
String? walletDataName =
myWalletProvider.getWalletDataByAddress(toAddress ?? '')?.name;
fromAddress = fromAddress ??
g1WalletsBox.get(defaultWalletAddress)?.username ??
defaultWalletName;
toAddress = toAddress ?? walletProfiles.address;
toUsername = toUsername ?? walletDataName ?? getShortPubkey(toAddress!);
amount = walletProfiles.payAmount.text;
isUdUnit = configBox.get('isUdUnit') ?? false;
if (sub.transactionStatus.containsKey(transactionId)) {
calculateTransactionStatus(
sub.transactionStatus[transactionId], transType);
}
}
void calculateTransactionStatus(String? result, String transType) {
if (result == null) {
txStatus = TransactionStatus.none;
} else if (result.contains('blockHash: ')) {
txStatus = TransactionStatus.success;
resultText = 'extrinsicValidated'
.tr(args: [actionMap[transType] ?? 'strangeTransaction']);
} else if (result.contains('Exception: ')) {
txStatus = TransactionStatus.failed;
String exception = result.split('Exception: ')[1];
resultText = resultMap[exception] ?? exception;
} else {
txStatus = TransactionStatus.loading;
resultText = resultMap[result] ?? 'Unknown status: $result';
}
}
}

View File

@ -151,7 +151,7 @@ class WalletViewScreen extends StatelessWidget {
return FutureBuilder(
future: sub.certState(defaultWallet.address, address),
builder: (context, AsyncSnapshot<Map<String, int>> snapshot) {
if (snapshot.data == null) return ScaledSizedBox();
if (snapshot.data == null) return const SizedBox.shrink();
String duration = '';
if (snapshot.data!['certDelay'] != null ||
@ -209,55 +209,53 @@ class WalletViewScreen extends StatelessWidget {
'assets/gecko_certify.png')),
),
onTap: () async {
final bool? result =
final result =
await confirmPopupCertification(
context,
'areYouSureYouWantToCertify1'
.tr(),
duniterIndexer
.walletNameIndexer[
address] ??
"noIdentity".tr(),
'areYouSureYouWantToCertify2'
.tr(),
getShortPubkey(address));
context,
'areYouSureYouWantToCertify1'
.tr(),
duniterIndexer
.walletNameIndexer[
address] ??
"noIdentity".tr(),
'areYouSureYouWantToCertify2'
.tr(),
getShortPubkey(address)) ??
false;
if (result ?? false) {
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(
wallet: defaultWallet);
},
),
);
}
if (pin != null ||
myWalletProvider.pinCode != '') {
WalletsProfilesProvider
walletViewProvider = Provider
.of<WalletsProfilesProvider>(
context,
listen: false);
final acc = sub.getCurrentWallet();
sub.certify(
acc.address!,
walletViewProvider.address,
pin ??
myWalletProvider.pinCode);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return const TransactionInProgress(
transType: 'cert');
}),
);
}
if (!result) return;
if (myWalletProvider.pinCode == '') {
await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(
wallet: defaultWallet);
},
),
);
}
if (myWalletProvider.pinCode == '') {
return;
}
WalletsProfilesProvider
walletViewProvider = Provider.of<
WalletsProfilesProvider>(
context,
listen: false);
final acc = sub.getCurrentWallet();
final transactionId = await sub.certify(
acc.address!,
walletViewProvider.address,
myWalletProvider.pinCode);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transactionId: transactionId,
transType: 'cert');
}),
);
}),
),
),

View File

@ -24,8 +24,9 @@ class NextButton extends StatelessWidget {
child: ElevatedButton(
key: keyGoNext,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, backgroundColor: orangeC,
elevation: 4, // foreground
foregroundColor: Colors.white,
backgroundColor: orangeC,
elevation: 4,
),
onPressed: () {
Navigator.push(

View File

@ -33,9 +33,8 @@ void paymentPopup(BuildContext context, String toAddress, String? username) {
walletViewProvider.payAmount.text = '';
Future executeTransfert() async {
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
@ -44,25 +43,26 @@ void paymentPopup(BuildContext context, String toAddress, String? username) {
),
);
}
if (pin != null || myWalletProvider.pinCode != '') {
// Payment workflow !
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final acc = sub.getCurrentWallet();
log.d(
"fromAddress: ${acc.address!},destAddress: $toAddress, amount: ${double.parse(walletViewProvider.payAmount.text)}");
sub.pay(
fromAddress: acc.address!,
destAddress: toAddress,
amount: double.parse(walletViewProvider.payAmount.text),
password: pin ?? myWalletProvider.pinCode);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
toAddress: toAddress, toUsername: username);
}),
);
}
if (myWalletProvider.pinCode == '') return;
// Payment workflow !
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final acc = sub.getCurrentWallet();
log.d(
"fromAddress: ${acc.address!},destAddress: $toAddress, amount: ${double.parse(walletViewProvider.payAmount.text)}");
final transactionId = await sub.pay(
fromAddress: acc.address!,
destAddress: toAddress,
amount: double.parse(walletViewProvider.payAmount.text),
password: myWalletProvider.pinCode);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transactionId: transactionId,
toAddress: toAddress,
toUsername: username);
}),
);
}
myWalletProvider.readAllWallets().then((value) => myWalletProvider.listWallets

View File

@ -1660,7 +1660,7 @@ packages:
source: hosted
version: "3.1.0"
uuid:
dependency: transitive
dependency: "direct main"
description:
name: uuid
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"

View File

@ -61,6 +61,7 @@ dependencies:
url_launcher: ^6.1.11
crypto: ^3.0.3
screen_brightness: ^0.2.2+1
uuid: ^3.0.7
dev_dependencies:
# flutter_launcher_icons: ^0.9.2