Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactored to use bloc pattern to verify #16

Merged
merged 1 commit into from
Nov 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/bloc/initialize/initialize_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ class InitializeBloc extends Bloc<InitializeEvent, InitializeState> {
InitializeBloc() : super(Initial()) {
on<InitializeAppEvent>((event, emit) async{
emit(Initial());
await Future.delayed(const Duration(seconds: 3));
//await Future.delayed(const Duration(seconds: 3));

emit(CheckingInternetConnection());
await Future.delayed(const Duration(seconds: 3));
//await Future.delayed(const Duration(seconds: 3));

var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile || connectivityResult == ConnectivityResult.wifi) {
Expand Down
40 changes: 36 additions & 4 deletions lib/bloc/verify/verify_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,47 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';

import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';

import '../../services/secure_storage_service.dart';
import '../../services/user_contract_service.dart';

part 'verify_event.dart';
part 'verify_state.dart';

class VerifyBloc extends Bloc<VerifyEvent, VerifyState> {
VerifyBloc() : super(VerifyInitial()) {
on<VerifyEvent>((event, emit) {
// TODO: implement event handler
VerifyBloc() : super(Initial()) {
on<QRDetectedEvent>((event, emit) async{
try{
Map<String, dynamic> data = jsonDecode(event.qrCode.code!);
log(data.toString());
emit(QRDetected(data["verifier-name"], data["verifier-contract"], data["token"]));
}
catch(error){
log(error.toString());
emit(Failed("Invalid QR code!"));
}
});

on<Verify>((event, emit) async{
emit(Submitted());

try{
var contractService = UserContractService();
var contractAddress = await SecureStorageService.get("contract-address") as String;
var privateKey = await SecureStorageService.get("private-key") as String;
var transactionID = await contractService.verify(event.verifierContract, event.token, contractAddress: contractAddress, privateKey: privateKey);
log(transactionID);
emit(Verified());
}
catch(error){
emit(Failed(error.toString()));
}



});
}
}
11 changes: 11 additions & 0 deletions lib/bloc/verify/verify_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,14 @@ part of 'verify_bloc.dart';

@immutable
abstract class VerifyEvent {}

class QRDetectedEvent extends VerifyEvent{
final Barcode qrCode;
QRDetectedEvent(this.qrCode);
}
class Verify extends VerifyEvent{
final String verifierContract;
final String token;

Verify(this.verifierContract, this.token);
}
18 changes: 17 additions & 1 deletion lib/bloc/verify/verify_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,20 @@ part of 'verify_bloc.dart';
@immutable
abstract class VerifyState {}

class VerifyInitial extends VerifyState {}
class Initial extends VerifyState {}

class QRDetected extends VerifyState{
final String verifierName;
final String verifierContractAddress;
final String token;
QRDetected(this.verifierName, this.verifierContractAddress, this.token);
}

class Submitted extends VerifyState{}

class Verified extends VerifyState{}

class Failed extends VerifyState{
final String message;
Failed(this.message);
}
177 changes: 99 additions & 78 deletions lib/pages/qr_result_page.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:iblock/services/secure_storage_service.dart';
import 'package:iblock/services/user_contract_service.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';

import './error_page.dart';
import '../widgets/forms/button.dart';
import '../bloc/verify/verify_bloc.dart';

class QRResultPage extends StatefulWidget {
final Barcode result;
Expand All @@ -17,90 +14,114 @@ class QRResultPage extends StatefulWidget {
}

class _QRResultPageState extends State<QRResultPage> {
Map<String, dynamic> processQR(Barcode qr) {
Map<String, dynamic> data = jsonDecode(qr.code!);
return data;
final VerifyBloc _verifyBloc = VerifyBloc();

@override
void initState() {
super.initState();
_verifyBloc.add(QRDetectedEvent(widget.result));
}

@override
Widget build(BuildContext context) {
try {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: const Text('Requesting Information'),
),
body: SizedBox(
width: double.infinity,
child: Column(crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: MediaQuery.of(context).size.width >
MediaQuery.of(context).size.height
? 1
: 4,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
body:
BlocProvider(
create: (context) => _verifyBloc,
child: BlocConsumer<VerifyBloc, VerifyState>(
listener: (context, state){
if (state is Failed){
Navigator.popAndPushNamed(context, "/error", arguments: {"message": state.message});
}
},
buildWhen: (previous, current)=> previous != current && (current is QRDetected || current is Submitted),
builder: (context, state){
if(state is QRDetected){
return SizedBox(
width: double.infinity,
child: Column(crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: MediaQuery.of(context).size.width >
MediaQuery.of(context).size.height
? 1
: 4,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.6,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
const Expanded(
flex: 1,
child: Text(
"Following service provider request your approval for access your personal information")),
Expanded(
flex: 1,
child: Text(
state.verifierName,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20),
),
),
const Expanded(
flex: 3,
child: SizedBox(
width: 300,
child: Image(
image: AssetImage(
'assets/images/contract-agreement.png')),
),
),
],
),
),
),
)),
Expanded(flex: 1,
child: Column(crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(padding: const EdgeInsets.all(2.0),
child: Button("Approve", onPressed: () async{
_verifyBloc.add(Verify(state.verifierContractAddress, state.token));
},)),
Padding(padding: const EdgeInsets.all(2.0),
child: Button("Decline", onPressed: () {
Navigator.popUntil(
context, ModalRoute.withName("/home"));
}, color: Colors.red,)),
],),)
],),);
}
else if(state is Submitted){
return const Center(
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.6,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
const Expanded(
flex: 1,
child: Text(
"Following service provider request your approval for access your personal information")),
Expanded(
flex: 1,
child: Text(
processQR(widget.result)["verifier-name"],
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20),
),
),
const Expanded(
flex: 3,
child: SizedBox(
width: 300,
child: Image(
image: AssetImage(
'assets/images/contract-agreement.png')),
),
),
],
),
width: 40,
child: CircularProgressIndicator(),
),
),
)),
Expanded(flex: 1,
child: Column(crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(padding: const EdgeInsets.all(2.0),
child: Button("Approve", onPressed: () async{
var data = processQR(widget.result);
var contractService = UserContractService();
var contractAddress = await SecureStorageService.get("contract-address") as String;
var privateKey = await SecureStorageService.get("private-key") as String;
await contractService.verify(data['verifier-contract'], data['token'], contractAddress: contractAddress, privateKey: privateKey);
},)),
Padding(padding: const EdgeInsets.all(2.0),
child: Button("Decline", onPressed: () {
Navigator.popUntil(
context, ModalRoute.withName("/home"));
}, color: Colors.red,)),
],),)
],),)
// Center(
// child: Text(result.code != null ? 'Barcode Type: ${describeEnum(result.format)} Data: ${result.code}': 'No result'),
// ),
);
}
else{
return AlertDialog(
title: const Text("Error"),
content: const Text("Unexpected Error!"),
actions: [
TextButton(onPressed: (){
Navigator.pop(context);
},
child: const Text("Go Back"))
],);
}
},
),
)
),);
} catch(e){
print(e);
return const ErrorPage(
message: "QR code not recognized!",
);
}
}
}
17 changes: 4 additions & 13 deletions lib/services/user_contract_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ import '../config.dart';

