diff --git a/demo/app/ios/Podfile.lock b/demo/app/ios/Podfile.lock index d4a9422a..573148f9 100644 --- a/demo/app/ios/Podfile.lock +++ b/demo/app/ios/Podfile.lock @@ -81,7 +81,7 @@ SPEC CHECKSUMS: FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a integration_test: 13825b8a9334a850581300559b8839134b124670 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb - path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 + path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e safe_device: 4539eb6bdbeb4b61a763a51c4e73e6b37dea4e3d diff --git a/demo/app/ios/Runner/OpenID4CI.swift b/demo/app/ios/Runner/OpenID4CI.swift index 2dff7caa..50a8452b 100644 --- a/demo/app/ios/Runner/OpenID4CI.swift +++ b/demo/app/ios/Runner/OpenID4CI.swift @@ -110,4 +110,11 @@ public class OpenID4CI { func getAuthorizationCodeGrantParams() throws -> Openid4ciAuthorizationCodeGrantParams { return try initiatedInteraction.authorizationCodeGrantParams() } + + // Not doing locale handling or text color handling etc. + func getIssuerMetadata() throws -> Openid4ciIssuerMetadata { + return try initiatedInteraction.issuerMetadata() + } + + } diff --git a/demo/app/ios/Runner/flutterPlugin.swift b/demo/app/ios/Runner/flutterPlugin.swift index 3d65e921..df75706d 100644 --- a/demo/app/ios/Runner/flutterPlugin.swift +++ b/demo/app/ios/Runner/flutterPlugin.swift @@ -87,6 +87,9 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin { case "getIssuerID": getIssuerID(arguments: arguments!, result:result) + case "getIssuerMetaData": + getIssuerMetaData(result:result) + case "activityLogger": storeActivityLogger(result:result) @@ -404,6 +407,88 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin { } } + public func getIssuerMetaData(result: @escaping FlutterResult) { + guard let openID4CI = self.openID4CI else{ + return result(FlutterError.init(code: "NATIVE_ERR", + message: "error while getting issuer meta data", + details: "openID4CI not initiated. Call authorize before this.")) + } + + do { + + var issuerMetaData = try openID4CI.getIssuerMetadata() + // creddential issuer + var credIssuer = issuerMetaData.credentialIssuer() + + // supported Credentials list + var supportedCredentials = issuerMetaData.supportedCredentials()! + var supportedCredentialsList = getSupportedCredentialsList(supportedCredentials: supportedCredentials) + + // localized issuer displays data + var localizedIssuerDisplays = issuerMetaData.localizedIssuerDisplays()! + var localizedIssuerDisplayList :[Any] = [] + for index in 0.. [Any] { + var supportedCredentialsList: [Any] = [] + for index in 0.., result: @escaping FlutterResult){ guard let issuerURI = arguments["issuerURI"] as? String else { return result(FlutterError.init(code: "NATIVE_ERR", @@ -422,20 +507,8 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin { let walletInitiatedOpenID4CI = try walletSDK.createOpenID4CIWalletIntiatedInteraction(issuerURI: issuerURI) let supportedCredentials = try walletInitiatedOpenID4CI.getSupportedCredentials() - var supportedCredentialsList: [Any] = [] - for index in 0.. prefs = SharedPreferences.getInstance(); var authCodeArgs; - if (qrCodeURL.contains("credential_offer_uri")){ + if (qrCodeURL.contains("credential_offer_uri")) { authCodeArgs = await parseCredentialOfferUri(qrCodeURL); log("credential offer uri auth code ${authCodeArgs}"); } else { - if (qrCodeURL.contains("authorization_code")){ + if (qrCodeURL.contains("authorization_code")) { authCodeArgs = await readIssuerAuthFlowConfig(qrCodeURL); log("auth code arguments fetched from config file $authCodeArgs"); // While fetching auth code args based on issuer key from file, if no key-value pair is found then set the // arguments to default scope and redirect url. authCodeArgs ??= { - "scopes": [ - "openid", - "profile" - ], - "redirectURI": "trustbloc-wallet://openid4vci/authcodeflow/callback" - }; + "scopes": ["openid", "profile"], + "redirectURI": "trustbloc-wallet://openid4vci/authcodeflow/callback" + }; } } @@ -50,21 +43,21 @@ void handleOpenIDIssuanceFlow(BuildContext context, String qrCodeURL) async { var authorizeResultPinRequired = responseJson["pinRequired"]; log("pin required flow - $authorizeResultPinRequired"); if (authorizeResultPinRequired == true) { - navigateToOTPScreen(context); + navigateToIssuancePreviewScreen(context, authorizeResultPinRequired); return; } else if (responseJson["authorizationURLLink"] != '') { // initiate authCode Flow log("initiating authCode Flow- ${responseJson["authorizationURLLink"]}"); Uri uri = Uri.parse(responseJson["authorizationURLLink"]); - navigateToAuthFlow(context, uri); + navigateToIssuancePreviewScreenAuthFlow(context, uri); return; } else { - navigateToWithoutPinFlow(context); + navigateToIssuancePreviewScreen(context, authorizeResultPinRequired); return; } } - readIssuerAuthFlowConfig(String qrCodeURL) async { +readIssuerAuthFlowConfig(String qrCodeURL) async { var decodedUri = Uri.decodeComponent(qrCodeURL); final uri = Uri.parse(decodedUri); var credentialIssuerKey = json.decode(uri.queryParameters["credential_offer"]!); @@ -76,8 +69,7 @@ void handleOpenIDIssuanceFlow(BuildContext context, String qrCodeURL) async { parseCredentialOfferUri(String qrCodeURL) async { var decodedUri = Uri.decodeComponent(qrCodeURL); final uri = Uri.parse(decodedUri); - final response = await http - .get(Uri.parse(uri.queryParameters['credential_offer_uri']!)); + final response = await http.get(Uri.parse(uri.queryParameters['credential_offer_uri']!)); if (response.statusCode == 200) { final String configResp = await rootBundle.loadString('lib/assets/issuerAuthFlowConfig.json'); final configData = await json.decode(configResp); @@ -88,59 +80,11 @@ parseCredentialOfferUri(String qrCodeURL) async { } } -void navigateToWithoutPinFlow(BuildContext context) async{ - final Future prefs = SharedPreferences.getInstance(); - var WalletSDKPlugin = WalletSDK(); - final StorageService storageService = StorageService(); - final SharedPreferences pref = await prefs; - - var didType = pref.getString('didType'); - var keyType = pref.getString('keyType'); - // choosing default if no selection is made - didType = didType ?? "ion"; - keyType = keyType ?? "ED25519"; - - var didResolution = await WalletSDKPlugin.createDID(didType, keyType); - var didDocEncoded = json.encode(didResolution); - Map responseJson = json.decode(didDocEncoded); - - var didID = responseJson["did"]; - var didDoc = responseJson["didDoc"]; - log("created didID :$didID"); - pref.setString('userDID',didID); - pref.setString('userDIDDoc',didDoc); - - String? credentials = await WalletSDKPlugin.requestCredential(''); - String? issuerURL = await WalletSDKPlugin.issuerURI(); - String? resolvedCredentialDisplay = await WalletSDKPlugin.serializeDisplayData([credentials],issuerURL!); - - var activities = await WalletSDKPlugin.storeActivityLogger(); - - var credID = await WalletSDKPlugin.getCredID([credentials]); - - log("activities and credID handle open id -$activities and $credID"); - storageService.addActivities(ActivityDataObj(credID!, activities)); - - navigateToCredPreviewScreen(context, credentials, issuerURL, resolvedCredentialDisplay!, didID, credID); +void navigateToIssuancePreviewScreen(BuildContext context, bool? authorizeResultPinRequired) async { + Navigator.push(context, + MaterialPageRoute(builder: (context) => IssuancePreview(authorizeResultPinRequired: authorizeResultPinRequired))); } -void navigateToOTPScreen(BuildContext context) async { - Navigator.push(context, MaterialPageRoute(builder: (context) => const OTP())); +void navigateToIssuancePreviewScreenAuthFlow(BuildContext context, Uri uri) async { + Navigator.push(context, MaterialPageRoute(builder: (context) => IssuancePreview(uri: uri))); } - -navigateToCredPreviewScreen( - BuildContext context, String credentialResp, String issuerURL, String resolvedCredentialDisplay, String didID, String credID) async { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - CredentialPreview(credentialData: CredentialData(rawCredential: credentialResp, issuerURL: issuerURL, credentialDisplayData: resolvedCredentialDisplay, credentialDID: didID, credID: credID)),)); -} - - -void navigateToAuthFlow(BuildContext context, Uri uri) async { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => HandleRedirectUri(uri, "issuer-initiated-flow", "") - )); -} \ No newline at end of file diff --git a/demo/app/lib/views/issuance_preview.dart b/demo/app/lib/views/issuance_preview.dart new file mode 100644 index 00000000..fd2e6afa --- /dev/null +++ b/demo/app/lib/views/issuance_preview.dart @@ -0,0 +1,253 @@ +/* +Copyright Gen Digital Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +import 'dart:convert'; +import 'dart:developer'; + +import 'package:app/main.dart'; +import 'package:app/views/dashboard.dart'; +import 'package:app/services/storage_service.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:app/widgets/common_title_appbar.dart'; +import 'package:app/widgets/primary_button.dart'; + +import 'package:app/models/activity_data_object.dart'; +import 'package:app/models/credential_data.dart'; +import 'package:app/wallet_sdk/wallet_sdk.dart'; +import 'credential_preview.dart'; +import 'handle_redirect_uri.dart'; +import 'otp.dart'; + +class IssuancePreview extends StatefulWidget { + bool? authorizeResultPinRequired; + Uri? uri; + + IssuancePreview({this.authorizeResultPinRequired, this.uri, Key? key}) : super(key: key); + + @override + State createState() => IssuancePreviewState(); +} + +class IssuancePreviewState extends State { + String issuerDisplayName = ""; + String credentialIssuer = ""; + String credentialDisplayName = ""; + String backgroundColor = ''; + String issuerDisplayURL = ''; + String textColor = ''; + String? logoURL; + + @override + void initState() { + super.initState(); + WalletSDKPlugin.getIssuerMetaData().then((response) { + setState(() { + credentialIssuer = response.first.credentialIssuer; + issuerDisplayName = response.first.localizedIssuerDisplays.first.name; + issuerDisplayURL = response.first.localizedIssuerDisplays.first.locale; + credentialDisplayName = response.first.supportedCredentials.first.display.first.name; + logoURL = response.first.supportedCredentials.first.display.first.logo; + backgroundColor = + '0xff${response.first.supportedCredentials.first.display.first.backgroundColor.toString().replaceAll('#', '')}'; + textColor = + '0xff${response.first.supportedCredentials.first.display.first.textColor.toString().replaceAll('#', '')}'; + }); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: const CustomTitleAppBar( + pageTitle: 'Issuance Preview', + addCloseIcon: true, + height: 60, + ), + body: Container( + padding: const EdgeInsets.fromLTRB(24, 40, 16, 24), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const SizedBox(height: 50), + const SizedBox( + child: Text( + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18, color: Colors.black), + "Add this credential ?"), + ), + const SizedBox(height: 30), + SizedBox( + height: 30, + child: Text( + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 24, color: Color(0xff190C21), fontWeight: FontWeight.bold), + issuerDisplayName), + ), + SizedBox( + height: 30, + child: Text( + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 12, color: Color(0xff190C21), fontWeight: FontWeight.normal), + issuerDisplayURL), + ), + const SizedBox(height: 20), + Container( + height: 80, + alignment: Alignment.center, + decoration: BoxDecoration( + color: backgroundColor.isNotEmpty ? Color(int.parse(backgroundColor)) : Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [BoxShadow(offset: const Offset(3, 3), color: Colors.grey.shade300, blurRadius: 5)]), + child: ListTile( + title: Text( + credentialDisplayName, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: textColor.isNotEmpty ? Color(int.parse(textColor)) : const Color(0xff190C21), + ), + textAlign: TextAlign.start, + ), + subtitle: Text( + credentialIssuer, + style: TextStyle( + fontSize: 6, + fontWeight: FontWeight.bold, + color: textColor.isNotEmpty ? Color(int.parse(textColor)) : const Color(0xff190C21), + ), + textAlign: TextAlign.start, + ), + leading: logoURL == null + ? const SizedBox.shrink() + : CachedNetworkImage( + imageUrl: logoURL!, + placeholder: (context, url) => const CircularProgressIndicator(), + errorWidget: (context, url, error) => + Image.asset('lib/assets/images/genericCredential.png', fit: BoxFit.contain), + width: 60, + height: 60, + fit: BoxFit.contain, + ), + )), + Expanded( + child: Align( + alignment: Alignment.bottomCenter, + child: Container( + height: 150, + padding: const EdgeInsets.all(16), + alignment: Alignment.topCenter, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: const Color(0xffDBD7DC), + width: 0.5, + ), + ), + child: Column( + children: [ + const Padding( + padding: EdgeInsets.fromLTRB(24, 0, 24, 0), + ), + PrimaryButton( + onPressed: () async { + if (widget.authorizeResultPinRequired == true) { + navigateToOTPScreen(context); + } else if (widget.uri != null) { + navigateToAuthFlow(context, widget.uri!); + } else { + navigateToWithoutPinFlow(context); + } + }, + width: double.infinity, + child: const Text('Add to Wallet', style: TextStyle(fontSize: 16, color: Colors.white))), + const Padding( + padding: EdgeInsets.fromLTRB(24, 0, 24, 8), + ), + PrimaryButton( + onPressed: () { + _navigateToDashboard(); + }, + width: double.infinity, + gradient: const LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xffFFFFFF), Color(0xffFFFFFF)]), + child: const Text('Cancel', style: TextStyle(fontSize: 16, color: Color(0xff6C6D7C))), + ), + ], + ), + ), //last one + ), + ), + ], + ), + ), + ); + } + + void navigateToOTPScreen(BuildContext context) async { + Navigator.push(context, MaterialPageRoute(builder: (context) => const OTP())); + } + + _navigateToDashboard() async { + Navigator.push(context, MaterialPageRoute(builder: (context) => const Dashboard())); + } + + void navigateToAuthFlow(BuildContext context, Uri uri) async { + Navigator.of(context) + .push(MaterialPageRoute(builder: (context) => HandleRedirectUri(uri, "issuer-initiated-flow", ""))); + } + + void navigateToWithoutPinFlow(BuildContext context) async { + var credentialData = await fetchPreviewScreenDetails(); + + Navigator.push(context, MaterialPageRoute(builder: (context) => CredentialPreview(credentialData: credentialData))); + } + + Future fetchPreviewScreenDetails() async { + final Future prefs = SharedPreferences.getInstance(); + var WalletSDKPlugin = WalletSDK(); + final StorageService storageService = StorageService(); + final SharedPreferences pref = await prefs; + + var didType = pref.getString('didType'); + var keyType = pref.getString('keyType'); + // choosing default if no selection is made + didType = didType ?? "ion"; + keyType = keyType ?? "ED25519"; + + var didResolution = await WalletSDKPlugin.createDID(didType, keyType); + var didDocEncoded = json.encode(didResolution); + Map responseJson = json.decode(didDocEncoded); + + var didID = responseJson["did"]; + var didDoc = responseJson["didDoc"]; + log("created didID :$didID"); + pref.setString('userDID', didID); + pref.setString('userDIDDoc', didDoc); + + String? credentials = await WalletSDKPlugin.requestCredential(''); + String? issuerURL = await WalletSDKPlugin.issuerURI(); + String? resolvedCredentialDisplay = await WalletSDKPlugin.serializeDisplayData([credentials], issuerURL!); + + var activities = await WalletSDKPlugin.storeActivityLogger(); + + var credID = await WalletSDKPlugin.getCredID([credentials]); + + log("activities and credID handle open id -$activities and $credID"); + storageService.addActivities(ActivityDataObj(credID!, activities)); + + return CredentialData( + rawCredential: credentials, + issuerURL: issuerURL, + credentialDisplayData: resolvedCredentialDisplay!, + credentialDID: didID, + credID: credID); + } +} diff --git a/demo/app/lib/views/supported_credentials_list.dart b/demo/app/lib/views/supported_credentials_list.dart index 35b16108..6395d78e 100644 --- a/demo/app/lib/views/supported_credentials_list.dart +++ b/demo/app/lib/views/supported_credentials_list.dart @@ -3,10 +3,6 @@ Copyright Gen Digital Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ - -import 'dart:developer'; - -import 'package:app/models/connect_issuer_config.dart'; import 'package:app/models/connect_issuer_config_value.dart'; import 'package:app/widgets/primary_button.dart'; import 'package:flutter/material.dart'; @@ -14,9 +10,6 @@ import 'package:flutter/material.dart'; import 'package:app/wallet_sdk/wallet_sdk_mobile.dart'; import 'package:app/wallet_sdk/wallet_sdk_model.dart'; import 'package:app/widgets/common_title_appbar.dart'; - -import 'package:app/services/config_service.dart'; - import 'handle_redirect_uri.dart'; class SupportedCredentialsList extends StatefulWidget { @@ -85,9 +78,6 @@ class SupportedCredentialsListState extends State { style: TextStyle(fontSize: 12, color: Colors.white), ), onPressed: () async { - log("scopes ${widget.connectIssuerConfigValue.scopes}"); - log("clientID ${widget.connectIssuerConfigValue.clientID}"); - log("redirectURI ${widget.connectIssuerConfigValue.redirectURI}"); var authorizationURL = await walletSDKPlugin.createAuthorizationURLWalletInitiatedFlow( widget.connectIssuerConfigValue.scopes, widget.supportedCredentialList.elementAt(index).types, diff --git a/demo/app/lib/wallet_sdk/wallet_sdk_js.dart b/demo/app/lib/wallet_sdk/wallet_sdk_js.dart index bc871942..9741027c 100644 --- a/demo/app/lib/wallet_sdk/wallet_sdk_js.dart +++ b/demo/app/lib/wallet_sdk/wallet_sdk_js.dart @@ -294,6 +294,10 @@ class WalletSDK extends WalletPlatform { return WellKnownDidConfig(isValid: jsConfig.isValid, serviceURL: jsConfig.serviceURL); } + Future> getIssuerMetaData() async { + return throw Exception('Method not implemented'); + } + Future getVerifierDisplayData() async { final data = await promiseToFuture(jsVerifierDisplayData()); return VerifierDisplayData(name: data.name, did: data.did, logoURI: data.logoURI, purpose: data.purpose); diff --git a/demo/app/lib/wallet_sdk/wallet_sdk_mobile.dart b/demo/app/lib/wallet_sdk/wallet_sdk_mobile.dart index 8f3a30d8..bf194d32 100644 --- a/demo/app/lib/wallet_sdk/wallet_sdk_mobile.dart +++ b/demo/app/lib/wallet_sdk/wallet_sdk_mobile.dart @@ -211,6 +211,12 @@ class WalletSDK extends WalletPlatform { return null; } + Future> getIssuerMetaData() async { + List getIssuerMetaDataResp = + await methodChannel.invokeMethod('getIssuerMetaData', {}); + return getIssuerMetaDataResp.map((d) => IssuerMetaData.fromMap(d.cast())).toList(); + } + Future getCredID(List credentials) async { try { final credentialID = diff --git a/demo/app/lib/wallet_sdk/wallet_sdk_model.dart b/demo/app/lib/wallet_sdk/wallet_sdk_model.dart index fe201073..acd98f27 100644 --- a/demo/app/lib/wallet_sdk/wallet_sdk_model.dart +++ b/demo/app/lib/wallet_sdk/wallet_sdk_model.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + class WellKnownDidConfig { final bool isValid; final String serviceURL; @@ -97,24 +99,152 @@ class InputDescriptor { } } +class IssuerMetaData { + final String credentialIssuer; + final List supportedCredentials; + final List localizedIssuerDisplays; + + const IssuerMetaData({ + required this.credentialIssuer, + required this.supportedCredentials, + required this.localizedIssuerDisplays, + }); + @override + String toString() { + return 'IssuerMetaData{ credentialIssuer: $credentialIssuer, supportedCredentials: $supportedCredentials, localizedIssuerDisplays: $localizedIssuerDisplays}'; + } + + Map toMap() { + return { + 'credentialIssuer': credentialIssuer, + 'supportedCredentials': supportedCredentials, + 'localizedIssuerDisplays': localizedIssuerDisplays + }; + } + + factory IssuerMetaData.fromJson(Map json) { + return IssuerMetaData( + credentialIssuer: json['credentialIssuer'], + supportedCredentials: json['supportedCredentials'], + localizedIssuerDisplays: json['localizedIssuerDisplays'], + ); + } + + factory IssuerMetaData.fromMap(Map map) { + return IssuerMetaData( + credentialIssuer: map['credentialIssuer'] as String, + supportedCredentials: (map['supportedCredentials'] as List) + .map((obj) => SupportedCredentials.fromMap(obj.cast())) + .toList(), + localizedIssuerDisplays: (map['localizedIssuerDisplays'] as List) + .map((obj) => IssuerDisplayData.fromMap(obj.cast())) + .toList(), + ); + } +} + class SupportedCredentials { final String format; final List types; + final List display; const SupportedCredentials({ required this.format, required this.types, + required this.display }); @override String toString() { - return 'SupportedCredentials{ format: $format, types: $types }'; + return 'SupportedCredentials{ format: $format, types: $types, display: $display }'; + } + + Map toMap() { + return { + 'format': format, + 'types': types, + 'display': display + }; } factory SupportedCredentials.fromMap(Map map) { + List display = map['display']; return SupportedCredentials( format: map['format'] as String, types: map['types'].cast(), + display: display.map((c) => SupportedCredentialDisplayData.fromMap(c.cast())).toList() + ); + } +} + +class SupportedCredentialDisplayData { + final String name; + final String locale; + final String logo; + final String textColor; + final String backgroundColor; + + const SupportedCredentialDisplayData({ + required this.name, + required this.locale, + required this.logo, + required this.textColor, + required this.backgroundColor, + }); + + @override + String toString() { + return 'SupportedCredentialDisplayData { name: $name, locale: $locale, logo: $logo, textColor: $textColor, backgroundColor: $backgroundColor }'; + } + + + Map toMap() { + return { + 'name': name, + 'locale': locale, + 'textColor': textColor, + 'logo': logo, + 'backgroundColor': backgroundColor + }; + } + + factory SupportedCredentialDisplayData.fromMap(Map map) { + return SupportedCredentialDisplayData( + name: map['name'] as String, + locale: map['locale'] as String, + logo: map['logo'] as String, + textColor: map['textColor'] as String, + backgroundColor: map['backgroundColor'] as String, + ); + } +} + +class IssuerDisplayData { + final String name; + final String locale; + + const IssuerDisplayData({ + required this.name, + required this.locale, + }); + + @override + String toString() { + return 'IssuerDisplayData { name: $name, locale: $locale }'; + } + + Map toMap() { + return { + 'name': name, + 'locale': locale, + }; + } + + + factory IssuerDisplayData.fromMap(Map map) { + return IssuerDisplayData( + name: map['name'] as String, + locale: map['locale'] as String, ); } } diff --git a/demo/app/pubspec.lock b/demo/app/pubspec.lock index 71a0fa9f..5f07d9d1 100644 --- a/demo/app/pubspec.lock +++ b/demo/app/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: archive - sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb" + sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" url: "https://pub.dev" source: hosted - version: "3.3.2" + version: "3.3.7" args: dependency: transitive description: @@ -81,14 +81,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.1" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" crypto: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" cupertino_icons: dependency: "direct main" description: @@ -283,10 +291,10 @@ packages: dependency: transitive description: name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.1" matcher: dependency: transitive description: @@ -347,10 +355,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" + sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.2.4" path_provider_linux: dependency: transitive description: @@ -363,10 +371,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84 url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.0" path_provider_windows: dependency: transitive description: @@ -395,18 +403,18 @@ packages: dependency: transitive description: name: permission_handler_apple - sha256: "7a187b671a39919462af2b5e813148365b71a615979165a119868d667fe90c03" + sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" url: "https://pub.dev" source: hosted - version: "9.1.3" + version: "9.1.4" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "79b36d93a41a4aecfd0d635d77552f327cb84227c718ce5e68b5f7b85546fe7e" + sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9" url: "https://pub.dev" source: hosted - version: "3.11.0+1" + version: "3.11.3" permission_handler_windows: dependency: transitive description: @@ -419,10 +427,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.4.0" platform: dependency: transitive description: @@ -435,10 +443,18 @@ packages: dependency: "direct main" description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" process: dependency: transitive description: @@ -491,10 +507,10 @@ packages: dependency: transitive description: name: shared_preferences_foundation - sha256: "0dc5c49ad8a05ed358b991b60c7b0ba1a14e16dae58af9b420d6b9e82dc024ab" + sha256: f39696b83e844923b642ce9dd4bd31736c17e697f6731a5adf445b1274cf3cd4 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.2" shared_preferences_linux: dependency: transitive description: @@ -544,18 +560,18 @@ packages: dependency: transitive description: name: sqflite - sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" url: "https://pub.dev" source: hosted - version: "2.2.8+4" + version: "2.3.0" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "8f7603f3f8f126740bc55c4ca2d1027aab4b74a1267a3e31ce51fe40e3b65b8f" + sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" url: "https://pub.dev" source: hosted - version: "2.4.5+1" + version: "2.5.0" stack_trace: dependency: transitive description: @@ -624,10 +640,10 @@ packages: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" uni_links: dependency: "direct main" description: @@ -656,18 +672,18 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e" url: "https://pub.dev" source: hosted - version: "6.1.11" + version: "6.1.12" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "15f5acbf0dce90146a0f5a2c4a002b1814a6303c4c5c075aa2623b2d16156f03" + sha256: "78cb6dea3e93148615109e58e42c35d1ffbf5ef66c44add673d0ab75f12ff3af" url: "https://pub.dev" source: hosted - version: "6.0.36" + version: "6.0.37" url_launcher_ios: dependency: transitive description: @@ -688,10 +704,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" url_launcher_platform_interface: dependency: transitive description: @@ -704,18 +720,18 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab" + sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4 url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.18" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" + sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422" url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.7" uuid: dependency: "direct main" description: @@ -752,26 +768,26 @@ packages: dependency: transitive description: name: win32 - sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0 url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "5.0.6" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" xml: dependency: transitive description: name: xml - sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.0" yaml: dependency: transitive description: @@ -781,5 +797,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0-0 <4.0.0" - flutter: ">=3.3.0" + dart: ">=3.0.0 <4.0.0" + flutter: ">=3.10.0"