diff --git a/lib/app/shared/constants/parameters.dart b/lib/app/shared/constants/parameters.dart index 54ac9f1ea..ba1f79d7e 100644 --- a/lib/app/shared/constants/parameters.dart +++ b/lib/app/shared/constants/parameters.dart @@ -66,4 +66,6 @@ class Parameters { static const String clientId = 'urn:altme:0001'; static const String clientSecret = 'urn:uuid:f2e1b84a-930b-4250-a6c6-f35cabf698c8'; + + static const int maxEntries = 3; } diff --git a/lib/app/shared/constants/secure_storage_keys.dart b/lib/app/shared/constants/secure_storage_keys.dart index 9adf15369..48c471af4 100644 --- a/lib/app/shared/constants/secure_storage_keys.dart +++ b/lib/app/shared/constants/secure_storage_keys.dart @@ -35,7 +35,7 @@ class SecureStorageKeys { static const String enableCryptographicHolderBinding = 'enableCryptographicHolderBinding'; static const String enableScopeParameter = 'enableScopeParameter'; - static const String isPreRegisteredWallet = 'isPreRegisteredWallet'; + static const String useBasicClientAuthentication = 'isPreRegisteredWallet'; static const String clientId = 'clientId'; static const String clientSecret = 'clientSecret'; diff --git a/lib/app/shared/extension/extension.dart b/lib/app/shared/extension/extension.dart index fa173ad47..cf7b1b524 100644 --- a/lib/app/shared/extension/extension.dart +++ b/lib/app/shared/extension/extension.dart @@ -1,3 +1,4 @@ export 'credential_status.dart'; export 'iterable_extension.dart'; export 'string_extension.dart'; +export 'unit8List_extension.dart'; diff --git a/lib/app/shared/extension/unit8List_extension.dart b/lib/app/shared/extension/unit8List_extension.dart new file mode 100644 index 000000000..ceb228099 --- /dev/null +++ b/lib/app/shared/extension/unit8List_extension.dart @@ -0,0 +1,21 @@ +import 'dart:typed_data'; + +extension Uint8ListExtension on Uint8List { + Uint8List get filterPayload { + final tester = Uint8List.fromList([5, 1]); + + if (length <= 6) { + return this; + } + + if (this[0] != tester[0]) { + return this; + } + + if (this[1] != tester[1]) { + return this; + } + + return sublist(6); + } +} diff --git a/lib/dashboard/connection/operation/cubit/operation_cubit.dart b/lib/dashboard/connection/operation/cubit/operation_cubit.dart index a92f53867..d2e2d9eba 100644 --- a/lib/dashboard/connection/operation/cubit/operation_cubit.dart +++ b/lib/dashboard/connection/operation/cubit/operation_cubit.dart @@ -458,122 +458,141 @@ class OperationCubit extends Cubit { emit(state.copyWith(status: AppStatus.goBack)); } + String? rpcNodeUrlForTransaction; + Future getBeaonOperationList({ required bool preCheckBalance, }) async { - try { - log.i('getOperationList'); + int retryCount = 0; + const maxRetries = Parameters.maxEntries; + while (retryCount < maxRetries) { + try { + log.i('getOperationList'); - final BeaconRequest beaconRequest = beaconCubit.state.beaconRequest!; + final BeaconRequest beaconRequest = beaconCubit.state.beaconRequest!; - final CryptoAccountData? currentAccount = walletCubit - .getCryptoAccountData(beaconRequest.request!.sourceAddress!); + final CryptoAccountData? currentAccount = walletCubit + .getCryptoAccountData(beaconRequest.request!.sourceAddress!); - if (currentAccount == null) { - throw ResponseMessage( - message: ResponseString - .RESPONSE_STRING_SOMETHING_WENT_WRONG_TRY_AGAIN_LATER, - ); - } + if (currentAccount == null) { + throw ResponseMessage( + message: ResponseString + .RESPONSE_STRING_SOMETHING_WENT_WRONG_TRY_AGAIN_LATER, + ); + } + + late String baseUrl; - late String baseUrl; - late String rpcNodeUrl; + final NetworkType? networkType = beaconRequest.request?.network?.type; - switch (beaconRequest.request!.network!.type!) { - case NetworkType.mainnet: + if (networkType == null) { + throw ResponseMessage( + message: ResponseString + .RESPONSE_STRING_SOMETHING_WENT_WRONG_TRY_AGAIN_LATER, + ); + } + + if (networkType == NetworkType.mainnet) { baseUrl = TezosNetwork.mainNet().apiUrl; final rpcNodeUrlList = TezosNetwork.mainNet().rpcNodeUrl as List; - rpcNodeUrl = rpcNodeUrlList[Random().nextInt(rpcNodeUrlList.length)]; - case NetworkType.ghostnet: + + rpcNodeUrlForTransaction ??= + rpcNodeUrlList[Random().nextInt(rpcNodeUrlList.length)]; + } else if (networkType == NetworkType.ghostnet) { baseUrl = TezosNetwork.ghostnet().apiUrl; - rpcNodeUrl = TezosNetwork.ghostnet().rpcNodeUrl as String; - case NetworkType.mondaynet: - case NetworkType.delphinet: - case NetworkType.edonet: - case NetworkType.florencenet: - case NetworkType.granadanet: - case NetworkType.hangzhounet: - case NetworkType.ithacanet: - case NetworkType.jakartanet: - case NetworkType.kathmandunet: - case NetworkType.custom: + rpcNodeUrlForTransaction = + TezosNetwork.ghostnet().rpcNodeUrl as String; + } else { throw ResponseMessage( message: ResponseString .RESPONSE_STRING_SOMETHING_WENT_WRONG_TRY_AGAIN_LATER, ); - } - - // TezartError also handles low balance - - if (preCheckBalance) { - /// check xtz balance - log.i('checking xtz'); - final int balance = await dioClient.get( - '$baseUrl/v1/accounts/${beaconRequest.request!.sourceAddress!}/balance', - ) as int; - log.i('total xtz - $balance'); - final formattedBalance = int.parse( - balance.toStringAsFixed(6).replaceAll('.', '').replaceAll(',', ''), - ); + } - final amount = int.parse(beaconRequest.operationDetails!.first.amount!); + // TezartError also handles low balance + + if (preCheckBalance) { + /// check xtz balance + log.i('checking xtz'); + final int balance = await dioClient.get( + '$baseUrl/v1/accounts/${beaconRequest.request!.sourceAddress!}/balance', + ) as int; + log.i('total xtz - $balance'); + final formattedBalance = int.parse( + balance.toStringAsFixed(6).replaceAll('.', '').replaceAll(',', ''), + ); - if (amount >= formattedBalance) { - emit( - state.copyWith( - message: StateMessage.error( - messageHandler: ResponseMessage( - message: - ResponseString.RESPONSE_STRING_transactionIsLikelyToFail, + final amount = + int.parse(beaconRequest.operationDetails!.first.amount!); + + if (amount >= formattedBalance) { + emit( + state.copyWith( + message: StateMessage.error( + messageHandler: ResponseMessage( + message: ResponseString + .RESPONSE_STRING_transactionIsLikelyToFail, + ), ), ), - ), - ); + ); + } } - } - - final client = TezartClient(rpcNodeUrl); - final keystore = - keyGenerator.getKeystore(secretKey: currentAccount.secretKey); - final operationList = OperationsList( - source: keystore, - publicKey: keystore.publicKey, - rpcInterface: client.rpcInterface, - ); + final client = TezartClient(rpcNodeUrlForTransaction!); + final keystore = + keyGenerator.getKeystore(secretKey: currentAccount.secretKey); - final List operations = getBeaonOperation(); - for (final element in operations) { - operationList.appendOperation(element); - } + final operationList = OperationsList( + source: keystore, + publicKey: keystore.publicKey, + rpcInterface: client.rpcInterface, + ); - final isReveal = await client.isKeyRevealed(keystore.address); - if (!isReveal) { - operationList.prependOperation(RevealOperation()); - } - log.i( - 'publicKey: ${keystore.publicKey} ' - 'amount: ${state.amount} ' - 'networkFee: ${state.fee} ' - 'address: ${keystore.address} =>To address: ' - '${beaconRequest.operationDetails!.first.destination!}', - ); + final List operations = getBeaonOperation(); + for (final element in operations) { + operationList.appendOperation(element); + } - return operationList; - } catch (e, s) { - log.e('error : $e, s: $s'); - if (e is MessageHandler) { - rethrow; - } else if (e is TezartNodeError) { - log.e('e: $e , metadata: ${e.metadata} , s: $s'); - rethrow; - } else { - throw ResponseMessage( - message: ResponseString.RESPONSE_STRING_OPERATION_FAILED, + final isReveal = await client.isKeyRevealed(keystore.address); + if (!isReveal) { + operationList.prependOperation(RevealOperation()); + } + log.i( + 'publicKey: ${keystore.publicKey} ' + 'amount: ${state.amount} ' + 'networkFee: ${state.fee} ' + 'address: ${keystore.address} =>To address: ' + '${beaconRequest.operationDetails!.first.destination!}', ); + + return operationList; + } catch (e, s) { + log.e('error : $e, s: $s'); + retryCount++; + log.i('retryCount: $retryCount'); + + if (e is MessageHandler) { + rethrow; + } else if (e is TezartNodeError) { + log.e('e: $e , metadata: ${e.metadata} , s: $s'); + if (retryCount < maxRetries) { + await Future.delayed(const Duration(seconds: 1)); + } else { + rethrow; + } + } else { + throw ResponseMessage( + message: ResponseString.RESPONSE_STRING_OPERATION_FAILED, + ); + } } } + + throw ResponseMessage( + message: ResponseString.RESPONSE_STRING_OPERATION_FAILED, + ); } List getBeaonOperation() { diff --git a/lib/dashboard/connection/sign_payload/cubit/sign_payload_cubit.dart b/lib/dashboard/connection/sign_payload/cubit/sign_payload_cubit.dart index 1eb68386b..f99c9d073 100644 --- a/lib/dashboard/connection/sign_payload/cubit/sign_payload_cubit.dart +++ b/lib/dashboard/connection/sign_payload/cubit/sign_payload_cubit.dart @@ -71,7 +71,8 @@ class SignPayloadCubit extends Cubit { encodedPayload = stringToHexPrefixedWith05(payload: payload); signingType = SigningType.raw; } - final bytes = hexToBytes(encodedPayload); + final bytes = hexToBytes(encodedPayload).filterPayload; + payloadMessage = utf8.decode(bytes, allowMalformed: true); case ConnectionBridgeType.walletconnect: diff --git a/lib/dashboard/connection/sign_payload/view/sign_payload_page.dart b/lib/dashboard/connection/sign_payload/view/sign_payload_page.dart index 6d3ef996f..f618ebebc 100644 --- a/lib/dashboard/connection/sign_payload/view/sign_payload_page.dart +++ b/lib/dashboard/connection/sign_payload/view/sign_payload_page.dart @@ -187,7 +187,7 @@ class _SignPayloadViewState extends State { textAlign: TextAlign.left, style: Theme.of(context).textTheme.titleLarge, ), - const SizedBox(height: Sizes.spaceXLarge), + const SizedBox(height: Sizes.spaceXSmall), Text( message, textAlign: TextAlign.left, diff --git a/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/view/oidc4vc_settings_menu.dart b/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/view/oidc4vc_settings_menu.dart index d872f23d6..cde90d76f 100644 --- a/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/view/oidc4vc_settings_menu.dart +++ b/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/view/oidc4vc_settings_menu.dart @@ -43,7 +43,7 @@ class Oidc4vcSettingMenuView extends StatelessWidget { const SubjectSyntaxTypeWidget(), const CryptographicHolderBindingWidget(), const ScopeParameterWidget(), - const PreRegisteredWalletWidget(), + const ClientAuthenticationWidget(), DrawerItem( title: l10n.clientMetadata, onTap: () { diff --git a/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/client_authentication_widget.dart b/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/client_authentication_widget.dart new file mode 100644 index 000000000..92df5977b --- /dev/null +++ b/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/client_authentication_widget.dart @@ -0,0 +1,353 @@ +import 'package:altme/app/app.dart'; +import 'package:altme/dashboard/profile/profile.dart'; +import 'package:altme/l10n/l10n.dart'; +import 'package:altme/theme/theme.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class ClientAuthenticationWidget extends StatelessWidget { + const ClientAuthenticationWidget({super.key}); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + return BlocBuilder( + builder: (context, state) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.max, + children: [ + Container( + padding: const EdgeInsets.all(Sizes.spaceSmall), + margin: const EdgeInsets.all(Sizes.spaceXSmall), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.drawerSurface, + borderRadius: const BorderRadius.all( + Radius.circular(Sizes.largeRadius), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + l10n.clientAuthentication, + style: Theme.of(context).textTheme.drawerItemTitle, + ), + const SizedBox(height: 10), + Text( + l10n.clientAuthenticationSubtitle, + style: Theme.of(context).textTheme.drawerItemSubtitle, + ), + const SizedBox(height: 10), + Opacity( + opacity: state.model.useBasicClientAuthentication + ? 1 + : 0.5, + child: Column( + children: [ + TransparentInkWell( + onTap: () async { + final String? clientId = + await showDialog( + context: context, + builder: (_) { + final color = + Theme.of(context).colorScheme.primary; + final background = Theme.of(context) + .colorScheme + .popupBackground; + final textColor = Theme.of(context) + .colorScheme + .dialogText; + + final clientIdController = + TextEditingController( + text: state.model.clientId, + ); + + return AlertDialog( + backgroundColor: background, + surfaceTintColor: Colors.transparent, + contentPadding: + const EdgeInsets.symmetric( + horizontal: 20, + vertical: 15, + ), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(25), + ), + ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Image.asset( + IconStrings.cardReceive, + width: 50, + height: 50, + color: textColor, + ), + const SizedBox( + height: Sizes.spaceNormal, + ), + TextFormField( + controller: clientIdController, + style: Theme.of(context) + .textTheme + .labelMedium, + maxLines: 1, + decoration: const InputDecoration( + border: OutlineInputBorder( + borderRadius: + BorderRadius.all( + Radius.circular( + Sizes.smallRadius, + ), + ), + ), + contentPadding: + EdgeInsets.symmetric( + vertical: 5, + horizontal: 10, + ), + ), + ), + const SizedBox( + height: Sizes.spaceNormal, + ), + MyElevatedButton( + text: l10n.confirm, + verticalSpacing: 14, + backgroundColor: color, + borderRadius: Sizes.smallRadius, + fontSize: 15, + elevation: 0, + onPressed: () { + Navigator.of(context).pop( + clientIdController.text + .trim(), + ); + }, + ), + const SizedBox(height: 15), + ], + ), + ); + }, + ); + + if (clientId != null) { + await context + .read() + .updateClientId(clientId); + } + }, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 7, + horizontal: 10, + ), + decoration: BoxDecoration( + border: Border.all( + color: Theme.of(context) + .colorScheme + .onBackground, + ), + borderRadius: const BorderRadius.all( + Radius.circular( + Sizes.smallRadius, + ), + ), + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + '${l10n.clientId}: ${state.model.clientId}', + style: Theme.of(context) + .textTheme + .drawerItemSubtitle, + ), + ), + const SizedBox(width: 8), + const Icon( + Icons.edit, + size: 20, + ), + ], + ), + ), + ), + const SizedBox(height: 10), + TransparentInkWell( + onTap: () async { + final String? clientSecret = + await showDialog( + context: context, + builder: (_) { + final color = + Theme.of(context).colorScheme.primary; + final background = Theme.of(context) + .colorScheme + .popupBackground; + final textColor = Theme.of(context) + .colorScheme + .dialogText; + + final clientSecretController = + TextEditingController( + text: state.model.clientSecret, + ); + + return AlertDialog( + backgroundColor: background, + surfaceTintColor: Colors.transparent, + contentPadding: + const EdgeInsets.symmetric( + horizontal: 20, + vertical: 15, + ), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(25), + ), + ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Image.asset( + IconStrings.cardReceive, + width: 50, + height: 50, + color: textColor, + ), + const SizedBox( + height: Sizes.spaceNormal, + ), + TextFormField( + controller: + clientSecretController, + style: Theme.of(context) + .textTheme + .labelMedium, + maxLines: 1, + decoration: const InputDecoration( + border: OutlineInputBorder( + borderRadius: + BorderRadius.all( + Radius.circular( + Sizes.smallRadius, + ), + ), + ), + contentPadding: + EdgeInsets.symmetric( + vertical: 5, + horizontal: 10, + ), + ), + ), + const SizedBox( + height: Sizes.spaceNormal, + ), + MyElevatedButton( + text: l10n.confirm, + verticalSpacing: 14, + backgroundColor: color, + borderRadius: Sizes.smallRadius, + fontSize: 15, + elevation: 0, + onPressed: () { + Navigator.of(context).pop( + clientSecretController.text + .trim(), + ); + }, + ), + const SizedBox(height: 15), + ], + ), + ); + }, + ); + + if (clientSecret != null) { + await context + .read() + .updateClientSecret(clientSecret); + } + }, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 7, + horizontal: 10, + ), + decoration: BoxDecoration( + border: Border.all( + color: Theme.of(context) + .colorScheme + .onBackground, + ), + borderRadius: const BorderRadius.all( + Radius.circular( + Sizes.smallRadius, + ), + ), + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + '${l10n.clientSecret}: ' + '${state.model.clientSecret}', + style: Theme.of(context) + .textTheme + .drawerItemSubtitle, + ), + ), + const SizedBox(width: 8), + const Icon( + Icons.edit, + size: 20, + ), + ], + ), + ), + ), + ], + ), + ), + ], + ), + ), + const SizedBox(height: 10), + Switch( + onChanged: (value) async { + await context + .read() + .updateBasicClientAuthenticationStatus( + enabled: value, + ); + }, + value: state.model.useBasicClientAuthentication, + activeColor: Theme.of(context).colorScheme.primary, + ), + ], + ), + ), + ], + ); + }, + ); + } +} diff --git a/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/pre_registered_wallet_widget.dart b/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/pre_registered_wallet_widget.dart deleted file mode 100644 index a98c93e15..000000000 --- a/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/pre_registered_wallet_widget.dart +++ /dev/null @@ -1,328 +0,0 @@ -import 'package:altme/app/app.dart'; -import 'package:altme/dashboard/profile/profile.dart'; -import 'package:altme/l10n/l10n.dart'; -import 'package:altme/theme/theme.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -class PreRegisteredWalletWidget extends StatelessWidget { - const PreRegisteredWalletWidget({super.key}); - - @override - Widget build(BuildContext context) { - final l10n = context.l10n; - return BlocBuilder( - builder: (context, state) { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisSize: MainAxisSize.max, - children: [ - Container( - padding: const EdgeInsets.all(Sizes.spaceSmall), - margin: const EdgeInsets.all(Sizes.spaceXSmall), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.drawerSurface, - borderRadius: const BorderRadius.all( - Radius.circular(Sizes.largeRadius), - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - l10n.preRegisteredWallet, - style: Theme.of(context).textTheme.drawerItemTitle, - ), - const SizedBox(height: 10), - Text( - l10n.preRegisteredWalletSubtitle, - style: Theme.of(context).textTheme.drawerItemSubtitle, - ), - const SizedBox(height: 10), - TransparentInkWell( - onTap: () async { - final String? clientId = await showDialog( - context: context, - builder: (_) { - final color = - Theme.of(context).colorScheme.primary; - final background = Theme.of(context) - .colorScheme - .popupBackground; - final textColor = - Theme.of(context).colorScheme.dialogText; - - final clientIdController = - TextEditingController( - text: state.model.clientId, - ); - - return AlertDialog( - backgroundColor: background, - surfaceTintColor: Colors.transparent, - contentPadding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 15, - ), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(25), - ), - ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Image.asset( - IconStrings.cardReceive, - width: 50, - height: 50, - color: textColor, - ), - const SizedBox( - height: Sizes.spaceNormal, - ), - TextFormField( - controller: clientIdController, - style: Theme.of(context) - .textTheme - .labelMedium, - maxLines: 1, - decoration: const InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular( - Sizes.smallRadius, - ), - ), - ), - contentPadding: EdgeInsets.symmetric( - vertical: 5, - horizontal: 10, - ), - ), - ), - const SizedBox( - height: Sizes.spaceNormal, - ), - MyElevatedButton( - text: l10n.confirm, - verticalSpacing: 14, - backgroundColor: color, - borderRadius: Sizes.smallRadius, - fontSize: 15, - elevation: 0, - onPressed: () { - Navigator.of(context).pop( - clientIdController.text.trim(), - ); - }, - ), - const SizedBox(height: 15), - ], - ), - ); - }, - ); - - if (clientId != null) { - await context - .read() - .updateClientId(clientId); - } - }, - child: Container( - padding: const EdgeInsets.symmetric( - vertical: 7, - horizontal: 10, - ), - decoration: BoxDecoration( - border: Border.all( - color: - Theme.of(context).colorScheme.onBackground, - ), - borderRadius: const BorderRadius.all( - Radius.circular( - Sizes.smallRadius, - ), - ), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Text( - '${l10n.clientId}: ${state.model.clientId}', - style: Theme.of(context) - .textTheme - .drawerItemSubtitle, - ), - ), - const SizedBox(width: 8), - const Icon( - Icons.edit, - size: 20, - ), - ], - ), - ), - ), - const SizedBox(height: 10), - TransparentInkWell( - onTap: () async { - final String? clientSecret = - await showDialog( - context: context, - builder: (_) { - final color = - Theme.of(context).colorScheme.primary; - final background = Theme.of(context) - .colorScheme - .popupBackground; - final textColor = - Theme.of(context).colorScheme.dialogText; - - final clientSecretController = - TextEditingController( - text: state.model.clientSecret, - ); - - return AlertDialog( - backgroundColor: background, - surfaceTintColor: Colors.transparent, - contentPadding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 15, - ), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(25), - ), - ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Image.asset( - IconStrings.cardReceive, - width: 50, - height: 50, - color: textColor, - ), - const SizedBox( - height: Sizes.spaceNormal, - ), - TextFormField( - controller: clientSecretController, - style: Theme.of(context) - .textTheme - .labelMedium, - maxLines: 1, - decoration: const InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular( - Sizes.smallRadius, - ), - ), - ), - contentPadding: EdgeInsets.symmetric( - vertical: 5, - horizontal: 10, - ), - ), - ), - const SizedBox( - height: Sizes.spaceNormal, - ), - MyElevatedButton( - text: l10n.confirm, - verticalSpacing: 14, - backgroundColor: color, - borderRadius: Sizes.smallRadius, - fontSize: 15, - elevation: 0, - onPressed: () { - Navigator.of(context).pop( - clientSecretController.text.trim(), - ); - }, - ), - const SizedBox(height: 15), - ], - ), - ); - }, - ); - - if (clientSecret != null) { - await context - .read() - .updateClientSecret(clientSecret); - } - }, - child: Container( - padding: const EdgeInsets.symmetric( - vertical: 7, - horizontal: 10, - ), - decoration: BoxDecoration( - border: Border.all( - color: - Theme.of(context).colorScheme.onBackground, - ), - borderRadius: const BorderRadius.all( - Radius.circular( - Sizes.smallRadius, - ), - ), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Text( - '${l10n.clientSecret}: ' - '${state.model.clientSecret}', - style: Theme.of(context) - .textTheme - .drawerItemSubtitle, - ), - ), - const SizedBox(width: 8), - const Icon( - Icons.edit, - size: 20, - ), - ], - ), - ), - ), - ], - ), - ), - const SizedBox(height: 10), - Switch( - onChanged: (value) async { - await context - .read() - .updatePreRegisteredWalletStatus( - enabled: value, - ); - }, - value: state.model.isPreRegisteredWallet, - activeColor: Theme.of(context).colorScheme.primary, - ), - ], - ), - ), - ], - ); - }, - ); - } -} diff --git a/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/widget.dart b/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/widget.dart index f433dbe55..8eef20985 100644 --- a/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/widget.dart +++ b/lib/dashboard/drawer/ssi/advanced_settings2/oidc4vc_settngs/widget/widget.dart @@ -1,6 +1,6 @@ export 'cryptograhic_holder_binding.dart'; export 'did_key_type_widget.dart'; -export 'pre_registered_wallet_widget.dart'; +export 'client_authentication_widget.dart'; export 'scope_parameter.dart'; export 'security_level_widget.dart'; export 'six_or_four_pin_widget.dart'; diff --git a/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/cubit/confirm_token_transaction_cubit.dart b/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/cubit/confirm_token_transaction_cubit.dart index e42e92800..af04de485 100644 --- a/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/cubit/confirm_token_transaction_cubit.dart +++ b/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/cubit/confirm_token_transaction_cubit.dart @@ -137,15 +137,21 @@ class ConfirmTokenTransactionCubit extends Cubit { Future _calculateFeeTezos() async { int retryCount = 0; - const maxRetries = 3; + const maxRetries = Parameters.maxEntries; while (retryCount < maxRetries) { try { emit(state.loading()); - final rpcNodeUrlList = - manageNetworkCubit.state.network.rpcNodeUrl as List; - rpcNodeUrlForTransaction = - rpcNodeUrlList[Random().nextInt(rpcNodeUrlList.length)]; + + final dynamic rpcNodeUrl = manageNetworkCubit.state.network.rpcNodeUrl; + + if (rpcNodeUrl is List) { + rpcNodeUrlForTransaction = + rpcNodeUrl[Random().nextInt(rpcNodeUrl.length)]; + } else { + rpcNodeUrlForTransaction = rpcNodeUrl.toString(); + } + logger.i('rpcNodeUrl: $rpcNodeUrlForTransaction'); final client = TezartClient(rpcNodeUrlForTransaction); final keystore = KeyGenerator() @@ -189,14 +195,23 @@ class ConfirmTokenTransactionCubit extends Cubit { ); break; } catch (e, s) { - logger.e('e: $e s: $s'); - retryCount++; - logger.i('retryCount: $retryCount'); + logger.e('error : $e, s: $s'); - if (retryCount < maxRetries) { - await Future.delayed(const Duration(seconds: 1)); - } else { + if (e is MessageHandler) { rethrow; + } else if (e is TezartNodeError) { + logger.e('e: $e , metadata: ${e.metadata} , s: $s'); + retryCount++; + logger.i('retryCount: $retryCount'); + if (retryCount < maxRetries) { + await Future.delayed(const Duration(seconds: 1)); + } else { + rethrow; + } + } else { + throw ResponseMessage( + message: ResponseString.RESPONSE_STRING_OPERATION_FAILED, + ); } } } diff --git a/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/view/confirm_token_transaction_page.dart b/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/view/confirm_token_transaction_page.dart index 783754ed1..9ea6381e1 100644 --- a/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/view/confirm_token_transaction_page.dart +++ b/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/view/confirm_token_transaction_page.dart @@ -2,6 +2,7 @@ import 'package:altme/app/app.dart'; import 'package:altme/dashboard/dashboard.dart'; import 'package:altme/l10n/l10n.dart'; import 'package:altme/pin_code/pin_code.dart'; +import 'package:altme/theme/theme.dart'; import 'package:altme/wallet/cubit/wallet_cubit.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; @@ -84,16 +85,8 @@ class ConfirmWithdrawalView extends StatefulWidget { } class _ConfirmWithdrawalViewState extends State { - late final TextEditingController withdrawalAddressController = - TextEditingController(text: widget.withdrawalAddress); - @override void initState() { - withdrawalAddressController.addListener(() { - context.read().setWithdrawalAddress( - withdrawalAddress: withdrawalAddressController.text, - ); - }); Future.microtask(context.read().calculateFee); super.initState(); } @@ -192,17 +185,33 @@ class _ConfirmWithdrawalViewState extends State { const SizedBox(height: Sizes.spaceSmall), const FromAccountWidget(isEnabled: false), const SizedBox(height: Sizes.spaceNormal), - WithdrawalAddressInputView( - withdrawalAddressController: withdrawalAddressController, - caption: l10n.to, - onValidAddress: (address) { - // context - // .read() - // .setWithdrawalAddress(withdrawalAddress: address); - // context - // .read() - // .calculateFee(); - }, + BackgroundCard( + color: Theme.of(context).colorScheme.cardBackground, + child: SizedBox( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + l10n.to, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + color: + Theme.of(context).colorScheme.onSurface, + ), + ), + const SizedBox(height: Sizes.spaceXSmall), + MyText( + widget.withdrawalAddress, + maxLines: 2, + style: Theme.of(context).textTheme.walletAddress, + ), + ], + ), + ), ), Padding( padding: const EdgeInsets.all(Sizes.spaceSmall), diff --git a/lib/dashboard/home/tab_bar/tokens/widgets/account_select_box_view.dart b/lib/dashboard/home/tab_bar/tokens/widgets/account_select_box_view.dart index f2f3f66a2..319ef909b 100644 --- a/lib/dashboard/home/tab_bar/tokens/widgets/account_select_box_view.dart +++ b/lib/dashboard/home/tab_bar/tokens/widgets/account_select_box_view.dart @@ -36,8 +36,8 @@ class AccountSelectBoxView extends StatelessWidget { cryptoAccountData: accounts[selectedAccountIndex], isBoxOpen: true, onPressed: isEnabled ? null : null, - ), - if (isEnabled) + ) + else Theme( data: Theme.of(context).copyWith( unselectedWidgetColor: Theme.of(context).colorScheme.onPrimary, diff --git a/lib/dashboard/home/tab_bar/tokens/widgets/from_account_widget.dart b/lib/dashboard/home/tab_bar/tokens/widgets/from_account_widget.dart index 9d1ad7320..23388cbce 100644 --- a/lib/dashboard/home/tab_bar/tokens/widgets/from_account_widget.dart +++ b/lib/dashboard/home/tab_bar/tokens/widgets/from_account_widget.dart @@ -19,6 +19,7 @@ class FromAccountWidget extends StatelessWidget { builder: (context, walletState) { return AccountSelectBoxView( title: l10n.from, + isEnabled: isEnabled, accounts: walletState.cryptoAccount.data, selectedAccountIndex: walletState.currentCryptoIndex, onSelectAccount: (accountData, index) { diff --git a/lib/dashboard/profile/cubit/profile_cubit.dart b/lib/dashboard/profile/cubit/profile_cubit.dart index 6bdc4da47..a4086f68c 100644 --- a/lib/dashboard/profile/cubit/profile_cubit.dart +++ b/lib/dashboard/profile/cubit/profile_cubit.dart @@ -133,11 +133,12 @@ class ProfileCubit extends Cubit { final enableScopeParameter = enableScopeParameterValue != null && enableScopeParameterValue == 'true'; - final isPreRegisteredWalletValue = await secureStorageProvider - .get(SecureStorageKeys.isPreRegisteredWallet); + final useBasicClientAuthenticationValue = await secureStorageProvider + .get(SecureStorageKeys.useBasicClientAuthentication); - final isPreRegisteredWallet = isPreRegisteredWalletValue != null && - isPreRegisteredWalletValue == 'true'; + final useBasicClientAuthentication = + useBasicClientAuthenticationValue != null && + useBasicClientAuthenticationValue == 'true'; final clientId = await secureStorageProvider.get(SecureStorageKeys.clientId) ?? @@ -182,7 +183,7 @@ class ProfileCubit extends Cubit { enableJWKThumbprint: enableJWKThumbprint, enableCryptographicHolderBinding: enableCryptographicHolderBinding, enableScopeParameter: enableScopeParameter, - isPreRegisteredWallet: isPreRegisteredWallet, + useBasicClientAuthentication: useBasicClientAuthentication, clientId: clientId, clientSecret: clientSecret, ); @@ -305,8 +306,8 @@ class ProfileCubit extends Cubit { ); await secureStorageProvider.set( - SecureStorageKeys.isPreRegisteredWallet, - profileModel.isPreRegisteredWallet.toString(), + SecureStorageKeys.useBasicClientAuthentication, + profileModel.useBasicClientAuthentication.toString(), ); emit( @@ -402,8 +403,11 @@ class ProfileCubit extends Cubit { await update(profileModel); } - Future updatePreRegisteredWalletStatus({bool enabled = false}) async { - final profileModel = state.model.copyWith(isPreRegisteredWallet: enabled); + Future updateBasicClientAuthenticationStatus({ + bool enabled = false, + }) async { + final profileModel = + state.model.copyWith(useBasicClientAuthentication: enabled); await update(profileModel); } diff --git a/lib/dashboard/profile/models/profile.dart b/lib/dashboard/profile/models/profile.dart index 95cb26d1f..51ccc95ef 100644 --- a/lib/dashboard/profile/models/profile.dart +++ b/lib/dashboard/profile/models/profile.dart @@ -23,7 +23,7 @@ class ProfileModel extends Equatable { required this.enableJWKThumbprint, required this.enableCryptographicHolderBinding, required this.enableScopeParameter, - required this.isPreRegisteredWallet, + required this.useBasicClientAuthentication, this.companyName = '', this.companyWebsite = '', this.jobTitle = '', @@ -60,7 +60,7 @@ class ProfileModel extends Equatable { enableJWKThumbprint: false, enableCryptographicHolderBinding: true, enableScopeParameter: false, - isPreRegisteredWallet: false, + useBasicClientAuthentication: false, clientId: Parameters.clientId, clientSecret: Parameters.clientSecret, ); @@ -88,7 +88,7 @@ class ProfileModel extends Equatable { final bool enableJWKThumbprint; final bool enableCryptographicHolderBinding; final bool enableScopeParameter; - final bool isPreRegisteredWallet; + final bool useBasicClientAuthentication; final String clientId; final String clientSecret; @@ -116,7 +116,7 @@ class ProfileModel extends Equatable { enableJWKThumbprint, enableCryptographicHolderBinding, enableScopeParameter, - isPreRegisteredWallet, + useBasicClientAuthentication, clientId, clientSecret, ]; @@ -146,7 +146,7 @@ class ProfileModel extends Equatable { bool? enableJWKThumbprint, bool? enableCryptographicHolderBinding, bool? enableScopeParameter, - bool? isPreRegisteredWallet, + bool? useBasicClientAuthentication, String? clientId, String? clientSecret, }) { @@ -168,8 +168,8 @@ class ProfileModel extends Equatable { enableCryptographicHolderBinding: enableCryptographicHolderBinding ?? this.enableCryptographicHolderBinding, enableScopeParameter: enableScopeParameter ?? this.enableScopeParameter, - isPreRegisteredWallet: - isPreRegisteredWallet ?? this.isPreRegisteredWallet, + useBasicClientAuthentication: + useBasicClientAuthentication ?? this.useBasicClientAuthentication, clientId: clientId ?? this.clientId, clientSecret: clientSecret ?? this.clientSecret, userConsentForIssuerAccess: diff --git a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart index 67dff84ed..00e704037 100644 --- a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart +++ b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart @@ -1084,10 +1084,10 @@ class QRCodeScanCubit extends Cubit { String clientId = ''; String? clientSecret; - final useClientIdAndClientRequest = - profileCubit.state.model.isPreRegisteredWallet; + final useBasicClientAuthentication = + profileCubit.state.model.useBasicClientAuthentication; - if (useClientIdAndClientRequest) { + if (useBasicClientAuthentication) { clientId = profileCubit.state.model.clientId; clientSecret = profileCubit.state.model.clientSecret; } else { diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index cf8d5da97..58d1b5282 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -988,8 +988,8 @@ "cryptographicHolderBindingSubtitle": "Default : On\nDisable to accept Bearer credentials as tickets with low assurance.", "scopeParameters": "Scope Parameters", "scopeParametersSubtitle": "Default : Off\nEnable to force wallet to use scope instead of authorization_details.", - "preRegisteredWallet": "Pre registered wallet", - "preRegisteredWalletSubtitle": "Default : Off\nEnable to use client_id and client_secret values.", + "clientAuthentication": "Client Authentication", + "clientAuthenticationSubtitle": "Default : Public client\nEnable to use the Basic Authentication scheme.", "theServiceIsNotAvailable": "The service is not available", "issuerDID": "Issuer DID", "subjectDID": "Subject DID", diff --git a/lib/l10n/untranslated.json b/lib/l10n/untranslated.json index 8d8254a4e..fb7287fe7 100644 --- a/lib/l10n/untranslated.json +++ b/lib/l10n/untranslated.json @@ -893,8 +893,8 @@ "cryptographicHolderBindingSubtitle", "scopeParameters", "scopeParametersSubtitle", - "preRegisteredWallet", - "preRegisteredWalletSubtitle", + "clientAuthentication", + "clientAuthenticationSubtitle", "theServiceIsNotAvailable", "issuerDID", "subjectDID", @@ -1806,8 +1806,8 @@ "cryptographicHolderBindingSubtitle", "scopeParameters", "scopeParametersSubtitle", - "preRegisteredWallet", - "preRegisteredWalletSubtitle", + "clientAuthentication", + "clientAuthenticationSubtitle", "theServiceIsNotAvailable", "issuerDID", "subjectDID", @@ -2022,8 +2022,8 @@ "cryptographicHolderBindingSubtitle", "scopeParameters", "scopeParametersSubtitle", - "preRegisteredWallet", - "preRegisteredWalletSubtitle", + "clientAuthentication", + "clientAuthenticationSubtitle", "theServiceIsNotAvailable", "issuerDID", "subjectDID", @@ -2935,8 +2935,8 @@ "cryptographicHolderBindingSubtitle", "scopeParameters", "scopeParametersSubtitle", - "preRegisteredWallet", - "preRegisteredWalletSubtitle", + "clientAuthentication", + "clientAuthenticationSubtitle", "theServiceIsNotAvailable", "issuerDID", "subjectDID", diff --git a/pubspec.lock b/pubspec.lock index 150e181a4..d7842a94b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: archive - sha256: "0da817eab9833cc222ee5575789664e99f60fe0c554be55dc1979f9b4ec6dd73" + sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b" url: "https://pub.dev" source: hosted - version: "3.4.8" + version: "3.4.9" args: dependency: transitive description: @@ -2521,10 +2521,10 @@ packages: dependency: "direct main" description: name: walletconnect_flutter_v2 - sha256: "55315779dd94b5b38754c8abcccba6e8f159083e799945dc49441a20dc73cffd" + sha256: "00005750b01c5b924fc028e329bee5a77f79691c8c537709536e8ef27360510a" url: "https://pub.dev" source: hosted - version: "2.1.8" + version: "2.1.9" watcher: dependency: transitive description: @@ -2601,10 +2601,10 @@ packages: dependency: "direct main" description: name: webview_flutter_wkwebview - sha256: af6f5ab05918070b33507b0d453ba9fb7d39338a3256c23cf9433dc68100774a + sha256: accdaaa49a2aca2dc3c3230907988954cdd23fed0a19525d6c9789d380f4dc76 url: "https://pub.dev" source: hosted - version: "3.9.3" + version: "3.9.4" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 919ba8511..4a58e4558 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: altme description: AltMe Flutter App -version: 1.24.2+315 +version: 1.24.3+316 environment: sdk: ">=3.1.0 <4.0.0"