class UserContractService{

late final Object _abiJSON;

UserContractService() {
_abiJSON = _getAbi();
}

Future<Map<String, String>> deploy({
required String name,
required String email,
Expand Down Expand Up @@ -45,7 +39,7 @@ class UserContractService{
}
}

Future<Object> _getAbi() async{
Future<Object> getAbi() async{
// get the abi from calling the application backend
final response = await http.get(Uri.parse("${Config.backendUrl}/contract"));
if(response.statusCode == 200){
Expand All @@ -62,7 +56,7 @@ class UserContractService{
EthPrivateKey credentials = EthPrivateKey.fromHex(privateKey);
EthereumAddress sender = await credentials.extractAddress();

Object abi = await _abiJSON;
Object abi = await getAbi();

DeployedContract smartContract = DeployedContract(ContractAbi.fromJson(jsonEncode(abi), "User"), contract);

Expand Down Expand Up @@ -124,7 +118,7 @@ class UserContractService{
EthereumAddress contract = EthereumAddress.fromHex(contractAddress);
EthPrivateKey credentials = EthPrivateKey.fromHex(privateKey);

Object abi = await _abiJSON;
Object abi = await getAbi();

DeployedContract smartContract = DeployedContract(ContractAbi.fromJson(jsonEncode(abi), "User"), contract);
ContractFunction setFunction = smartContract.function(setFunctionName);
Expand Down Expand Up @@ -170,7 +164,7 @@ class UserContractService{
EthereumAddress verifierContract = EthereumAddress.fromHex(verifierContractAddress);
EthPrivateKey credentials = EthPrivateKey.fromHex(privateKey);

Object abi = await _abiJSON;
Object abi = await getAbi();

DeployedContract smartContract = DeployedContract(ContractAbi.fromJson(jsonEncode(abi), "User"), contract);
ContractFunction verifyFunction = smartContract.function("verify");
Expand All @@ -194,7 +188,4 @@ class UserContractService{
}
}

Object getAbiJson() {
return _abiJSON;
}
}
2 changes: 1 addition & 1 deletion test/services/user_contract_service_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'package:test/test.dart';
void main(){
test('Testing for abi file', () async{
final service = UserContractService();
Object abi = await service.getAbiJson();
Object abi = await service.getAbi();
print(abi);
});

Expand Down