Skip to content

Commit

Permalink
Merge pull request #347 from famousj/develop
Browse files Browse the repository at this point in the history
Add support for public/private profiles in the example app
  • Loading branch information
plusema86 authored Nov 17, 2023
2 parents 79e6da3 + 475a7d7 commit c2b903b
Show file tree
Hide file tree
Showing 19 changed files with 265 additions and 72 deletions.
2 changes: 1 addition & 1 deletion example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Demonstrates how to use the polygonid_flutter_sdk plugin.
2. Run `flutter pub get` from example directory.
3. Run `build_runner` to generate `.g.dart` files:
```bash
flutter pub run build_runner build --delete-conflicting-outputs
dart run build_runner build --delete-conflicting-outputs
```
4. After the previous steps, build and run the project.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ Future<void> init() async {

void registerEnv() {
Map<String, dynamic> polygonMumbai = jsonDecode(Env.polygonMumbai);
List<EnvEntity> env = [
EnvEntity(
Map<String, dynamic> polygonMainnet = jsonDecode(Env.polygonMainnet);

Map<String, EnvEntity> env = {
"mumbai": EnvEntity(
blockchain: polygonMumbai['blockchain'],
network: polygonMumbai['network'],
web3Url: polygonMumbai['web3Url'],
Expand All @@ -49,13 +51,23 @@ void registerEnv() {
pushUrl: polygonMumbai['pushUrl'],
ipfsUrl: polygonMumbai['ipfsUrl'],
),
];
getIt.registerSingleton<List<EnvEntity>>(env);
"mainnet": EnvEntity(
blockchain: polygonMainnet['blockchain'],
network: polygonMainnet['network'],
web3Url: polygonMainnet['web3Url'],
web3RdpUrl: polygonMainnet['web3RdpUrl'],
web3ApiKey: polygonMainnet['web3ApiKey'],
idStateContract: polygonMainnet['idStateContract'],
pushUrl: polygonMainnet['pushUrl'],
ipfsUrl: polygonMainnet['ipfsUrl'],
)
};
getIt.registerSingleton<Map<String, EnvEntity>>(env);
}

///
Future<void> registerProviders() async {
await PolygonIdSdk.init(env: getIt<List<EnvEntity>>()[0]);
await PolygonIdSdk.init(env: getIt<Map<String, EnvEntity>>()["mumbai"]);
getIt.registerLazySingleton<PolygonIdSdk>(() => PolygonIdSdk.I);
}

Expand Down
23 changes: 23 additions & 0 deletions example/lib/src/presentation/ui/auth/auth_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
import 'dart:typed_data';

import 'package:bloc/bloc.dart';
import 'dart:math';
import 'package:polygonid_flutter_sdk/common/domain/domain_constants.dart';
import 'package:polygonid_flutter_sdk/common/domain/domain_logger.dart';
import 'package:polygonid_flutter_sdk/common/domain/entities/env_entity.dart';
import 'package:polygonid_flutter_sdk/iden3comm/domain/entities/common/iden3_message_entity.dart';
import 'package:polygonid_flutter_sdk/sdk/polygon_id_sdk.dart';
import 'package:polygonid_flutter_sdk_example/src/data/secure_storage.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/dependency_injection/dependencies_provider.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/auth/auth_event.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/auth/auth_state.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/common/widgets/profile_radio_button.dart';
import 'package:polygonid_flutter_sdk_example/utils/nonce_utils.dart';
import 'package:polygonid_flutter_sdk_example/utils/secure_storage_keys.dart';

class AuthBloc extends Bloc<AuthEvent, AuthState> {
final PolygonIdSdk _polygonIdSdk;

static const SelectedProfile _defaultProfile = SelectedProfile.public;
SelectedProfile selectedProfile = _defaultProfile;

AuthBloc(this._polygonIdSdk) : super(const AuthState.initial()) {
on<ClickScanQrCodeEvent>(_handleClickScanQrCode);
on<ScanQrCodeResponse>(_handleScanQrCodeResponse);
on<ProfileSelectedEvent>(_handleProfileSelected);
}

void _handleProfileSelected(
ProfileSelectedEvent event, Emitter<AuthState> emit) {
selectedProfile = event.profile;
emit(AuthState.profileSelected(event.profile));
}

///
Expand Down Expand Up @@ -73,10 +91,15 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
network: envEntity.network);

try {
final BigInt nonce = selectedProfile == SelectedProfile.public
? GENESIS_PROFILE_NONCE
: await NonceUtils(getIt()).getPrivateProfileNonce(
did: did, privateKey: privateKey, from: iden3message.from);
await _polygonIdSdk.iden3comm.authenticate(
message: iden3message,
genesisDid: did,
privateKey: privateKey,
profileNonce: nonce,
);

emit(const AuthState.authenticated());
Expand Down
3 changes: 3 additions & 0 deletions example/lib/src/presentation/ui/auth/auth_event.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/common/widgets/profile_radio_button.dart';

part 'auth_event.freezed.dart';

@freezed
class AuthEvent with _$AuthEvent {
const factory AuthEvent.profileSelected(SelectedProfile profile) =
ProfileSelectedEvent;
const factory AuthEvent.clickScanQrCode() = ClickScanQrCodeEvent;
const factory AuthEvent.onScanQrCodeResponse(String? response) =
ScanQrCodeResponse;
Expand Down
4 changes: 4 additions & 0 deletions example/lib/src/presentation/ui/auth/auth_state.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:polygonid_flutter_sdk/iden3comm/domain/entities/common/iden3_message_entity.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/common/widgets/profile_radio_button.dart';

part 'auth_state.freezed.dart';

Expand All @@ -9,6 +10,9 @@ class AuthState with _$AuthState {

const factory AuthState.loading() = LoadingAuthState;

const factory AuthState.profileSelected(SelectedProfile profile) =
ProfileSelectedAuthState;

const factory AuthState.navigateToQrCodeScanner() =
NavigateToQrCodeScannerAuthState;

Expand Down
43 changes: 28 additions & 15 deletions example/lib/src/presentation/ui/auth/widgets/auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:polygonid_flutter_sdk_example/src/presentation/ui/auth/auth_bloc
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/auth/auth_event.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/auth/auth_state.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/common/widgets/button_next_action.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/common/widgets/profile_radio_button.dart';
import 'package:polygonid_flutter_sdk_example/utils/custom_button_style.dart';
import 'package:polygonid_flutter_sdk_example/utils/custom_colors.dart';
import 'package:polygonid_flutter_sdk_example/utils/custom_strings.dart';
Expand Down Expand Up @@ -49,23 +50,22 @@ class _AuthScreenState extends State<AuthScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox(height: 50),
_buildDescription(),
const SizedBox(height: 24),
_buildProgress(),
const SizedBox(height: 24),
_buildAuthenticationSuccessSection(),
const SizedBox(height: 24),
_buildErrorSection(),
const SizedBox(height: 48),
],
),
SingleChildScrollView(
child: Column(
children: [
const SizedBox(height: 50),
_buildDescription(),
const SizedBox(height: 24),
_buildProgress(),
const SizedBox(height: 24),
_buildAuthenticationSuccessSection(),
const SizedBox(height: 24),
_buildErrorSection(),
const SizedBox(height: 48),
],
),
),
Expanded(child: _buildRadioButtons()),
Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Stack(
Expand Down Expand Up @@ -221,4 +221,17 @@ class _AuthScreenState extends State<AuthScreen> {
},
);
}

///
Widget _buildRadioButtons() {
void _selectProfile(SelectedProfile profile) {
widget._bloc.add(AuthEvent.profileSelected(profile));
}

return BlocBuilder(
bloc: widget._bloc,
builder: (BuildContext context, AuthState state) {
return ProfileRadio(widget._bloc.selectedProfile, _selectProfile);
});
}
}
11 changes: 10 additions & 1 deletion example/lib/src/presentation/ui/claims/claims_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'dart:async';

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:polygonid_flutter_sdk/common/domain/domain_constants.dart';
import 'package:polygonid_flutter_sdk/common/domain/domain_logger.dart';
import 'package:polygonid_flutter_sdk/common/domain/entities/env_entity.dart';
import 'package:polygonid_flutter_sdk/common/domain/entities/filter_entity.dart';
import 'package:polygonid_flutter_sdk/credential/domain/entities/claim_entity.dart';
Expand All @@ -14,6 +16,7 @@ import 'package:polygonid_flutter_sdk_example/src/presentation/ui/claims/claims_
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/claims/mappers/claim_model_mapper.dart';
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/claims/models/claim_model.dart';
import 'package:polygonid_flutter_sdk_example/utils/custom_strings.dart';
import 'package:polygonid_flutter_sdk_example/utils/nonce_utils.dart';
import 'package:polygonid_flutter_sdk_example/utils/secure_storage_keys.dart';

class ClaimsBloc extends Bloc<ClaimsEvent, ClaimsState> {
Expand Down Expand Up @@ -58,17 +61,23 @@ class ClaimsBloc extends Bloc<ClaimsEvent, ClaimsState> {
emit(const ClaimsState.loading());

Iden3MessageEntity iden3message = event.iden3message;

if (event.iden3message.messageType != Iden3MessageType.credentialOffer) {
emit(const ClaimsState.error("Read message is not of type offer"));
return;
}

BigInt nonce = await NonceUtils(_polygonIdSdk).lookupNonce(
did: didIdentifier,
privateKey: privateKey,
from: iden3message.from) ??
GENESIS_PROFILE_NONCE;

try {
List<ClaimEntity> claimList =
await _polygonIdSdk.iden3comm.fetchAndSaveClaims(
message: event.iden3message as OfferIden3MessageEntity,
genesisDid: didIdentifier,
profileNonce: nonce,
privateKey: privateKey,
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
import 'package:polygonid_flutter_sdk_example/utils/custom_colors.dart';
import 'package:polygonid_flutter_sdk_example/utils/custom_strings.dart';

enum SelectedProfile { public, private }

typedef ProfileCallback = void Function(SelectedProfile);

class ProfileRadio extends StatelessWidget {
const ProfileRadio(SelectedProfile profile, ProfileCallback profileCallback,
{Key? key})
: _profile = profile,
_profileCallback = profileCallback,
super(key: key);

final ProfileCallback _profileCallback;
final SelectedProfile? _profile;

@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
_makeRadioListTile(
CustomStrings.authPublicProfile, SelectedProfile.public),
_makeRadioListTile(
CustomStrings.authPrivateProfile, SelectedProfile.private),
],
);
}

Widget _makeRadioListTile(String text, SelectedProfile value) {
return RadioListTile(
title: Text(text),
value: value,
groupValue: _profile,
activeColor: CustomColors.primaryButton,
onChanged: (SelectedProfile? value) {
_profileCallback(value!);
});
}
}
3 changes: 2 additions & 1 deletion example/lib/src/presentation/ui/home/home_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:polygonid_flutter_sdk_example/src/presentation/ui/home/home_even
import 'package:polygonid_flutter_sdk_example/src/presentation/ui/home/home_state.dart';
import 'package:polygonid_flutter_sdk_example/utils/custom_strings.dart';
import 'package:polygonid_flutter_sdk_example/utils/secure_storage_keys.dart';
import 'package:polygonid_flutter_sdk/common/domain/domain_logger.dart';

class HomeBloc extends Bloc<HomeEvent, HomeState> {
final PolygonIdSdk _polygonIdSdk;
Expand Down Expand Up @@ -50,7 +51,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
try {
PrivateIdentityEntity identity =
await _polygonIdSdk.identity.addIdentity();
print("identity: ${identity.privateKey}");
logger().i("identity: ${identity.privateKey}");
await SecureStorage.write(
key: SecureStorageKeys.privateKey, value: identity.privateKey);
emit(HomeState.loaded(identifier: identity.did));
Expand Down
4 changes: 3 additions & 1 deletion example/lib/utils/custom_strings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class CustomStrings {
"You need to create an identity first";

// AUTH
static const String authPrivateProfile = "Private Profile";
static const String authPublicProfile = "Public Profile";
static const String authButtonCTA = "Connect";
static const String authDescription =
"Authenticate through verifier provider by scanning QR Code.\nIf you are already authenticated, you can skip this step";
Expand Down Expand Up @@ -45,7 +47,7 @@ class CustomStrings {

// ERROR
static const String genericError = "A generic error occurred, try again";
static const String iden3messageGenericError = "Error in the readed message";
static const String iden3messageGenericError = "Error in the read message";

// SIGN MESSAGE FEATURE CARD
static const String signMessageMethod = "identity.sign()";
Expand Down
Loading

0 comments on commit c2b903b

Please sign in to comment.